Quantcast
Channel: PowerShell – faq-o-matic.net
Viewing all 101 articles
Browse latest View live

SQL Server Express: Datensicherung über Powershell

$
0
0

Die SQL Express Edition erfreut sich gerade für kleine Anwendungen großer Beliebtheit, da sie keine Lizenzkosten verursacht. Diese Beliebtheit dürfte sogar noch steigen seit dem Microsoft mit dem Service Pack 1 für den SQL Server 2016 viele Funktionen der Standard und sogar Enterprise Edition nun auch in der Express Edition verfügbar macht. Nun stehen hier auch viele der In-Memory Features und Sicherheitsfunktionen wie AlwaysEncrypted auch in der Express Edition bereit. Informationen zu allen Neuerungen in der Express Edition findet man in der offiziellen Ankündigung unter https://blogs.msdn.microsoft.com/sqlreleaseservices/sql-server-2016-service-pack-1-sp1-released/

Der Agent

Etwas, was aber weiterhin nur eingeschränkt enthalten ist, ist der SQL Server Agent. Dadurch muss man sich Alternativen überlegen, wie man zeitgesteuerte Aufgaben abbilden kann. Dieser Umstand wird gerade für die Sicherungen der Datenbank zum Problem. Mit den Bordmitteln des SQL Server Express gibt es erstmal keine Möglichkeit seine Datenbanken automatisch zu sichern.

Bei der Suche im Internet findet man häufig die Vorgehensweise die Datenbank Datei direkt zu sichern indem man die mdf-Datei kopiert. Der Nachteil an dieser Methode ist aber, dass der SQL Server Dienst für den Zeitraum der Sicherung nicht laufen darf, da sonst die Datei(en) noch im Zugriff sind. Ein weiterer Nachteil ist zudem, dass man die Datenbank nur im Wiederherstellungsmodel „Einfach“ betreiben kann da eine Log Sicherung und damit das leeren des Transaktionslogs nicht möglich ist.

Alternative Powershell

Microsoft stellt aber mit der Powershell eine einfache Möglichkeit bereit wie man auch in der Express Edition seine Datenbanken sichern kann.

Hierfür braucht man lediglich ein kleines Powershell-Skript und den Aufgabenplaner von Windows, und fertig ist die Sicherungslösung. Hier habe ich ein Beispiel für ein solches Sicherungsskript erstellt.

<#—————————————————————–

Datensicherung von SQL Datenbanken über die Powershell

Autor Benjamin Hoch

Version 1.0 Datum: 12.12.2016

——————————————————————#>

# Variablen Definieren und Werte zuweisen

$Server= ‚SERVER' # Servername des Windows Servers

$Instanz= ‚INSTANZ' # Instanz Name des SQL Servers

$Zielpfad= ‚c:\temp\backup\' # Zielpfad der Sicherungsdateien

# Zeitstempel erzeugen

$date = Get-Date -Format o | foreach {$_ -replace ‚:', ‚.'}

# Auslesen aller Datenbanken außer TempDB und Variable zuweisen

$dbs= dir sqlserver:\sql\$Server\$Instanz\databases -force | Where-Object {$_.name -notlike ‚tempdb'}

# Backup Ordner erzeugen sofern nicht vorhanden

if(!(test-path $zielpfad)){New-Item $zielpfad -ItemType directory}

# Backup aller Datenbanken

$dbs | foreach-object {Backup-SqlDatabase -ServerInstance $server\$Instanz -Database $_.name -BackupFile $zielpfad\$_$date.bak"}

Das Skript sichert alle Datenbanken außer der TempDB in das angegebene Zielverzeichnis. Für jede Datenbank wird ein eigener Unterordner erstellt und jede Sicherungsdatei erhält einen eindeutigen Zeitstempel.

Das Skript speichert man ab und ruft es über den Aufgabenplaner von Windows im gewünschten Intervall auf.

Transaktionslog-Sicherung

Um eine Transaktionslog-Sicherung für eine bestimmte Datenbank durchzuführen, nutzt man einen zusätzlichen Parameter.

<#—————————————————————–

Logsicherung von einer SQL Datenbank über die Powershell

Autor Benjamin Hoch

Version 1.0 Datum: 12.12.2016

——————————————————————#> 

# Variablen Definieren und Werte zuweisen

$Server= ‚SERVER' # Servername des Windows Servers

$Instanz= ‚INSTANZ' # Instanz Name des SQL Servers

$Zielpfad= ‚c:\temp\backup\' # Ziel der Sicherung

$Datenbank =‚meinedb' 

# Zeitstempel erzeugen

$date = Get-Date -Format o | foreach {$_ -replace ‚:', ‚.'} 

Backup-SqlDatabase -ServerInstance $Server\$Instanz -Database $Datenbank -BackupAction Log -BackupFile $zielpfad\$datenbank$date.trn“ 

Aufgabe erstellen

Im Windows-Aufgabenplaner erstellt man nun eine neue Aufgabe für die Sicherung. Im Reiter „Aktionen“ wählt man „Programm starten“ aus und wählt als Programm die Powershell.exe aus. Diese findet man im typischerweise in folgendem Verzeichnis:

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe

Bei „Argumente hinzufügen“ gibt man nun den Pfad und den Namen des Powershell-Skriptes an, welches ausgeführt werden soll.

clip_image002

Fertig ist die Sicherung der SQL Server Datenbanken.

Es ist natürlich auch möglich, in derselben Aufgabe mehrere Aktionen zu planen. Hierdurch kann man in einer Aktion die tägliche/wöchentliche Vollsicherung aller Datenbanken planen und in einer anderen Aktion die stündliche Transaktionslog-Sicherung für eine bestimmte Datenbank.

Hinweis

Die Beispielskripte entfernen keine alten Sicherungen. Es ist daher notwendig die alten Sicherungen von Zeit zu Zeit händisch/automatisch zu löschen.

Die Skripte sind mit der Powershell 5 auf Windows Server 2012 R2 und 2016 mit SQL Express 2014 getestet.


PowerShell: Was ist eigentlich die ExecutionPolicy?

$
0
0

Wer nur gelegentlich mit der PowerShell arbeitet, stolpert oft über die ExecutionPolicy, die das Ausführen von Skripten (zunächst) verhindert. Was dahintersteckt, wissen aber auch PowerShell-Power-User (hihi) oft nicht genau.

Der PowerShell-Guru Tobias Weltner hat dies gut dargestellt und gibt auch einige Empfehlungen:

[Understanding Execution Policy]
http://www.powertheshell.com/understanding-execution-policy/

Hyper-V: Die Konfigurationsdatei einer VM finden

$
0
0

Hyper-V speichert die Konfiguration einer VM in einer Datei, die das System manchmal auch schlicht als “Virtueller Computer” bezeichnet. Bis Windows Server 2012 R2 handelte es sich dabei um eine XML-Datei, ab Windows Server 2016 ist es eine Binärdatei mit der Erweiterung VMCX.

Leider ist es nicht ganz einfach, den Speicherort dieser Datei ausfindig zu machen, denn in der grafischen Oberfläche zeigt Hyper-V ihn nirgends an. Wenn man beim Erzeugen der VM nicht aufmerksam ist, liegt sie u.U. an einem Ort, der nicht ganz offensichtlich ist. Wer etwa die Grundeinstellung von Hyper-V übernommen hat und beim Erzeugen einer VM nichts anderes angibt, speichert die VM-Konfigurationen unter C:\ProgramData\Microsoft\Windows\Hyper-V – schlauerweise kommt man an den Ordner nicht ohne Weiteres mit dem Explorer ran, weil dieser mit den Berechtigungen dort nicht umgehen kann.

Ein älterer Artikel beschreibt die Logik, nach der Hyper-V seine Dateien ablegt, sehr umfassend und (bis auf die Dateinamenerweiterungen) auch weiterhin zutreffend:

[Understanding where your virtual machine files are [Hyper-V] | Ben Armstrong’s Virtualization Blog]
https://blogs.msdn.microsoft.com/virtual_pc_guy/2010/03/10/understanding-where-your-virtual-machine-files-are-hyper-v/

Tatsächlich gibt es eine relativ einfache Möglichkeit, die Konfigurationsdatei zu finden – aber nur in der PowerShell. Dort ist der Ordnerpfad über das Cmdlet Get-VM im Attribut ConfigurationLocation zu finden. Der eigentliche Dateiname entspricht dann der GUID der VM plus Erweiterung.

Äh – sagte ich “relativ einfach”? Smiley mit geöffnetem Mund

Das folgende PowerShell-Skript zeigt den vollen Pfad an, wenn man ihm den Namen der VM gibt. Man führt das Skript direkt auf dem Host aus.

$VMName = Read-Host 'Enter VM name'
# get VM data
$VMData = Get-VM $VMName -ErrorAction SilentlyContinue
if (!$VMData) {
"VM $VMName not found."
Return
}
# get config details
$VMConfLoc = $VMData.ConfigurationLocation
$VMGUID = $VMData.VMId
$VMVer = $VMData.Version
# select file name extension: XML until version 5.0, VMCX later
"VM $VMName version is: $VMVer"
if ($VMVer -ge '6.0') {
$VMConfExt = 'vmcx'
} else {
$VMConfExt = 'xml'
}
# create full VM config file path
$VMConfDefPath = $VMConfLoc + '\Virtual Machines\' + $VMGUID + '.' + $VMConfExt
# check if the file exists
$CheckDefPath = Get-Item $VMConfDefPath -ErrorAction SilentlyContinue
if ($CheckDefPath) {
"VM configuration file is: $VMConfDefPath"
} else {
"VM configuration file for $VMName not found."
}

ADFS: Den Systemzustand per PowerShell prüfen

$
0
0

Microsoft hat in der TechNet Gallery ein hilfreiches PowerShell-Modul veröffentlicht, das den Zustand einer ADFS-Installation überprüft. Es handelt sich um dieselbe Komponente, die auch innerhalb von Azure eingesetzt wird. Der folgende Blogbeitrag gibt einen Überblick:

[Under the hood tour of Azure AD Connect Health: AD FS Diagnostics Module &#8211; Azure AD Customer Experience Engineering Team]
https://blogs.technet.microsoft.com/aadceeteam/2015/02/13/under-the-hood-tour-of-azure-ad-connect-health-ad-fs-diagnostics-module/

Hier ist der Download:

[Skript AD FS Diagnostics Module]
https://gallery.technet.microsoft.com/scriptcenter/AD-FS-Diagnostics-Module-8269de31

Get-HyperVInventory: Neue Version mit 2016-Details

$
0
0

Das erfolgreiche Dokumentationsskript für Hyper-V gibt es jetzt in einer neuen Version. Get-HyperVInventory.ps1 berücksichtigt nun auch die wichtigsten neuen Funktionen von Windows Server 2016.

Das PowerShell-Skript erzeugt vollautomatische Konfigurations-Reports für Hyper-V-Umgebungen. Es umfasst dabei die Hostserver, die virtuellen Maschinen und, soweit vorhanden, die Failover-Cluster-Funktionen. Die Reports liegen als HTML-Dateien vor und sind so einfach nutzbar und gut weiterzuverwenden. Das Werkzeug eignet sich für Hyper-V-Infrastrukturen mit Windows Server 2012, 2012 R2 und 2016 sowie für Client-Hyper-V mit Windows 8, 8.1 und 10.

Neu in Version 2.4:

  • Funktionen von Windows Server 2016 wie Shielded VMs, Checkpoint-Typen, VM-Gruppen
  • Storage-Konfiguration für Storage Spaces Direct (S2D), Virtual Fibre Channel, iSCSI und lokalen Speicher
  • Signierte Skript-Version (optional) stellt sicher, dass das Skript im Originalzustand ist

Get-HyperVInventory.ps1 steht wie immer kostenlos in der TechNet Gallery zur Verfügung. Eine umfassende Online-Hilfe und Parameterhinweise sind vorhanden.

[TechNet Get-HyperVInventory: Create inventory reports of Hyper-V environments]
https://gallery.technet.microsoft.com/Get-HyperVInventory-Create-2c368c50

Virtuelle Festplatten in Hyper-V-VM-Notizen aufführen

$
0
0

In meinem Testlab verzichte ich bisweilen auf bestimmte Best Practices. So kommt es vor, dass ich virtuelle Festplatten von Hyper-V-VMs einfach “irgendwo” ablege. Ebenso lege ich oft VMs ohne Platte an, weil ich nur eine Hülle brauche.

Der Nachteil daran ist, dass ich beim Starten einer VM manchmal erst zu spät feststelle, dass diese gar nicht lauffähig ist. Als kleine Gedankenstütze habe ich mir daher ein Skript gebaut, das die Konfiguration der virtuellen Platten in die Notizen der VM schreibt, sodass der Hyper-V-Manager diese Informationen im Infobereich gleich anzeigen kann.

$VMs = (Get-VM)
foreach ($VM in $VMs) {
     $Drives = Get-VMHardDiskDrive -VM $VM | Sort-Object -Property @{Expression = 'ControllerNumber'; Descending = $true}, @{Expression = 'ControllerLocation'; Descending = $true}
     $Notes = $VM.Notes
     if ($Drives -ne $null) {
         foreach ($Drive in $Drives) {
             $Notes = $Drive.Path + "`r`n" + $Notes
             Set-VM $VM -Notes $Notes
         }
     }
}
Note: There is a file embedded within this post, please visit this post to download the file.

Hyper-V-VM als Vorlage ex- und importieren

$
0
0

Hyper-V bringt kein System zum Verwalten von VM-Vorlagen mit. Mit separaten Produkten (z.B. System Center Virtual Machine Manager oder 5Nine Manager) lässt sich so eine Funktion ergänzen. Man kann sie aber für “kleine Zwecke” auch mit Bordmitteln ersetzen.

Viele Admins behelfen sich, indem sie einfach den wichtigsten Teil einer VM als Basis-Vorlage speichern, nämlich die virtuelle Festplatte. Der Weg ist simpel: Man installiert eine VM und konfiguriert das Gast-Betriebssystem so, wie man es braucht. Als letzten Schritt führt man sysprep aus, beendet die VM und legt die VHD(X)-Datei schreibgeschützt an eine separate Stelle. Die VM kann man dann löschen (oder gleich als erste neue VM auf Basis der Vorlage verwenden). Braucht man nun eine VM auf Grundlage des erzeugten Templates, so definiert man eine neue VM und kopiert die Vorlagen-VHDX an die passende Stelle.

Dies lässt sich noch erweitern, indem man auch die eigentliche VM als Vorlage speichert. Dadurch hat man dann auch gleich die virtuelle Hardware vordefiniert und spart sich den manuellen Schritt, die VM-Hülle neu einzurichten. Dabei hilft eine Funktion, die es schon seit der ersten Hyper-V-Version von Windows Server 2008 gibt, die seit einigen Jahren aber in Vergessenheit geraten ist. Hyper-V ermöglicht nämlich den VM-Export ohne virtuelle Festplatte, also nur die Konfiguration der VM. Früher gab es diese Funktion im grafischen Hyper-V Manager, doch seit einigen Jahren ist sie nur noch programmatisch erreichbar.

Hier kommt eine PowerShell-Lösung ins Spiel, die ich im Folgenden vorstelle.

Der folgende Artikel im TechNet-Wiki beschreibt, wie man eine Hyper-V-VM “config-only” exportiert. Das dortige Skript nutzt WMI, um diesen Export auszuführen.

[Hyper-V: Export VM Config-Only Using PowerShell – TechNet Articles – United States (English) – TechNet Wiki]
https://social.technet.microsoft.com/wiki/contents/articles/1350.hyper-v-export-vm-config-only-using-powershell.aspx

Ich habe das Skript etwas erweitert, um es komfortabler zu machen:

#################
# Export-VMConfigOnly.ps1
# exports only a VM's configuration without the virtual hard disk files
# based on http://social.technet.microsoft.com/wiki/contents/articles/1350.hyper-v-export-vm-config-only-using-powershell.aspx
# Nils Kaczenski, faq-o-matic.net, 2016-12-21
#################

$SourceVM = Read-Host 'Specify the name of the VM to export'
$expDir = Read-Host 'Specify the target root path for the export (VM name will be appended)'

$ns = 'root\virtualization\v2'

$expDir = $expDir + $SourceVM
if( -Not (Test-Path -Path $expDir ) )
{
    New-Item -ItemType directory -Path $expDir | Out-Null
}

#Get VM Object
$vm = gwmi -n $ns Msvm_ComputerSystem | ?{$_.ElementName -eq $SourceVM}

#Get export setting object
$exp = @($vm.GetRelated('Msvm_VirtualSystemExportSettingData'))[0]

#If you dont want to copy the VHDs and AVHDs
$exp.CopyVmStorage = $false

#If you dont want to copy the Saved state
$exp.CopyVmRuntimeInformation = $false

#Get VMMS object
$vmms = gwmi -n $ns Msvm_VirtualSystemManagementService

#Perform Export
$out = $vmms.ExportSystemDefinition($vm.Path.Path, $expDir, $exp.GetText(1))

#Perform Job handling if necessary
if ($out.ReturnValue -eq 4096)
{
       $task = [Wmi]$out.Job;
       while($task.JobState -eq 3 -or $task.JobState -eq 4)
       {
              $task.Get();
              sleep 1;
       }
       if ($task.JobState -ne 7)
       {
              "Error exporting VM " + $task.ErrorDescription;
       }
       else
       {
              "Export completed successfully..."
       }

}
elseif ($out.ReturnValue -ne 0)
{
       "Export failed with error : " + $out.ReturnValue;
}
else
{
       "Export completed successfully."
}

Skript: Export-VMConfigOnly.ps1, exportiert nur die Konfiguration einer VM

Den so erzeugten Export kann man nun als VM-Vorlage verwenden. Um auch diesen Vorgang komfortabler zu machen, habe ich ein zweites Skript gebaut. Es fragt nach der Konfigurationsdatei der Vorlage und nach dem Namen für die neue VM. Die Vorlage selbst muss man nicht über den oben gezeigten Export erzeugen, prinzipiell eignet sich auch eine vorhandene oder eine schlicht kopierte VM. Der Kniff besteht nun darin, dass das Skript prüft, ob zu der angegebenen Vorlagen-VM virtuelle Festplatten gehören. Ist dies nicht der Fall, so entfernt es aus der neuen VM die Verweise auf die VHD(X)-Dateien, sodass die reine Hülle übrig bleibt. Im letzten Schritt kopiert man nun die Sysprep-VHD(X)-Dateien an die passende Stelle und bindet sie in die VM ein.

#############
# Import-VMFromTemplate.ps1
# Imports a VM by copying the original data and renaming the object afterwards
# thus, the original VM (which may have been exported) serves as a template
# if the export folder does not contain VHD or VHDX files all disks will be removed from the imported VM!
# Nils Kaczenski, faq-o-matic.net, 2016-12-21
#############

$SourceVM = Read-Host 'Enter the path of the source VM config file (XML or VMCX)'
$SourceVM = $SourceVM.Replace('"','') # remove quotes as Test-Path doesn't like them
if( -Not (Test-Path -PathType Leaf $SourceVM) )
{
    'File not found. Exiting script.'
    return
}

$TargetVMName = Read-Host 'Enter the name of the new VM to be created'
$TargetVMPath = Read-Host 'Enter the root path to store the new VM (VM name will be appended)'
$TargetVMPath = $TargetVMPath + '\' + $TargetVMName

# create the target folder if it does not exist
if( -Not (Test-Path -Path $TargetVMPath ) )
{
    New-Item -ItemType directory -Path $TargetVMPath | Out-Null
}


$NewVM = Import-VM -Path $SourceVM -Copy -VirtualMachinePath $TargetVMPath -GenerateNewId
Rename-VM $NewVM -NewName $TargetVMName
"VM imported as $NewVM"

# check if the export contains Virtual Hard Disks
$SourceVHDPath = (Get-Item $SourceVM).Directory.Parent.FullName + '\Virtual Hard Disks\*.vhd*'
if (!(Test-Path $SourceVHDPath)) {
    # no, it does not - thus remove VHD bindings from the VM
    Get-VMHardDiskDrive $NewVM | Remove-VMHardDiskDrive
    'VM virtual hard disks have been removed as there were none in the export data.'
}

$NewVM | fl *

Skript: Import-VMFromTemplate.ps1, importiert die Konfiguration einer VM

Hier der Download:

Note: There is a file embedded within this post, please visit this post to download the file.

PowerShell ISE Presenter

$
0
0

Ein sehr spezielles Tool hat der schweizerische IT-Trainer Claudio Spizzi veröffentlicht. Der PowerShell ISE Presenter klinkt sich als Add-on in die Windows-eigene PowerShell-Oberfläche ein und unterstützt dafür einen Präsentationsmodus. Mit der Tastatur oder auch mit einer Präsentations-Fernbedienung kann man Befehl für Befehl durch ein Skript gehen und einzelne Zeilen ausführen.

PowerShell ISEPresenter

[PowerShell ISE Presenter – Claudio Spizzi]
https://spizzi.net/2016/10/18/powershell-ise-presenter/


Hyper-V-VMs zu Demozwecken erzeugen

$
0
0

Um in Hyper-V-Laborumgebungen Dinge zu entwickeln oder zu demonstrieren, brauche ich manchmal einfach eine Anzahl “ganz kleiner” VMs. Meist reichen dabei Hüllen aus – nur die VM-Konfiguration, aber kein installiertes Betriebssystem. So eine VM kann man dann konfigurieren, starten und beenden, auch wenn sie nichts Sinnvolles macht.

Das folgende Skript erzeugt in einem Rutsch solche VM-Hüllen. In der Variablen $VMPrefix legt es die Namen der VMs fest, die dann numerisch hochgezählt werden (mit diesen einheitlichen Namen kann man dann die VMs auch schnell wieder löschen). Die Angabe $VMCount enthält die Anzahl der VM-Hüllen. Die Konfigurationsdateien legt Hyper-V im Standardpfad für VMs ab.

$VMPrefix = 'BlankVM-'
$VMCount = 15
$Counter = 1
while ($Counter -le $VMCount) {
  $Number = $Counter.ToString().PadLeft(2, '0')
  New-VM -Name ($VMPrefix + $Number) -MemoryStartupBytes 32MB -NoVHD
  $Counter += 1
}

Hier der Download:

Note: There is a file embedded within this post, please visit this post to download the file.

image

SQL Server: E-Mail-Benachrichtigungen per PowerShell einrichten

$
0
0

Wie sonst auch in der IT ist ein Datenbankserver nicht frei von Fehlern oder Problemen. Um schnell auf Fehler reagieren zu können, ist es notwendig, schnell über Störungen des Betriebs informiert zu werden. Innerhalb des SQL Servers übernimmt der SQL Server Agent (nicht in der Express Edition vorhanden) diese Aufgabe.

Vorbereitungen

Damit der SQL Server Agent Benachrichtigungen versenden kann, muss “Datenbank-Mail” eingerichtet sein. Weitere Informationen zu Einrichtung von Datenbank-Mail findet man im Technet unter https://technet.microsoft.com/de-de/library/ms175887(v=sql.105).aspx. Ich plane auch zum Thema “Einrichtung von Datenbank-Mail über Powershell” noch einen Beitrag.

Des Weiteren muss der SQL Server Agent gestartet sein (Dienst-Starttyp Automatisch) und für den Mailversand vorbereitet. https://msdn.microsoft.com/de-de/library/ms186358.aspx

Verbindungsaufbau

Zunächst muss ein Verbindungsobjekt zur SQL-Server-Instanz angelegt werden. Hier sind die Unterschiede zwischen der Standardinstanz und einer benannten Instanz zu beachten.

Import-module sqlps -DisableNameChecking

# Herstellen der Verbindung zum SQL Server

$sqlServer = 'SERVERNAME\INSTANZNAME' # bei benannten Instanzen
$sqlServer = 'SERVERNAME' # Bei der Standardinstanz
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$server = New-Object 'Microsoft.SqlServer.Management.SMO.Server' ($sqlServer)
$Job = $server.JobServer

Anlegen eines Operators

Operatoren sind im SQL Server Platzhalter für einzelne Personen oder Gruppen, an die Benachrichtigungen gesendet werden können. Für jeden Operator kann man definieren, für welche Aufträge und Fehler eine Benachrichtigung erfolgen soll. Hier soll nun ein Operator mit dem Namen MeinName erstellt werden.

$Name = "MeinName"
$Mail = "Mein.Name@Test-adresse.de"
$operator = New-Object Microsoft.SqlServer.Management.Smo.Agent.Operator -ArgumentList $Job, $Name
$operator.EmailAddress = $Mail
$operator.Create()

Wenn man mehrere Operatoren erstellen möchte, kann man den Codeabschnitt mehrfach hintereinander mit verschiedenen Werten für $Name und $Mail ausführen.

Warnungen erstellen

Damit ein Operator auch Benachrichtigungen zu Fehlern oder Störungen erhalten kann, müssen hierfür zunächst die gewünschten Warnungen einmalig erstellt werden. Im Beispiel werden für die Fehlerschweregrade 17 – 25 und für die Fehlernummern 823 – 825 die entsprechenden Warnungen angelegt.

for($i=17; $i -le 25;$i++)
{
    if(!($Job.Alerts.Contains("Fehler Level $i")))
    {
        $Warnung = New-Object Microsoft.SqlServer.Management.Smo.Agent.Alert -ArgumentList $Job, "Fehler Level $i"
        $Warnung.Severity = $i
        $Warnung.IsEnabled
        $Warnung.Create()
        Write-Host -ForegroundColor Green "Warnung Fehler Level $i angelegt"
    }
  }
if(!($Job.Alerts.Contains("823")))
{
      $Warnung = New-Object Microsoft.SqlServer.Management.Smo.Agent.Alert -ArgumentList $Job, "823"
      $Warnung.MessageID = "823"
      $Warnung.IsEnabled
      $Warnung.Create()
      Write-Host -ForegroundColor Green "Warnung 823 angelegt"
}
if(!($Job.Alerts.Contains("824")))
{
      $Warnung = New-Object Microsoft.SqlServer.Management.Smo.Agent.Alert -ArgumentList $Job, "824"
      $Warnung.MessageID = "824"
      $Warnung.IsEnabled
      $Warnung.Create()
      Write-Host -ForegroundColor Green "Warnung 824 angelegt"
}
if(!($Job.Alerts.Contains("825")))
{
      $Warnung = New-Object Microsoft.SqlServer.Management.Smo.Agent.Alert -ArgumentList $Job, "825"
      $Warnung.MessageID = "825"
      $Warnung.IsEnabled
      $Warnung.Create()
      Write-Host -ForegroundColor Green "Warnung 825 angelegt"
}

Operator mit Warnungen „verheiraten“

Nachdem man nun den Operator erstellt hat und alle Warnungen angelegt sind, muss man nur noch definieren, für welche Warnungen der Operator eine E-Mail bekommen soll. Im Beispiel sollen alle vorhandenen Operatoren für alle erstellten Warnungen eine Benachrichtigung erhalten. Dies lässt sich in der PowerShell sehr einfach über zwei Foreach-Schleifen realisieren.

# Auslesen aller vorhandenen Warnungen und Operatoren
$Alarme = $job.Alerts
$Operatoren = $Job.Operators

# Verbinden von allen Warnungen mit allen Operatoren

foreach($Operator in $Operatoren)
{
    foreach($Alarm in $Alarme)
    {
       $Alarm.AddNotification($Operator.Name,[Microsoft.SqlServer.Management.Smo.Agent.NotifyMethods]::NotifyEmail)
       Write-Host -ForegroundColor Green "Warung $alarm mit $operator verbunden"
    }
}

Wenn schon Verbindungen zwischen Operator und Warnung bestehen, wird ein Fehler ausgelöst. Dieser Fehler beeinflusst aber die weitere Funktion des Skripts aber nicht. Aus Gründen der besseren Lesbarkeit habe ich hier auf eine entsprechende Fehlerbehandlung verzichtet.

Das Skript wurde mit PowerShell 5 auf Windows Server 2012 R2 und Windows Server 2016 gegen SQL Server 2012, 2014 und 2016 getestet.

Just Enough Administration: Material von der CDC Germany 2017

$
0
0

Auf der Cloud & Datacenter Conference Germany 2017 hatte ich die Ehre, vor großem Publikum die neue Sicherheitstechnik “Just Enough Administration” am Beispiel von Hyper-V vorzustellen. Hier ist ein wenig Material dazu.

Just Enough Administraion (oder JEA) ist ein neuartiges Berechtigungskonzept für zahlreiche Dienste und Applikationen. Anders als herkömmliche Verfahren setzt es nicht auf Objektberechtigungen auf, die innerhalb einer Anwendung definiert sein müssen, sondern es steuert das Ausführen administrativer Tätigkeiten über die PowerShell. Damit ermöglicht es JEA, sehr zielgerichtet Verwaltungszugriffe auf eine Applikation festzulegen, sodass Administratoren nicht mehr “allmächtig” sein müssen.

Am Beispiel von Hyper-V in Windows Server 2016 habe ich gezeigt, wie man JEA einsetzen kann, um Helpdesk-Mitarbeitern eng abgegrenzte Zugriffsrechte auf die Virtualisierungsumgebung zu erteilen. Von Haus aus unterscheidet Hyper-V (nur noch) Administratoren und den Rest der Welt. Ein Admin kann so alles oder gar nichts – das ist nicht eben unternehmenstauglich. Durch JEA lassen sich Szenarien wie die folgenden (relativ) leicht umsetzen:

  • Der Helpdesk soll bestimmte VMs starten, beenden und auflisten können, sonst aber die Host-Umgebung nicht manipulieren dürfen
  • Die Softwareentwickler sollen auf bestimmten Hosts neue VMs mit bestimmten Parametern erzeugen können und ihre eigenen VMs dann steuern – mehr nicht
  • JEA kann alles steuern, was PowerShell spricht, also soll die Ausbildungsleitung die AD-Konten von Azubis bearbeiten können, aber keine anderen

Eine gute Einführung in JEA gibt es hier:

[Übersicht über Just Enough Administration]
https://msdn.microsoft.com/powershell/jea/overview

Auf dieser Basis habe ich für meine Demo einige Skripts entwickelt, die das Prinzip demonstrieren:

  • Konfigurationsdateien für den JEA-Endpunkt
  • Skripte, die JEA in Aktion zeigen
  • Ein grafisches Werkzeug, das JEA einsetzt, um dem Helpdesk die oben skizzierten Aktionen zu ermöglichen, ohne dass die PowerShell nötig wird

Hier finden sich die Skripte und die CDC-Präsentation zum Download:

Note: There is a file embedded within this post, please visit this post to download the file.

Eine umfassende Einführung in JEA gibt es auch in dem Buch “Microsoft Hyper-V”, das vor wenigen Tagen in neuer Auflage im Rheinwerk Verlag erschienen ist.

Eine Wortliste aus einem Text erzeugen

$
0
0

Für unseren Kennwortgenerator “Schwester-Pelzhut-Ledersofa-Auch” brauchen wir eine Liste eindeutiger Wörter. Der Einfachheit halber habe ich dafür einen vorhandenen Text genommen, der ohne Lizenzkosten zur Verfügung steht. Meine Wahl fiel auf Franz Kafkas “Verwandlung”. Da Kafka vor mehr als 70 Jahren gestorben ist, sind die Einschränkungen des Urheberrechts erloschen, man darf den Text also “einfach so” verwenden.

Nun ist der reine Text als Liste noch nicht gut geeignet, denn viele Wörter wiederholen sich. Das sind naturgemäß vor allem Trivialwörter wie Artikel oder einfache Adjektive. Ich brauchte also eine Funktion, die aus dem Text eine Wortliste macht, in dem jedes Wort nur einmal auftaucht. Das ging mit der PowerShell recht einfach.

$WordListFile =  'C:\Daten\Kafka-Verwandlung.txt'
$WordList = Get-Content $WordListFile
$WordArray = $WordList.Split(' ')
$WordArrayUnique = @()
foreach ($Word in $WordArray) {
  $WordTrim = ($Word -replace '[\W]', '')
  $WordArrayUnique +=$WordTrim
}

$WordArrayUnique = ($WordArrayUnique | Sort-Object -Unique) # | Measure-Object
$WordArrayUnique -join(',') | Out-File 'C:\Daten\Wortliste-Kafka-Verwandlung.txt'

Das Skript öffnet eine Textdatei, das die vollständige Textquelle enthält, und liest den gesamten Text ein. Um die einzelnen Wörter zu erhalten, trennt es den Text jeweils bei einem Leerzeichen und schreibt die so entstandenen Fragmente in ein Array. Dieses Array durchläuft dann eine Schleife mit einem Regulären Ausdruck, der alle Zeichen entfernt, die nicht zu einem Wort gehören (etwa Satzzeichen). Abschließend ordnet die vorletzte Zeile das Array alphabetisch und entfernt dabei alle Dopplungen. Das so verbleibende Array mit eindeutigen Wörtern schreibt die letzte Zeile dann in die Zieldatei.

Wer wissen möchte, wie viele eindeutige Wörter so entstanden sind, entfernt das Kommentarzeichen in der vorletzten Zeile und kommentiert die letzte Zeile aus.

PowerShell-Remoting und Gruppenmitgliedschaften

$
0
0

In einer Kundenumgebung stieß ich gerade auf ein Problem beim PowerShell-Remoting: Es kam zwischen Client und Server keine Verbindung zustande. Nachdem ich die Lösung gefunden hatte, stellte ich fest, dass das Problem ein alter Bekannter war. Aber der Reihe nach.

Ein Skript versuchte, eine PS-Remoting-Session aufzubauen. Dies schlug fehl mit folgenden Fehlermeldungen:

New-PSSession : [SRV01] Connecting to remote server SRV01 failed with the following error message : The WinRM client cannot process the request. It cannot
determine the content type of the HTTP response from the destination computer. The content type is absent or invalid. For more information, see the
about_Remote_Troubleshooting Help topic.
At C:\Daten\Skript.ps1:35 char:12
+ $session = New-PSSession -ComputerName $Server
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
    + FullyQualifiedErrorId : -2144108297,PSSessionOpenFailed

Die typischen Verdächtigen – Namensauflösung, Firewall, WinRM nicht gestartet – waren nicht Schuld. Ein wenig Recherche führte aber zum Ziel. Tatsächlich war der Account, der die Verbindung aufbauen wollte, in sehr vielen Gruppen Mitglied. Das kann bei HTTP-Zugriffen problematisch sein, weil der HTTP-Dienst eine Größenbegrenzung für Datenpakete hat, die vom Access Token leicht überschritten wird. Hier kann es helfen, die Limits hochzusetzen. Dazu startet man auf dem Ziel-Rechner den Registry-Editor als Administrator und setzt folgende Keys:

  • unter HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
  • neuer DWORD (falls noch nicht vorhanden): MaxFieldLength, Wert (dezimal) z.B. 40000
  • neuer DWORD (falls noch nicht vorhanden): MaxRequestBytes, Wert (dezimal) 32768

Den Server neu starten. Dann funktionierte es in meinem Fall.

PowerShell Saturday: 26. August 2017 in Hannover

$
0
0

Der PowerShell Saturday am 26.08.2017 ist ein ganzer Tag, der nur Themen rund um unsere Lieblingsshell gewidmet ist. An diesem Tag soll die PowerShell einem größeren Publikum bekannt gemacht werden. Dazu ist jeder herzlich eingeladen, der die PowerShell kennt oder sie einfach mal kennenlernen möchte. Mit dabei sind z.B. der Powershell-MVP Dr. Tobias Weltner, Peter Kirchner von Microsoft, MCT und Buchautor Thorsten Butz und die Powershell Usergroup Hannover.

Die komplette Agenda findet man unter http://www.psugh.de/saturday/. Die Teilnahme ist kostenlos, aber eine Anmeldung über Meetup ist erforderlich, da die Plätze begrenzt sind.

Die OU eines AD-Users in ein Attribut kopieren

$
0
0

In einer AD-Migration bei einem Kunden sollten die Quell-OUs der Userkonten in einem freien Attribut gespeichert werden, um nach der Migration bei den Zielobjekten den ursprünglichen Ablageort feststellen zu können. Das folgende PowerShell-Skript erfüllte in der Quelldomäne die Aufgabe.

$Users = Get-ADUser -Filter * -SearchBase 'OU=Benutzer,DC=ad2016,DC=faq-o-matic,DC=net'
foreach ($Account in $Users) {
  $Parent = (([adsi]"LDAP://$($Account.DistinguishedName)").Parent).Substring(7)
  $Account.Name + ': ' + $Parent
  Set-ADUser -Identity $Account.DistinguishedName -Add @{info=$Parent}
}

PowerShell-Alternative: Die OU eines AD-Users in ein Attribut kopieren

$
0
0

Zu dem Artikel “Die OU eines AD-Users in ein Attribut kopieren” gibt es ein alternatives Verfahren, das die Eigenheiten der PowerShell besser ausnutzt. Wenig bekannt ist, dass die Pipeline-Technik der PowerShell meist viel schneller ist. Die folgende Code-Variante dürfte daher in großen Umgebungen schneller fertig sein.

[regex]$regex = "(?:,)(?'name'((CN|OU=).*))"

Get-ADUser -Filter * -SearchBase "OU=Benutzer,DC=ad2016,DC=faq-o-matic,DC=net" | ForEach-Object {
    $ou = $regex.Match($_.DistinguishedName).Groups['name']

    Write-Host($_.Name + ": $ou")
    $_ | Set-ADUser -Add @{info=$ou}
}

Der Code findet sich auch auf GitHub.

PrimaryGroupID automatisch korrigieren

$
0
0

Möchte man die PrimaryGroupID (näheres siehe in diesem Beitrag) automatisch für alle AD-User prüfen und ggf. auch automatisch korrigieren, so kann man dies natürlich auch per PowerShell tun.

Im Active Directory gibt es standardmäßig eine Ausnahme, welche nicht die primaryGroupID 513 („Domain-Users“) hat: Hierbei handelt es sich um den User „Guest“, dieser hat die primaryGroupID 514 („Domain-Guests“) und muss somit gesondert berücksichtigt werden. Das Script „Correct-ADPrimaryGroup.ps1” (zu finden auf Github) berücksichtigt auch diese Ausnahme.

[Correct-ADPrimaryGroup.ps1 · GitHub]
https://gist.github.com/RobinBeismann/cbd3ae7e74d9d8fd331304d13788f0e0

Falls man sich nur die Vorkommnisse anzeigen lassen will, so kann man das Script direkt ausführen, da die Variable „$dryRun“ standardmäßig auf true steht. Möchte man die oben generierten (potentiellen) Fehler automatisch korrigieren lassen, so muss man Zeile 2 auf „$dryRun = $false“ ändern.

In der Standardeinstellung fragt das Script alle AD-User in der aktuellen Domäne ab, dies kann geändert werden in dem man Zeile 3 auf „$searchBase=’OU Pfad’“ ändert.

OCSP Responder in der DMZ

$
0
0

Setzt man sich mit der Planung und Implementierung einer (möglicherweise Multi-Tier-) Enterprise-CA unter Windows auseinander, so wird man feststellen, dass hierfür sowohl ein CRL-Webserver (Certificate Revocation List) als auch ein OCSP Responder (Online Certificate Status Protocol) sinnvoll sind. In größeren Umgebungen befinden sich sowohl der CRL-Webserver als auch der OCSP Responder meistens in einer DMZ und sind weder Mitglied der selben noch Mitglied einer vertrauten Domäne der Issuing Certificate Authority (dt. Zertifizierungsstelle).

Im Gegensatz zu einer herkömmlichen Zertifikatssperrliste (CRL), welche komplett digital signiert von der Zertifizierungsstelle kommt, werden OCSP Anfragen pro Antwort signiert. Dafür wird ein OCSP Response Signing Zertifikat benötigt, welches nur kurze Laufzeiten haben sollte, da dies die Zertifikatserweiterung „id-pkix-ocsp-nocheck“ beinhaltet und so keinerlei Revocation Check erfolgt.

Die folgende Grafik beschreibt den Ablauf eines OCSP-Checks:

image

Steht der OCSP Responder (ggf. mehrere hinter einem Load Balancer) nun in einer DMZ, hat dieser keinerlei Möglichkeit, ein solches Zertifikat automatisch bei einer CA anzufordern. Dadurch gibt es für die Automatisierung dieses Vorganges auch keine Best Practice. Allerdings konnte uns auch hier PowerShell wieder aushelfen.

Das Script „Renew-OCSPResponderCertificate.ps1” (zu finden auf Github) übernimmt das automatische Anfordern eines OCSP-Signing-Zertifikats für eine oder mehrere Enterprise-CAs und OCSP-Responder-Server. Hierfür wird eine PowerShell Remoting (WinRM) Verbindung zu den Servern genutzt, welche die OCSP-Responder-Rolle (z.B. in der DMZ) hosten. Seitens der OCSP Responder Server wird ein Service-Account benötigt, welcher die Rechte hat, den lokalen Computer-Zertifikatsspeicher zu nutzen und zu bearbeiten, um darüber Zertifikatsanforderungen auszustellen und abzuschließen. Außerdem muss dieser mindestens die Rechte haben, die Windows Remote Management Schnittstelle zu bedienen, eine passende lokale Gruppe dafür ist z.B. Remote Management Users (dt. Remoteverwaltungsbenutzer).

Um die Zertifikatsanforderung abzuschließen, wird ein weiterer Service Account (ggf. Domainbasiert) mit Windows Remote Management Berechtigungen auf einem System in der Domäne der entsprechenden Enterprise CA benötigt. Hierfür kann z.B. auch eine direkte Verbindung auf den Server, welcher die Enterprise CA hostet, genutzt werden. Der erwähnte Service Account benötigt außerdem die Rechte, Zertifikate mit der entsprechenden OCSP Signing Vorlage anzufordern.

Der Job, der dieses Script ausführt, sollte bereits einige Tage vor Ablauf des alten Zertifikates ausgeführt werden.

Beispiel: Hat die OCSP Responder Zertifikatsvorlage eine Laufzeit von 14 Tagen, so sollte man nach Möglichkeit den Job im Intervall von 10 Tage laufen lassen.

Das Script führt also die folgenden Schritte pro OCSP Responder Definition aus:

  • Aufbau einer PowerShell Remoting Session zum OCSP Responder
  • Ausstellen einer Zertifikatsanforderung (CSR) pro definierter Enterprise CA mit „certreq.exe“
  • Kopieren der CSR Files in die Workfolder des Scriptes
  • Pro CA:
    • Aufbau einer PowerShell Remoting Session zum WinRM Jumphost in der Domäne der CA
    • Kopieren der jeweiligen CSR Datei auf den WinRM Jumphost
    • Abschließen der Zertifikatsanforderung mit „certreq.exe“
    • Kopieren des signierten Zertifikates auf den jeweiligen OCSP Responder Server über die Workfolder des Scriptes
    • Import der abgeschlossenen Zertifikatsanforderung auf dem OCSP Responder Server „certreq.exe“
    • Hinzufügen der Berechtigung für den „NETWORK SERVICE“ auf den Private Key des Zertifikates (notwendig für Zugriff des OCSP Responder IIS Pools)
    • Entfernen aller bereits abgelaufenen Zertifikate auf dem OCSP Responder Server

Da der Private Key des Zertifikates den jeweiligen OCSP Responder nicht verlässt, ist diese Methode auch aus sicherheitskritischer Sicht in Ordnung.

Konfiguriert man den OCSP Responder Service mit der „automatischen OCSP Signing Zertifikatsauswahl“, so wird dieser das neue Zertifikat auswählen, sobald das alte abgelaufen ist. Bei einem manuellen Neustart des OCSP Responders, wird automatisch das Zertifikat mit der längsten Laufzeit gewählt.

SQL Server: Backups testen

$
0
0

Oder: Vertrauen ist gut, Kontrolle ist besser!

Welcher Windows-Administrator kennt diese Situation nicht? Man ist zwar eigentlich kein Datenbankadministrator (DBA), aber zur der Anwendung gehört halt ein SQL Server, und einen echten DBA gibt es nun mal nicht. Also muss man sehen, dass die Datenbank läuft. Genauso wichtig wie ein laufender Server ist gerade bei Datenbanken, dass man die Daten im Notfall auch wiederherstellen kann. Dabei muss man immer wieder feststellen, dass das Backup noch recht gut überwacht und kontrolliert wird, aber die Wiederherstellung so gut wie nie getestet ist.

Es gilt der Spruch:

Was interessiert mich das erfolgreiche Backup, der erfolgreiche Restore ist mir viel wichtiger!

Und letztendlich trifft dies genau den Kern des Problems. Viele (Teilzeit-) Datenbankadministratoren verlassen sich zu sehr auf die Meldung „Backup erfolgreich“, testen aber zu selten bis niemals ob auch die Wiederherstellung aus dem Backup funktioniert. Eine regelmäßige händische Kontrolle ist aufwendig, zeitintensiv und von Spaß wollen wir erst gar nicht reden. Aber es gibt einen einfachen und schnellen Weg den Restore über die Powershell zu testen.

DBATOOLS

Gerade für Nicht-DBAs gibt es ein Powershell-Modul mit dem Namen DBAtools, welches einem viel Arbeit abnehmen kann. Weitere Informationen zu dem Modul sowie Download-Möglichkeiten gibt es auf der Projekt Seite unter www.dbatools.io

Das Module kann auf einem PC mit Internetzugang ganz leicht über den Powershell Befehl

Install-module dbatools

installiert werden. Um das Modul zu nutzen, ist keine Installation oder Änderung am Server notwendig. In der Regel muss nur der Port des SQL Servers (Standmäßig 1433) von dem Administrations-PC aus erreichbar sein.

Für den Recovery Test steht das folgende Cmdlet zur Verfügung:

Test-DbaLastBackup -SqlInstance SERVER -Database DBNAME

Das Cmdlet stellt nun eine Verbindung zu dem SQL Server „SERVER“ her und führt eine Wiederherstellung der Datenbank durch. Die Datenbank wird mit einem anderen Namen und anderen Dateinamen aus den Backupdaten wiederhergestellt und ein DBCC CHECKDB durchgeführt. Somit besteht keine Gefahr für die produktiven Datenbanken während des Tests. Nachdem die Wiederherstellung und der Datenbankcheck abgeschlossen sind, wird die Datenbank automatisch wieder gelöscht. Zudem ist es möglich, mehrere Datenbanken (oder auch alle) mit einem Befehl zu testen und den Testlauf auf einem separaten Server durchzuführen.

Test-DbaLastBackup -SqlInstance QUELLSERVER -Destination ZIELSERVER | ogv

Durch diesen Befehl werden alle Datenbanken vom Quellserver auf dem Zielserver testweise wiederhergestellt und geprüft. Das Ergebnis wird in einem separaten Fenster als Liste ausgegeben.

clip_image002

Im Beispiel wurden die Datenbanken einer anderen Instanz wiederhergestellt und geprüft. Man kann gut erkennen, dass der Restore von allen Datenbanken funktioniert hat. Lediglich der Check der Master-DB kann auf Grund von technischen Einschränkungen nicht durchgeführt werden.

Neben der Information, ob der Restore überhaupt funktioniert, erhält man auch Informationen zum Zustand der Datenbank und wie lange die Wiederherstellung gedauert hat. Diese Information kann wichtig werden, wenn es um vertragliche Wiederherstellungszeiten aus SLA (Service-Level-Agreement) geht. Kann ich die vereinbarten Zeiten überhaupt einhalten oder dauert der reine Restore schon länger als vereinbart? 

Speicheranforderung

Da alle Datenbanken nach der Prüfung wieder gelöscht werden, braucht man nur so viel Festplattenspeicher wie die größte Datenbank belegt.

Weitere Informationen zum Cmdlet Test-DbaLastBackup findet man unter https://dbatools.io/functions/test-dbalastbackup/

Offene Exchange-Verteilerlisten mit externen Kontakten

$
0
0

Problem:

Mitarbeiter hatten die Anforderungen, selber Verteilerlisten mit externen Projektpartnern zu verwalten. Eine Exchange-Verteilerliste zu verwalten, ist eigentlich keine große Aufgabe. Die Probleme fangen an, sobald externe Adressen benötigt werden in der Verteilerliste. Dazu ist jeweils ein AD-Objekt notwendig, das als Kontakt angelegt worden ist.

Ich habe mir diverse Lösungen angeschaut, dies über RSAT zu machen. Die waren mir aber zu unflexibel, da auf jedem Rechner erst mal RSAT installiert werden muss.

Meine Lösung ist über die Exchange-Rollen zu realisieren. Das Pflegen geht über die ECP-Konsole des Exchange-Servers. Die Kontakte werden in eine eigene OU gepackt und von den jeweiligen Mitarbeitern selber verwaltet. Das Ganze hat diverse Stunden gedauert: Wie diese Rollen ticken und welche Kommandos notwendig sind, dazu gibt es wenige Beispiele. Was ich selber nicht hin bekommen habe, war, den „write scope“ so zu setzen, dass der Anwender nicht immer die OU auswählen muss. Wer hier eine Lösung hat, darf sie mir gerne mitteilen.

Ich habe mir diverse Beispiele angeschaut und aus den ganzen Beispielen mir eine Lösung zusammen gebaut. Das Ganze wurde auf einem Exchange Server 2013 durchprobiert, sollte für 2016 genauso gehen.

Dann werfen wir die Powershell an. Dazu schauen wir uns mal die Rollen an. Wir brauchen dafür nur ein paar Rechte aus den Rollen. Es sind ca. 125 also doch etwas unübersichtlich.

Get-ManagementRoleEntry „Mail Recipients\*“ | Select Name

clip_image002

Get-ManagementRoleEntry „View-Only Recipients\*“ | Select Name

clip_image004

Wir erstellen uns neue Rollen, dies geht mit folgenden Befehlen

1. New-ManagementRole -Parent „Mail Recipients“ -Name „Custom Role – Mail Contacts“

2. New-ManagementRole -Parent „Mail Recipient Creation“ -Name „Custom Role – Mail Contacts Creation“

clip_image006

Jetzt haben wir eine 1-zu-1-Kopie der bestehenden Rollen anfertigt. Wir verwenden dazu folgenden Befehl

Get-ManagementRoleEntry „Custom Role – Mail Contacts\*“ | Where {$_.Name -notlike „*MailContact“} | Remove-ManagementRoleEntry

clip_image008

Wir werden hier gefragt, ob wir wirklich die Rechte entfernen möchten, dies beantworten wir mit A für Alle. Sonst darf man jedes einzelne Recht bestätigen, was entfernt werden soll.

Get-ManagementRoleEntry „Custom Role – Mail Contacts Creation\*“ | Where {$_.Name -notlike „*MailContact“} | Remove-ManagementRoleEntry

clip_image010

Wir schauen uns die angepassten Custom Rollen an mit folgendem Befehl.

Get-ManagementRoleEntry „Custom Role – Mail Contacts\*“

clip_image012

Wir sehen nun in der Custome Role – Mail Contacs nur noch vier Rollen, die wir benötigen. Die Rollen heißen wie folgt:

Disable-Mailcontact
Enable- Mailcontact
Get-MailContact
Set-MailContact

Get-ManagementRoleEntry „Custom Role – Mail Contacts Creation\*“

clip_image014

Hier sind nur noch drei übrig mit folgender Bezeichnung:

Get-MailContact
New-Mailcontact
Remove-MailContact

Jetzt müssen wir noch eine letzte Custom Rolle erstellen:

New-ManagementRole -Parent „View-Only Recipients“ -Name „Custom Role – View-Only Recipients“

clip_image016

Wir entfernen wieder alle nicht benötigte Rollen:

Get-ManagementRoleEntry „Custom Role – View-Only Recipients\*“ | Where {$_.Name -notlike „*MailContact“} | Remove-ManagementRoleEntry

clip_image018

Wieder mit A alles entfernen

Ich habe jetzt keine Möglichkeit gefunde,n wie ich in einer Zeile mehrere Rollen gleichzeitig hinzufügen kann per Powershell.

Folgende Rollen benötigen wir noch

Add-ManagementRoleEntry „Custom Role – View-Only Recipients\Get-OrganizationalUnit“
Add-ManagementRoleEntry „Custom Role – View-Only Recipients\Get-Recipient“
Add-ManagementRoleEntry „Custom Role – View-Only Recipients\Get-Contact“

clip_image020

Es sind dann vier Rollen in der „Custom Role – View-Only Recipients“ Rolle zu sehen.

Get-Contact
Get-Recipient
Get-OrganizationalUnit
Get-MailContact

Nun erstellen wir eine Admin-Rolle mit der Powershell, in der wir unsere 3 Custom Rollen gleichzeitig hinzufügen. Dies würde auch über die ECP GUI gehen.

New-RoleGroup –Name “Contact Editor” –Roles “Custom Role – View-Only Recipients”, „Custom Role – Mail Contacts“, „Custom Role – Mail Contacts Creation“

clip_image022

Anpassungen der ECP-Konsole

Danach geht es in der ECP-Konsole des Exchange Admins. Unter “Admin Rollen” finden wir nun eine Rolle mit dem Namen „Contact Editor“. Wir definieren nun einen Benutzer über die ECP, der Kontakte pflegen kann. Der Benutzer muss nicht zwingend eine Mailbox besitzen. Ein reines AD Konto reicht aus. Hier sei noch angemerkt, wird ein Benutzer mit Mailbox verwendet, so kann er seine eigene ECP-Seite nicht mehr aufrufen.

Wir definieren eine OU, in der diese Rolle schreiben und löschen darf, speichern das Ganze und melden uns an der ECP Konsole mit dem definierten Benutzer an.

clip_image023

Angepasste ECP-Seite

Nun sehen wir eine sehr abgespeckte ECP Webseite.

clip_image025

Es ist nicht möglich, Kontakte außerhalb der definierten OU zu bearbeiten. Ich kann diese zwar sehen aber nicht bearbeiten.

Wir erstellen nun einen neuen Kontakt

Wie wir sehen, haben wir nur die Möglichkeit einen Kontakt und keine Mailbox zu erstellen.

clip_image026

clip_image027

Nun sind die entsprechenden Felder zu füllen, die benötigt werden. Wichtig dabei ist, auch die richtige OU zu wählen, in der die Kontakt angelegt werden sollen.

clip_image029

Speichern klicken, und das war es auch schon. Der Kontakt wird in die definierte OU geschrieben und kann nun in den Mailverteiler mit aufgenommen werden.

Noch ein paar Powershell-Befehle, die mir geholfen haben

Wie entferne ich eine selbst gebaute Rolle wieder

Remove-ManagementRole „Custom Role – View-Only Recipients“

Eine leere Rolle mit einer vorhanden füllen

Get-ManagementRoleEntry „View-Only Recipients\*“ | Add-ManagementRoleEntry -Role „Custom Role – View-Only Recipients“

Viewing all 101 articles
Browse latest View live