Tierney - stock.adobe.com

Wie man Gruppenmitgliedschaften mit PowerShell überwacht

Mit PowerShell lassen sich Berichte über lokale Gruppenmitgliedschaften auf Servern und Sicherheitsgruppen in Active Directory erstellen, um unregelmäßiges Verhalten zu überwachen.

Die Kontrolle von Mitgliedschaften in privilegierten Gruppen ist eine wichtige Aufgabe, die eine PowerShell-Automatisierung mit minimalem Aufwand erledigen kann.

Der einfache Ansatz zur Gruppenmitgliederverwaltung, wie zum Beispiel Domänenadministratoren in Active Directory oder die lokale Administratorengruppe auf einem Server, ist das Kontrollieren des Gruppenverwaltungszugriffs – und darauf zu vertrauen, dass niemand etwas tut, was er nicht soll. In größeren Umgebungen, in denen viele Personen administrativen Zugriff auf Gruppen haben, ist Vertrauen gut, aber Kontrolle besser. Wir zeigen, wie Sie mit PowerShell ganz einfach ein Skript schreiben, um die Mitgliedschaften in diesen Gruppen zu überwachen oder sogar zu erzwingen.

Sowohl bei Windows-Servern als auch bei Active Directory ist der Ansatz zur Verwaltung dieser Gruppen ähnlich. Zunächst müssen wir eine Liste der zu überwachenden Gruppen erstellen, dann die Mitglieder jeder Gruppe abrufen und schließlich prüfen, ob es seit der letzten Ausführung des Skripts Änderungen gegeben hat.

Lokale Gruppenmitgliedschaften auf Windows Server erfassen

Auf einem lokalen Server ist die Liste der Gruppen wahrscheinlich recht kurz. In diesem Artikel werden wir nur mit zwei Gruppen arbeiten – Administratoren und Remote-Desktop-Benutzer – Sie die Strategie aber auf eine beliebige Anzahl von Gruppen ausweiten, indem Sie das Skript entsprechend anpassen.

Beginnen Sie das Skript mit einer Variablen, die die Gruppen enthält, und fügen Sie dann eine foreach-Schleife hinzu, die jede dieser Gruppen durchläuft und die Gruppenzugehörigkeit zurückgibt.

$groups = @(
    'Administrators'
    'Remote Desktop Users'
)
$groupMembers = foreach ($group in $groups) {
    Get-LocalGroupMember $group
}

Sehen wir uns die Ausgabe von $groupMembers an und die Mitglieder jeder dieser Gruppen (Abbildung 1).

Abbildung 1: Die Ergebnisse des Skripts zur Erfassung der Gruppenmitgliedschaft auf dem Server führen die lokalen Administratoren auf.
Abbildung 1: Die Ergebnisse des Skripts zur Erfassung der Gruppenmitgliedschaft auf dem Server führen die lokalen Administratoren auf.

Sie können sich die Informationen in einer E-Mail-Benachrichtigung zusenden lassen. Man kann aber auch PowerShell verwenden, um Gruppenmitgliedschaften zu überwachen und Benachrichtigungen zu senden, wenn Änderungen auftreten.

Zunächst exportieren Sie die Mitgliedschaften in eine CSV-Datei und laden diese dann, um den vorherigen Lauf mit dem aktuellen Lauf zu vergleichen. Verwenden Sie dazu zwei zusätzliche foreach-Schleifen: Die erste sucht nach Benutzern, die hinzugefügt wurden, und die zweite nach Benutzern, die entfernt wurden.

foreach ($group in $groups) {
    $previousRunMemberships = $null
    if (Test-Path "C:\tmp\$group.csv") {
        $previousRunMemberships = Import-Csv -Path "C:\tmp\$group.csv"
    }
    $groupMembers = Get-LocalGroupMember $group
    $added = foreach ($member in $groupMembers) {
        if ($previousRunMemberships.SID -notcontains $member.SID) {
            $member
        }
    }
    $removed = foreach ($member in $previousRunMemberships) {
        if ($groupMembers.SID -notcontains $member.SID) {
            $member
        }
    }
   $groupMembers | Export-Csv -Path "C:\tmp\$group.csv" -NoTypeInformation
}

Das Skript gibt die aktuellen Benutzer in eine CSV-Datei aus, die mit einer CSV-Datei verglichen wird, welche einen älteren Zustand der Mitgliedschaften enthält.

Im nächsten Schritt stellen Sie eine Benachrichtigung ein. Es gibt viele Optionen, wie zum Beispiel den Befehl Send-MailMessage, doch in diesem Tutorial verwenden wir Azure Logic Apps, um die Benachrichtigung weiterzuleiten.

Erstellen Sie zunächst eine Funktion und fügen Sie sie wie folgt in den Anfang des Skripts ein:

Function Send-LogicAppEmail {
    param (
        [string]$LogicAppUri = '<logic app uri>',
        [string]$To = '[email protected]',
        [string]$CC,
        [string]$Subject,
        [string]$Message
    )
    $headers = @{
        'Content-Type' = 'application/json'
    }
    $body = @{
        To = $To
        CC = $CC
        Subject = $Subject
        Body = $Message
    }
    $splat = @{
        Uri = $LogicAppUri
        Method = 'POST'
        Headers = $headers
        Body = ($body | ConvertTo-Json)
    }
    Invoke-RestMethod @splat
}

Als Nächstes erstellen Sie den HTML-Code und rufen diese Funktion in der foreach-Schleife auf.

   if ($added -or $removed) {
        $html = @"
<h1>$($env:COMPUTERNAME)</h1>
<h2>$group</h2>
<h2>Added</h2>
<pre>
$($added | Format-Table | Out-String)
</pre>
<h2>Removed</h2>
<pre>
$($removed | Format-Table | Out-String)
</pre>
"@
        Send-LogicAppEmail -To '[email protected]' -Subject "Changes to $group on $($env:COMPUTERNAME)" -Message $html
    }

Abbildung 2 zeigt ein Beispiel für eine E-Mail, die anzeigt, dass ein Benutzer zur Gruppe der Remote-Desktop-Benutzer hinzugefügt wurde.

Abbildung 2: Die Benachrichtigung zeigt die Liste der Benutzer an, die zur Gruppe der Remote-Desktop-Benutzer hinzugefügt oder entfernt wurden.
Abbildung 2: Die Benachrichtigung zeigt die Liste der Benutzer an, die zur Gruppe der Remote-Desktop-Benutzer hinzugefügt oder entfernt wurden.

Im Folgenden finden Sie das vollständige Skript zur Überwachung der Gruppenmitgliedschaft.

Function Send-LogicAppEmail {
    param (
        [string]$LogicAppUri = '<logic app uri>',
        [string]$To = '[email protected]',
        [string]$CC,
        [string]$Subject,
        [string]$Message
    )
    $headers = @{
        'Content-Type' = 'application/json'
    }
    $body = @{
        To = $To
        CC = $CC
        Subject = $Subject
        Body = $Message
    }
    $splat = @{
        Uri = $LogicAppUri
        Method = 'POST'
        Headers = $headers
        Body = ($body | ConvertTo-Json)
    }
    Invoke-RestMethod @splat
}
$groups = @(
    'Administrators'
    'Remote Desktop Users'
)
foreach ($group in $groups) {
    $previousRunMemberships = $null
    if (Test-Path "C:\tmp\$group.csv") {
        $previousRunMemberships = Import-Csv -Path "C:\tmp\$group.csv"
    }
    $groupMembers = Get-LocalGroupMember $group
    $added = foreach ($member in $groupMembers) {
        if ($previousRunMemberships.SID -notcontains $member.SID) {
            $member
        }
    }
    $removed = foreach ($member in $previousRunMemberships) {
        if ($groupMembers.SID -notcontains $member.SID) {
            $member
        }
    }
    if ($added -or $removed) {
        $html = @"
<h1>$($env:COMPUTERNAME)</h1>
<h2>$group</h2>
<h2>Added</h2>
<pre>
$($added | Format-Table | Out-String)
</pre>
<h2>Removed</h2>
<pre>
$($removed | Format-Table | Out-String)
</pre>
"@
        Send-LogicAppEmail -To '[email protected]' -Subject "Changes to $group on $($env:COMPUTERNAME)" -Message $html
    }
$groupMembers | Export-Csv -Path "C:\tmp\$group.csv" -NoTypeInformation
}

Speichern Sie dieses Skript in einem lokalen Pfad auf jedem Server, und rufen Sie es dann regelmäßig mit einer geplanten Aufgabe auf.

Gruppenmitgliedschaften in Active Directory überwachen

Der Prozess zum Überwachen von Gruppen in Active Directory ähnelt dem für lokale Gruppen auf Serversystemen. Der einzige Unterschied ist, dass wir die Befehle des Active-Directory-Moduls einsetzen. Dazu muss das folgende Skript entweder auf einem Domänencontroller oder auf einem Gerät laufen, auf dem das Active-Directory-Modul installiert und mit dem Domänencontroller verbunden ist.

Stellen Sie zunächst das Gruppen-Array so ein, dass es auf Active Directory-Gruppen verweist. Fügen Sie so viele Gruppen hinzu, wie Sie möchten. Für dieses Beispiel werden wir die folgenden zwei Gruppen prüfen:

$groups = @(
    'Domain Admins'
    'Schema Admins'
)

Verwenden Sie den Befehl Get-ADGroupMember, um die Gruppenmitglieder zu ermitteln.

$groupMembers = Get-ADGroupMember $group

Passen Sie abschließend die HTML-Nachricht und den Betreff so an, dass sie auf Active Directory verweisen.

   if ($added -or $removed) {

        $html = @"
<h1>Active Directory</h1>
<h2>$group</h2>
<h2>Added</h2>
<pre>
$($added | Format-Table | Out-String)
</pre>
<h2>Removed</h2>
<pre>
$($removed | Format-Table | Out-String)
</pre>
"@
        Send-LogicAppEmail -To '[email protected]' -Subject "Changes to $group in Active Directory" -Message $html
    }

Nun sieht das vollständige Skript wie folgt aus:

Function Send-LogicAppEmail {
    param (
        [string]$LogicAppUri = '<logic app uri>',
        [string]$To = '[email protected]',
        [string]$CC,
        [string]$Subject,
        [string]$Message
    )
    $headers = @{
        'Content-Type' = 'application/json'
    }
    $body = @{
        To = $To
        CC = $CC
        Subject = $Subject
        Body = $Message
    }
   $splat = @{
        Uri = $LogicAppUri
        Method = 'POST'
        Headers = $headers
        Body = ($body | ConvertTo-Json)
    }
    Invoke-RestMethod @splat
}
$groups = @(
    'Domain Admins'
    'Schema Admins'
)
foreach ($group in $groups) {
    $previousRunMemberships = $null
    if (Test-Path "C:\tmp\$group.csv") {
        $previousRunMemberships = Import-Csv -Path "C:\tmp\$group.csv"
    }
    $groupMembers = Get-ADGroupMember $group
    $added = foreach ($member in $groupMembers) {
        if ($previousRunMemberships.SID -notcontains $member.SID) {
            $member
        }
    }
    $removed = foreach ($member in $previousRunMemberships) {
        if ($groupMembers.SID -notcontains $member.SID) {
            $member
        }
    }
    if ($added -or $removed) {
        $html = @"
<h1>Active Directory</h1>
<h2>$group</h2>
<h2>Added</h2>
<pre>
$($added | Format-Table | Out-String)
</pre>
<h2>Removed</h2>
<pre>
$($removed | Format-Table | Out-String)
</pre>
"@
        Send-LogicAppEmail -To '[email protected]' -Subject "Changes to $group in Active Directory" -Message $html
    }
    $groupMembers | Export-Csv -Path "C:\tmp\$group.csv" -NoTypeInformation
}

Abbildung 3 zeigt die vom Skript generierte E-Mail-Benachrichtigung.

Abbildung 3: Die E-Mailbenachrichtigung zeigt den Namen des Nutzers, den Sie zur Administratorengruppe in Active Directory hinzugefügt haben.
Abbildung 3: Die E-Mailbenachrichtigung zeigt den Namen des Nutzers, den Sie zur Administratorengruppe in Active Directory hinzugefügt haben.

Die E-Mail zeigt, dass ein Benutzer mit dem Namen Test User zur Gruppe der Domänenadmins hinzugefügt wurde.

Dieses Skript kann in regelmäßigen Abständen über den Task Scheduler ausgeführt werden.

Warum sollte man Gruppenmitgliedschaften mit einem PowerShell-Skript überwachen?

PowerShell hat vielleicht nicht die Anziehungskraft eines ausgefeilten Überwachungsprodukts, doch es kann viele Funktionen übernehmen, wenn Sie sich die Zeit nehmen, zu lernen, wie man ein Skript schreibt und pflegt. Eine ausgefeiltere Version des Skripts kann sogar noch weiter gehen und Benutzer entfernen, die nicht in der Gruppe sein sollten, oder Benutzer hinzufügen, die versehentlich entfernt wurden. PowerShell ist flexibel genug, um diese Aufgaben zu erledigen, damit Sie sich auf andere Aufgaben konzentrieren können.

Erfahren Sie mehr über Datenschutz und Compliance