Gruppenrichtlinien mit PowerShell verwalten
Trotz Intune, DSC und Entra ID (Azure AD); Gruppenrichtlinien sind in vielen Firmen immer noch ein weit verbreitete Methode um Windows Clients und Server zu verwalten. Die MMC ist aber nicht wirklich dazu geeignet mehrere hundert GPOs zu verwalten. Doch dafür gibt es PowerShell.
Die meisten werden Get-GPO
schon genutzt haben, aber Microsoft liefert noch 25 weitere cmdlets und zwei Alias im Modul GroupPolicy
.
PS C:\Users\Fabian> Get-Command -Module GroupPolicy
CommandType Name Version Source
----------- ---- ------- ------
Alias Get-GPPermissions 1.0.0.0 GroupPolicy
Alias Set-GPPermissions 1.0.0.0 GroupPolicy
Cmdlet Backup-GPO 1.0.0.0 GroupPolicy
Cmdlet Copy-GPO 1.0.0.0 GroupPolicy
Cmdlet Get-GPInheritance 1.0.0.0 GroupPolicy
Cmdlet Get-GPO 1.0.0.0 GroupPolicy
Cmdlet Get-GPOReport 1.0.0.0 GroupPolicy
Cmdlet Get-GPPermission 1.0.0.0 GroupPolicy
Cmdlet Get-GPPrefRegistryValue 1.0.0.0 GroupPolicy
Cmdlet Get-GPRegistryValue 1.0.0.0 GroupPolicy
Cmdlet Get-GPResultantSetOfPolicy 1.0.0.0 GroupPolicy
Cmdlet Get-GPStarterGPO 1.0.0.0 GroupPolicy
Cmdlet Import-GPO 1.0.0.0 GroupPolicy
Cmdlet Invoke-GPUpdate 1.0.0.0 GroupPolicy
Cmdlet New-GPLink 1.0.0.0 GroupPolicy
Cmdlet New-GPO 1.0.0.0 GroupPolicy
Cmdlet New-GPStarterGPO 1.0.0.0 GroupPolicy
Cmdlet Remove-GPLink 1.0.0.0 GroupPolicy
Cmdlet Remove-GPO 1.0.0.0 GroupPolicy
Cmdlet Remove-GPPrefRegistryValue 1.0.0.0 GroupPolicy
Cmdlet Remove-GPRegistryValue 1.0.0.0 GroupPolicy
Cmdlet Rename-GPO 1.0.0.0 GroupPolicy
Cmdlet Restore-GPO 1.0.0.0 GroupPolicy
Cmdlet Set-GPInheritance 1.0.0.0 GroupPolicy
Cmdlet Set-GPLink 1.0.0.0 GroupPolicy
Cmdlet Set-GPPermission 1.0.0.0 GroupPolicy
Cmdlet Set-GPPrefRegistryValue 1.0.0.0 GroupPolicy
Cmdlet Set-GPRegistryValue 1.0.0.0 GroupPolicy
Gruppenrichtlinien finden
Leider unterstützt Get-Gpo
keinerlei Suchfilter sondern kann nur alle oder eine GPO ausgeben. Dabei kann man über -Id
oder -Name
einzelne Gruppenrichtlinien angeben, muss aber die Werte exakt kennen. Mit dem Parameter -All
wird eine Liste aller GPOs ausgeben.
Eine Filter kann daher immer erst im Nachgang angewendet werden.
# Default Domain Policy
Get-Gpo -Id 31b2f340-016d-11d2-945f-00c04fb984f9
# Default Domain Controllers Policy
Get-Gpo -Id 6ac1786c-016f-11d2-945f-00c04fb984f9
# List all GPOs
Get-Gpo -All
# Filter by name
Get-Gpo -All | Where-Object DisplayName -match "Default Domain"
Gruppenrichtlinien erstellen
Um eine neue, leere Gruppenrichtlinie anzulegen muss man nicht viel Informationen liefern. Ein sprechender Name ist ausreichend, ein beschreibender Kommentar wünschenswert.
PS C:\Users\Fabian> New-GPO -Name "MSFT Windows Server 2022 - Member Server" -Comment "Microsoft Security Baseline"
DisplayName : MSFT Windows Server 2022 - Member Server
DomainName : lab.bader.cloud
Owner : LAB\Domain Admins
Id : 0ef52ff6-0ef0-42e1-9273-508463a69a44
GpoStatus : AllSettingsEnabled
Description : Microsoft Security Baseline
CreationTime : 11/15/2021 8:07:55 PM
ModificationTime : 11/15/2021 8:07:55 PM
UserVersion : AD Version: 0, SysVol Version: 0
ComputerVersion : AD Version: 0, SysVol Version: 0
WmiFilter :
Einstellungen importieren
Bei z.B. Security Baselines werden häufig Exporte von Gruppenrichtlinien als Vorlagen geliefert. So macht es auch Microsoft mit Ihrem Microsoft Security Compliance Toolkit. Dieses enthält für alle gängigen Betriebssysteme und Browser die von Microsoft empfohlenen Einstellungen.
Um diese Vorlagen zu importieren kann Import-GPO
genutzt werden. Dieses cmdlet überschreibt alle in der Gruppenrichtlinie vorhandenen Einstellungen
$GPO = Get-Gpo -Name "MSFT Windows Server 2022 - Member Server"
Import-GPO -Path "C:\Users\Fabian\Downloads\Windows Server-2022-Security-Baseline-FINAL\GPOs" -BackupGpoName "MSFT Windows Server 2022 - Member Server" -TargetGuid $GPO.id
Anstatt die GPO schon vorher anzulegen kann dies mit dem Parameter -CreateIfNeeded
in einem Schritt gemacht werden.
Import-GPO -Path "C:\Users\Fabian\Downloads\Windows Server-2022-Security-Baseline-FINAL\GPOs" -BackupGpoName "MSFT Windows Server 2022 - Domain Controller" -TargetName "MSFT Windows Server 2022 - Domain Controller" -CreateIfNeeded
Beim Import einer GPO kann auch eine Mapping Datei angegeben werden. Diese übersetzt z.B. SIDs von einer Domäne in die andere.
Import-GPO -Path "C:\Users\Fabian\Downloads\Windows Server-2022-Security-Baseline-FINAL\GPOs" -BackupGpoName "MSFT Windows Server 2022 - Domain Controller" -TargetName "MSFT Windows Server 2022 - Domain Controller" -CreateIfNeeded -MigrationTable C:\Users\Fabian\Documents\DomainA2DomainB.migtable
Die benötigte .migtable
Datei muss dabei manuell erstellt werden. Hier empfiehlt es sich eventuell doch einmal die GUI zu nutzen und das entsprechende Mapping für die zukünftige Nutzung zu speichern. Wer darauf keine Lust hat kann die Datei auch leicht von Hand erstellen. Es handelt sich um eine XML Datei wie in diesem Beispiel zu sehen.
<?xml version="1.0" encoding="utf-16"?>
<MigrationTable xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.microsoft.com/GroupPolicy/GPOOperations/MigrationTable">
<Mapping>
<Type>Computer</Type>
<Source>COMPUTER01</Source>
<Destination>COMPUTER02</Destination>
</Mapping>
<Mapping>
<Type>User</Type>
<Source>Administrator</Source>
<Destination>SuperAdmin</Destination>
</Mapping>
</MigrationTable>
Report erstellen
Ähnlich wie in der GUI kann man sich die Konfiguration einer Gruppenrichtlinie ausgeben lassen. Dabei können jedoch unterschiedliche Formate gewählt werden.
- HTML = Der aus der MMC bekannt Report der im Browser angesehen werden kann
- XML = Ausgabe im XML Formart. Dies ermöglicht es z.B. die Informationen mittels PowerShell weiter zu verarbeiten.
Get-GPOReport -Name "MSFT Windows Server 2022 - Member Server" -ReportType Html -Path .\Desktop\Report.html
Get-GPOReport -Name "MSFT Windows Server 2022 - Member Server" -ReportType Xml -Path .\Desktop\Report.xml
Get-GPOReport
ist leider nicht sehr performant, weswegen ich das cmdlet nicht für Auswertungen über viele Gruppenrichtlinien empfehlen kann.OU Link erstellen und verändern
Damit eine GPO überhaupt erst angewendet wird, muss diese mit einer oder mehrerer OUs, Domänen oder Sites verknüpft werden. New-GPLink
erledigt dies zuverlässig. Will man anschließend diese Verknüpfung anpassen ist dies mit Set-GPLink
leicht möglich. Das erleichtert z.B. die Anpassung der Link Order ungemein.
$GPO = Get-Gpo -Name "MSFT Windows Server 2022 - Member Server"
# Create a new link
New-GPLink -Guid $GPO.Id -Target "OU=DemoOU,$((Get-ADDomain).DistinguishedName)" -LinkEnabled Yes -Order 1
# Change existing link
Set-GPLink -Guid $GPO.Id -Target "OU=DemoOU,$((Get-ADDomain).DistinguishedName)" -LinkEnabled No
Enforced
wird die Einstellungen dieser Gruppenrichtlinie immer angewendet unabhängig von der “Link Order” oder unterbrochener Vererbung.Set-GPLink -Guid $GPO.Id -Target "OU=DemoOU,$((Get-ADDomain).DistinguishedName)" -Enforced Yes
Link entfernen
Ebenso einfach lässt sich eine solche Verknüpfung wieder entfernen.
Remove-GPLink -Guid $GPO.Id -Target "OU=DemoOU,$((Get-ADDomain).DistinguishedName)"
Zugewiesene Gruppenrichtlinien ermitteln
Um herauszufinden welche GPO an einer bestimmten OU überhaupt wirken wird Get-GPInheritance
genutzt.
Get-GPInheritance "OU=DemoOU,$((Get-ADDomain).DistinguishedName)"
Name : demoou
ContainerType : OU
Path : ou=demoou,dc=lab,dc=bader,dc=cloud
GpoInheritanceBlocked : No
GpoLinks : {}
InheritedGpoLinks : {Default Domain Policy}
Vererbung unterbrechen
Set-GPInheritance "OU=DemoOU,$((Get-ADDomain).DistinguishedName)" -IsBlocked Yes
Name : demoou
ContainerType : OU
Path : ou=demoou,dc=lab,dc=bader,dc=cloud
GpoInheritanceBlocked : Yes
GpoLinks : {}
InheritedGpoLinks : {}
WMI Filter zuweisen
Das Erstellen von WMI Filtern ist leider über die PowerShell nicht mit nativen cmdlets möglich. Natürlich hat die Community nachgelegt und ein entsprechendes Modul zu Verfügung gestellt. GPWmiFilter von Friedrich Weinmann.
Was nativ jedoch möglich ist, ist es wenn ein WMI schon in Verwendung ist, diesen einer weiteren GPO zuzuweisen.
# Get WMI filter from existing GPO
$WMIFilter = Get-GPO -Name "SourceGPO" | Select-Object -ExpandProperty WmiFilter
# Get target GPO ...
$GPO = Get-GPO -Name "MSFT Windows Server 2022 - Member Server"
# ... an apply the WMI filter
$GPO.WmiFilter = $WMIFilter
Berechtigungen auslesen
Um die Berechtigungen auszulesen die einer Gruppenrichtlinie zugewiesen sind, sollte Get-GPPermission
genutzt werden. Auch hier ist wieder möglich alle auszulesen, oder nur für eine benannte Gruppe oder AD Objekt.
Get-GPPermission -Name "MSFT Windows Server 2022 - Member Server" -All
Trustee : Authenticated Users
TrusteeType : WellKnownGroup
Permission : GpoApply
Inherited : False
Trustee : Domain Admins
TrusteeType : Group
Permission : GpoEditDeleteModifySecurity
Inherited : False
Trustee : Enterprise Admins
TrusteeType : Group
Permission : GpoEditDeleteModifySecurity
Inherited : False
Trustee : ENTERPRISE DOMAIN CONTROLLERS
TrusteeType : WellKnownGroup
Permission : GpoRead
Inherited : False
Trustee : SYSTEM
TrusteeType : WellKnownGroup
Permission : GpoEditDeleteModifySecurity
Inherited : False
Get-GPPermission -Name "MSFT Windows Server 2022 - Member Server" -TargetType Group
Trustee : Authenticated Users
TrusteeType : WellKnownGroup
Permission : GpoApply
Inherited : False
Berechtigungen setzen
Soll eine Gruppenrichtlinie nur einer speziellen Gruppe an Personen zugewiesen werden muss z.B. immer die Berechtigung der Authenticated Users verändert werden. Diese dürfen unter keinen Umständen einfach entfernt werden.
Der Standardmodus des cmdlets Set-GPPermission
ist additiv, die benannten Rechte werden hinzugefügt. Sollten schon höhere Rechte vorhanden sein, bleiben diese bestehen. Daher ist die korrekte Verwendung des Parameters -Replace
wichtig.
$GPO = Get-Gpo -Name "MSFT Windows 11 - User"
Set-GPPermission -Guid $GPO.Id -PermissionLevel GpoApply -TargetType Group -TargetName "Windows 11 Users"
Set-GPPermission -Name $GPO.Id -PermissionLevel GpoRead -TargetType Group -TargetName "Authenticated Users" -Replace
Dasselbe cmdlet wird auch verwendet wenn Berechtigungen entfernt werden sollen. Hier wird als PermissionLevel
None angegeben und der Parameter -Replace
genutzt.
Set-GPPermission -Guid $GPO.Id -PermissionLevel None -TargetName "Windows 11 Users" -TargetType Group -Replace
Backup
Eine Sicherung der Gruppenrichtlinien ist mit Backup-GPO
sehr einfach. Es wird für jedes Backup ein neues Verzeichnis mit einer GUID erstellt und alle relevanten Daten in diesem Verzeichnis gespeichert. Eine regelmäßige Sicherung aller GPOs ist damit kein Problem.
Get-GPO -All | Backup-GPO -Path C:\GPOBackup\ -Comment "$(Get-Date)"
Werte auslesen
Um einzelne Werte aus einer GPO auszulesen gibt es zwei cmdlets: Get-GPPrefRegistryValue
und Get-GPRegistryValue
.
Der Unterschied der beiden cmdlets besteht darin, Art von Registry Wert sie aus der Gruppenrichtlinie auslesen.
Get-GPPrefRegistryValue
liest Werte aus, die unterhalb von Computer -> Preferences -> Windows Settings -> Registry angelegt wurden. Dies sind nicht die Werte die in der GUI über ADMX Dateien gesteuert werden, sondern Werte die man manuell hinzufügt. Sie sind nicht auf HKEY_LOCAL_(MACHINE|USER)\SOFTWARE\Policies\
beschränkt.
Get-GPRegistryValue
ist alles was über eine ADMX Datei in der registry.pol
gespeichert wird. Dies ist in den meisten Fällen der Bereich den man auch bearbeiten möchte.
Unter Angabe des Registry -Key
können alle Werte in diesem ausgelesen werden.
Get-GPRegistryValue -Guid $GPO.Id -Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service\"
KeyPath : SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
FullKeyPath : HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
Hive : LocalMachine
PolicyState : Set
Value : 0
Type : DWord
ValueName : AllowBasic
HasValue : True
KeyPath : SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
FullKeyPath : HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
Hive : LocalMachine
PolicyState : Set
Value : 0
Type : DWord
ValueName : AllowUnencryptedTraffic
HasValue : True
KeyPath : SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
FullKeyPath : HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
Hive : LocalMachine
PolicyState : Set
Value : 1
Type : DWord
ValueName : DisableRunAs
HasValue : True
Get-GPRegistryValue -Guid $GPO.Id -Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service\" -ValueName AllowBasic
KeyPath : SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
FullKeyPath : HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
Hive : LocalMachine
PolicyState : Set
Value : 0
Type : DWord
ValueName : AllowBasic
HasValue : True
Werte setzen
Mittels Set-GPRegistryValue
lassen sich einzelne Werte in der GPO auch verändern. Somit ist zum setzen von neuen Einstellungen nicht mehr die MMC notwendig, sondern nur noch das Wissen in welchem Registry Key sich welche Einstellung verbirgt.
Hierbei ist die Webseite admx.help eine große Hilfe. Für fast alle ADMX Dateien werden die entsprechenden Werte aufbereitet dargestellt und die notwendigen Informationen zu “Registry Path” und Value Name/Type und möglichen Werten aufgeschlüsselt.
Hier am Beispiel der Einstellung Turn off real-time protection
Set-GPRegistryValue -Name 'MSFT Windows Server 2022 - Member Server' -Key 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection' -ValueName 'DisableRealtimeMonitoring' -Type DWord -Value 0
Werte recursive auslesen
Da es mit dem nativen cmdlet Get-GPRegistryValue
nicht möglich ist mehr als eine Ebene auszulesen, habe ich inspiriert von diesem Snippet eine Funktion erstellt die dies erlaubt. So können alle Einstellungen einer Gruppenrichtlinie als PolicyRegistrySetting Objekte auszugeben und direkt weiterverarbeitet werden. Dies ist um ein vielfaches schneller als das cmdlet Get-GPOReport
.
function Get-GPRegistryValueRecurse {
[CmdletBinding()]
param (
[Alias('DisplayName')]
[Parameter(Mandatory = $true,
ValueFromPipelineByPropertyName = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$Key
)
# Remove trailing backslash
$Key = $Key -replace '\\$'
$RegistryItems = Get-GPRegistryValue -Name $Name -Key $key
Write-Verbose "Found $($RegistryItems.Count) items"
foreach ($RegistryItem in $RegistryItems) {
if ( $RegistryItem -is [Microsoft.GroupPolicy.PolicyRegistrySetting] ) {
# Output the registry item
$RegistryItem
Write-Verbose "Found registry item: $($RegistryItem.Name)"
} elseif ( $RegistryItem -is [Microsoft.GroupPolicy.RegistryItem]) {
Write-Verbose "Found registry key: $($RegistryItem.FullKeyPath)"
# Go deeper
Get-GPRegistryValueRecurse -Key $RegistryItem.FullKeyPath -Name $Name
}
}
}
Beispielhafte Anwendung mit Pipelining
$GPO | Get-GPRegistryValueRecurse -Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Client\"
Gruppenrichtlinien zusammenführen
Mit dem eben Gelernten lässt sich auch ein weiteres Problem leicht lösen: Wie kann man zwei Gruppenrichtlinien in zusammenführen?
Da die GUI nur den Import anbietet, diese Funktion aber alle bestehenden Einstellungen überschreibt bleibt auch hier nur der Griff zur PowerShell.
Im folgenden Beispiel lese ich erst rekursiv alle Werte unterhalb des Registry Keys HKLM\SOFTWARE\Policies\Microsoft\Windows Defender\
aus, um diese anschließend mittels Set-GPRegistryValue
in die schon bestehenden GPO “MSFT Windows Server 2022 - Member Server” zu übernehmen.
# Retrieve all settings from a specific registry key
$SourceSettings = Get-GPRegistryValueRecurse -Name "MSFT Windows Server 2022 - Defender Antivirus" -Key "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender\"
# Define target GPO name
$TargetGPOName = "MSFT Windows Server 2022 - Member Server"
foreach ($Setting in $SourceSettings) {
if (-not [string]::isNullOrWhitespace($Setting ) ) {
# Replace double backslash if present
$TargetKey = $Setting.FullKeyPath -replace '\\\\', '\'
if ($Setting.PolicyState -eq "Delete") {
Set-GPRegistryValue -Name $TargetGPOName -Key $TargetKey -ValueName $($Setting.ValueName) -Disable
} else {
Set-GPRegistryValue -Name $TargetGPOName -Key $TargetKey -ValueName $($Setting.ValueName) -Type $($Setting.Type) -Value $($Setting.Value)
}
}
}
Jedoch nicht alle Werte, sondern nur Werte die in Konflikt mit der Quell GPO stehen.
Dieses Beispiel lässt sich sehr leicht anpassen um alle “Computer” Werte zu übernehmen.
$SourceSettings = Get-GPRegistryValueRecurse -Name "MSFT Windows Server 2022 - Defender Antivirus" -Key "HKLM\SOFTWARE\"
Firewalleinstellungen bearbeiten
Um die Windows Defender Firewall Einstellungen bearbeiten zu können taugt keiner der oben genannten Befehle. Jedoch hat Microsoft noch zwei weitere cmdlets, besser gesagt Function, im Petto.
PS C:\Users\Fabian> Get-Command *gpo* | ? Source -ne GroupPolicy
CommandType Name Version Source
----------- ---- ------- ------
Function Open-NetGPO 2.0.0.0 NetSecurity
Function Save-NetGPO 2.0.0.0 NetSecurity
Application chgport.exe 10.0.22... C:\Windows\system32\chgport.exe
Open-NetGPO
erstellt eine WMI Session zu einer bestehenden Gruppenrichtlinie und erlaubt es dann, diese mit den normalen cmdlets um Firewallregeln zu verwalten zu nutzen. Die WMI Session muss dabei immer an den Parameter -GPOSession
übergeben werden.
-GPOSession
in der Windows 11 von Get-NetFirewallRule
nicht mehr vorhanden. Hier kann alternativ -PolicyStore
genutzt werden.New-GPO -Name "GPO_Server_Windows_Firewall"
$gpoSession = Open-NetGPO -PolicyStore lab.bader.cloud\GPO_Server_Windows_Firewall
# Windows until 11
Get-NetFirewallRule -GPOSession $gpoSession
# Windows 11
Get-NetFirewallRule -PolicyStore $gpoSession
# Add outbound DNS queries to 8.8.8.8
New-NetFirewallRule -GPOSession $gpoSession -DisplayName "Allow traffic to Google" -Action Allow -Direction Outbound -RemoteAddress 8.8.8.8 -Protocol Udp -RemotePort 53
# Save changes to GPO
Save-NetGPO -GPOSession $gpoSession
# Check if changes where made correctly
$gpoSession = Open-NetGPO -PolicyStore lab.bader.cloud\GPO_Server_Windows_Firewall
Get-NetFirewallRule -PolicyStore $gpoSession
Auswertungen über alle GPOs
Mir kam immer wieder folgende Problemstellung unter: In welcher Gruppenrichtlinie ist einer oder mehrere Einstellungen gesetzt und wenn ja mit welchem Wert.
Die einzige Antwort die ich bisher im Internet gefunden habe, war die Nutzung von Get-GPOReport
mit der Umwandlung als XML und anschließender Auswertung der XML Dateien. Leider ist das sehr sehr langsam, bei mehreren hundert, vielleicht sogar tausenden GPOs in der Umgebung ist dies keine echte Lösung.
Daher habe ich das Skript CheckGPOSettings.ps1
erstellt.
Dieses Skript analysiert anhand einer übergebenen Hashtable alle Gruppenrichtlinien in einer oder auch mehrere Domains nach einem oder mehrere Werte und liefert die Ergebnisse als PowerShell Objekt zurück. Dadurch können diese sehr einfach weiter verarbeitet werden. Und das Beste ist, es werden alle typischen Speicherorte innerhalb der GPO durchsucht. Egal ob Get-GPRegistryValue
, GptTmpl.inf
oder Get-GPPrefRegistryValue
, das Script findet sie alle.
audit.csv
nicht unterstützt.Query Hashtable
Die Hashtable die für die Suche genutzt wird, besteht aus zwei verschachtelten Hashtables. Die äußere nutzt als Key einen frei wählbaren Namen für den gesuchten Wert. Hier sollte z.B. der sprechende Name der Einstellung genutzt werden.
Als Value wird ein weiteres Hashtable verwendet, dieses beschreibt den zu suchenden Wert. Als Key wird hier der Registry Key genutzt und als Value den Value Name des Registry Items.
$CheckSettings = @{
"Unique setting name for the report. Choose something you can remember like the display name of the setting" = @{
# Key = The path to the registry key
"Key" = "HKLM\SOFTWARE\Policies\Microsoft\PassportForWork"
# ValueName = The name of the registry value
"ValueName" = "Enabled"
}
}
In folgendem Beispiel suche ich zwei verschiedene Registry Settings. Das erste ist das LAN Manager Authentication Level (steht hoffentlich auf 5) und das zweite ist der Wert für den Service MrxSmb10
besser bekannt als SMBv1. hier ist als Wert 4 wünschenswert (Deaktiviert).
$CheckSettings = @{
"Network security: LAN Manager authentication level" = @{
"Key" = "HKLM\System\CurrentControlSet\Control\Lsa"
"ValueName" = "LmCompatibilityLevel"
}
"SMBv1 service state" = @{
"Key" = "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MrxSmb10"
"ValueName" = "Start"
}
}
Anschließend starte ich die Funktion Get-SettingsFromGPOs
und übergebe die zu prüfenden Domain und das eben erstelle Hashtable.
C:\Users\Fabian> Get-SettingsFromGPOs -Domain "lab.bader.cloud" -CheckSetting $CheckSettings
Als Ergebnis bekomme ich folgenden Informationen geliefert:
- In welcher Domäne ist die Gruppenrichtlinie vorhanden
- Wie lautet der Name der Gruppenrichtlinie
- Wo ist diese Gruppenrichtlinie verknüpft*
- Angewendeten WMI Filter
- Den Pfad zur GPO
- aktueller Status der GPO (Enabled/Disabled)
- Den selbstgewählten Namen für die Einstellung
- Den Registry Key
- Den Namen des RegistryItem
- Den Wert des RegistryItem
- Den Typ des RegistryItem
DomainName : lab.bader.cloud
GPO : MSFT Windows Server 2022 - Domain Controller
GPOLinks :
Setting : Network security: LAN Manager authentication level
ValueName : LmCompatibilityLevel
Hive : HKLM\System\CurrentControlSet\Control\Lsa
WmiFilter :
PolicyState :
Value : 5
Type : REG_DWORD
Path : cn={1C09EB8B-1EB0-488B-A92C-34030213F58B},cn=policies,cn=system,DC=lab,DC=bader,DC=cloud
DomainName : lab.bader.cloud
GPO : MSFT Windows Server 2022 - Domain Controller
GPOLinks :
Setting : SMBv1 service state
ValueName : Start
Hive : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MrxSmb10
WmiFilter :
PolicyState : Set
Value : 4
Type : DWord
Path : cn={1C09EB8B-1EB0-488B-A92C-34030213F58B},cn=policies,cn=system,DC=lab,DC=bader,DC=cloud
* Die GPLinks kann ich aktuell nur unter Verwendung des cmdlets Get-GPReport
herausfinden. Dieses wird aber immer nur dann gestartet, wenn der gesuchte Wert in der Gruppenrichtlinie gefunden wurde. Für zusätzliche Performance habe ich den Schalten -NoGPLink
eingebaut. Dieser hat in meiner kleinen Demoumgebung die Ausführungszeit von 776ms auf 568ms verbessert. In besonders großen Umgebungen kann sich das also lohnen.
In diesem diesem GitHub Repository findet Ihr weitere Beispiele und das Repository steht für Pull Requests offen. So kann über die Zeit eine Sammlung an Suchparametern zusammengetragen werden.
Fazit
Mit der PowerShell lassen sich Gruppenrichtlinien sehr umfangreich manipulieren und wie so häufig spart dies viel Zeit. Leider ist der Einstieg nicht ganz so einfach wie bei anderen cmdlets, aber wenn man das Grundkonzept durchschaut hat lassen sich damit viele tolle Sache realisieren.
Wer genau aufgepasst hat, wird bemerkt haben das es bestimmte cmdlets nicht in den Blogartikel geschafft haben. Das hat entweder den Grund das diese selbsterklärend sind (Copy-GPO
), der Gegenpart vorgestellt wurde (Remove-GPRegistryValue
) oder ich diese einfach nicht nutze (*-GPStarterGPO
).
Daher fehlen Beispiele für folgende cmdlets
Copy-GPO
Get-GPStarterGPO
Invoke-GPUpdate
New-GPStarterGPO
Remove-GPPrefRegistryValue
Remove-GPRegistryValue
Rename-GPO
Restore-GPO