Automatisierte Aktualisierung der GPOs über RDP

Hier die Vorgeschichte warum ich GPOs zusätzlich über den Aufgabenplaner aktualisiere.

Ich hatte das Problem, dass mir immer wieder Rechte fehlten um VM Clients zu starten oder / und zu konfigurieren. Die Ursache liegt daran, dass ich die notwendigen Rechte des Hyper-V Accounts über Gruppenrichtlinien verteile. Nach Analyse habe ich über das Web fest gestellt, dass ich mit meinen Problem nicht alleine bin. Durch das ich nur Lösungen gefunden habe in der ich jeden Hyper-V Host manuell konfigurieren muss habe ich mich für dieses Skript entschieden.

Damit das Skript erfolgreich läuft, sind folgende Positionen notwendig:

  • Der Account für die Ausführung im Aufgabenplaner muss das Recht Anmelden als Dienst besitzen (Lokale Sicherheitsrichtlinien / Zuweisung von Benutzerrechten / Anmelden als Stapelverarbeitungsauftrag)
  • Das Account-Passwort für die Aktualisierung der Gruppenrichtlinien
    Dieses wird verschlüsselt abgelegt, siehe passwort-in-datei-ueber-powershell-erstellen-speichern
  • Der Account für die Ausführung des Aufgabenplaner und der für die Aktualisierung der GPOs sollte der gleiche sein und sich mindestens ein mal am Domänencontroller angemeldet haben. Dies ist notwendig für die Ablage des Passworts.
  • Ausführungsrecht des Skripts. Hier haben Sie die Möglichkeit mit dem Befehl
    Set-ExecutionPolicy Unrestricted

    entsprechende Rechte zu setzen. Dieser Befehl sollt aus Sicherheitsgründen nicht eingesetzt werden.
    Die Sichere Methode ist, das Skript zu signieren. Siehe powershell-skript-signieren

  • Recht für die Ausführung einrichten
    powershell -ep RemoteSigned -file MyScript.ps1

Die im Skript Fett gekennzeichneten Felder sind anzupassen.

# PowerShell Automatisierte Aktualisierung der GPOs ueber RDP 1.0.0
# (c) Siegfried Paul 2014
function Update-GPO{
    # .SYNOPSIS Aktualisiertung GPUpdate AD Hyper-Vs .DESCRIPTION Hyper-V Server, die in der Domaene integriert sind und die Rechte ueber GPO gesteutert werden hat der Account "NT Virtual Machine\Virtual Machines" nur solagen die notwendigen Rechte wie die GPOs gueltig sind. Aktualisiert ueber GPUpdate alle Hyper-V Systeme die in der AD hinterlegt sind umd mit dem Namen HV beginnen. Im Fehlerfall wird eine E-Mail an mail@mail.de versendet. .PARAMETER SystemName Name des Sysetms auf dem es ausgefuehrt wird. Parameter ist hilfreich wenn fehler auftreten. .PARAMETER SendEMailSuccess Wird der Parameter $true mit uebergeben und der Durchlauf ist erfolgreich wird eine positive E-Mail versendet. Im Standard ist der Wert $false belegt Es koennen die Parameter $true oder $false uebergeben werden. .PARAMETER EMailTo Die Empfaenger-Adresse fuer einen erfolgreichen und fehlerhaften Durchlauf. Im Standard ist der Wert mit der Adresse mail@mail.de belegt. .EXAMPLE Update-GPO -SystemName [Systemname] Hier handelt es sich um den Systemnamen des Domain Controllers. Im Standard wird bei einem Fehlerfall eine E-Mail versendet. Zur Identifizierung bei mehreren Systemen sollte dieser Parameter mit übergeben werden. .EXAMPLE ​Update-GPO -SendEMailSuccess $true Aktualisiert alle Systeme mit Mail-Versand des erfolgreichen Durchlaufs .EXAMPLE Update-GPO -EMailTo $true Aktualisiert alle Systeme mit Mail-Versand des erfolgreichen Durchlaufs #>
    # Uebergabeparameter
    PARAM(
        [String][Parameter(Mandatory=$false,HelpMessage="Name des Domain Controllers")]$SystemName = "System unbekannt",
        [String][Parameter(Mandatory=$false,HelpMessage="E-Mail Empfaengeradresse")]$EMailTo = "mail@mail.de",
        [Bool][Parameter(Mandatory=$false,HelpMessage="E-Mail Versand bei erfolgreicher ausfuehrung")]$SendEMailSuccess = $false
    )
    # Konsolenausgabe
    $Text = Get-Date
    "Start - $Text"
    ###
    # Anpassungen
    ###
    # Catch - Mail-Variable
    $EMailFrom = "mail@mail.de"
    $EMailServer = "smtp.mail.de"
    $EMailPort = 25
    $SystemInfoText = "System unbekannt"
    $MailSubject = "GPUpdate - $Systemname"
    # Filter für LDAP
    $LDAPFilter = "HV*"
    # RDP Zugangsdaten
    $user = "domanin\administrator"
    # Passwortdatei
    $Text = "Passwortdatei pruefen"
    $PasswordDatei = "$env:USERPROFILE\spsoffice-Administrator.txt"
    if(-Not(Test-Path $PasswordDatei)){
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $Text = "$Text`r`nFehler-Message: Die Passwortdatei wurde nicht gefunden.`r`n"
        $MailSubject = "Error - $MailSubject"
        # Konsolenausgabe
        $Text
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Break
    }
    try{
        # Einlesen der Systeme basierend auf LDAP-Filter
        $Text = "Einlesen der Systeme basierend auf LDAP-Filter"
        # Konsolenausgabe
        $Text
        $cn = Get-ADComputer -LDAPFilter "(name=$LDAPFilter)"
    }
    catch{
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $Text = "$Text`r`nFehler-StackTrace: $FailedItem`r`n Fehler-Message: $ErrorMessage`r`n"
        $MailSubject = "Error - $MailSubject"
        # Konsolenausgabe
        $Text
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Break
    }
    try{
        # Passwort auslesen
        $Text = "Passwort auslesen"
        # Konsolenausgabe
        $Text
        $PWord = Get-Content $PasswordDatei | ConvertTo-SecureString
    }
    catch{
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $Text = "$Text`r`nFehler-StackTrace: $FailedItem`r`n Fehler-Message: $ErrorMessage`r`n"
        $MailSubject = "Error - $MailSubject"
        # Konsolenausgabe
        $Text
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Break
    }
    try{
        # RDP Zugangsdaten generieren
        $Text = "RDP Zugangsdaten generieren"
        # Konsolenausgabe
        $Text
        $Credential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $User, $PWord
    }
    catch{
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $Text = "$Text`r`nFehler-StackTrace: $FailedItem`r`n Fehler-Message: $ErrorMessage`r`n"
        $MailSubject = "Error - $MailSubject"
        # Konsolenausgabe
        $Text
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Breas.pk
    }
    try{
        # RDP-Verbindungen aufbauen  - siehe $cn
        $Text = "RDP-Verbindungen aufbauen"
        # Konsolenausgabe
        $Text
        $session = New-PSSession -cn $cn.name -cred $Credential
    }
    catch{
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $Text = "$Text`r`nFehler-StackTrace: $FailedItem`r`n Fehler-Message: $ErrorMessage`r`n"
        $MailSubject = "Error - $MailSubject"
        # Konsolenausgabe
        $Text
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Break
    }
    try{
        # Befehl auf RDP System ausfuehren - gpupdate
        $Text = "Befehl auf RDP System ausfuehren"
        # Konsolenausgabe
        $Text
        icm -Session $session -ScriptBlock {gpupdate /force}
    }
    catch{
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $Text = "$Text`r`nFehler-StackTrace: $FailedItem`r`n Fehler-Message: $ErrorMessage`r`n"
        $MailSubject = "Error - $MailSubject"
        # Konsolenausgabe
        $Text
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Break
    }
    $Text = "GPUpdate wurde erfolgreich ausgefuehrt"
    # Konsolenausgabe
    $Text
    # Mailversand bei erfolgreicher ausfuehrung
    if($SendEMailSuccess -eq $true){
        $FailedItem = $_.Exception.StackTrace
        $ErrorMessage = $_.Exception.Message
        $MailSubject = "Success - $MailSubject"
        Send-MailMessage -From $EMailFrom -To $EMailTo -Subject $MailSubject -SmtpServer $EMailServer -Port $EMailPort -Body $Text
        Break
    }
}

Taskmanager

Der Aufruf erfolgt im Taskmanager wie folgt

Programm: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Argumente:

Update-GPO -SystemName NAMEDOMAINCONTROLLER  *> "C:\PowerShell\Update-GPO.log" -SendEMailSuccess $true

Leave a Reply