Lister les GPO Vide

Suite à la découverte d’une GPO vide, nous nous sommes demandé combien nos admins en avaient créé. Il était bien sur hors de question de vérifier à la main et une par une les très nombreuse GPO de notre ActiveDirectory. Du coup, goto powershell!

En utilisant le module GroupPolicy, nous pouvons obtenir facilement la liste des GPOs :

Get-GPO -All

Comment trouver les GPO vides ?

Nous avons d’abord essayé avec Get-GPRegistryValue mais nous ne pouvions obtenir la liste des “Paramètres Windows”, du coup nous nous sommes tournés vers Get-GPOReport qui permets de dumper les paramètres de GPO en xml. L’un des gros avantages est que Powershell gère nativement le XML.

PS > get-gporeport -Name MaGPO -ReportType XML
<?xml version="1.0" encoding="utf-16"?>
<GPO (...)> 
(some information ...)
  <Computer>
    <VersionDirectory>X</VersionDirectory>
    <VersionSysvol>X</VersionSysvol>
    <Enabled>true</Enabled>
    <extensionData>(settings GPO Computer)</extensionData>
  </Computer>
  <User>
    <VersionDirectory>X</VersionDirectory>
    <VersionSysvol>X</VersionSysvol>
    <Enabled>true</Enabled>
    <extensionData>(settings GPO User)</extensionData>
  </User>
</GPO>

La présence du nœud “entensionData” sous les nœuds Computer et User permettent de s’assurer de la présence ou non de paramètre dans la GPO. Voici un exemple de vérification

 (get-gporeport -Name MaGPO -ReportType XML).GPO.Computer.extensionData -ne $null

Nous avons 2 noeuds à vérifier et il la génération du rapport à un coût. Le cmdlet Where-Object accepte le parametre -FilterScript qui nous permet de spécifier un script de filtrage et donc de ne générer qu’une seule fois le report

Where-Object -FilterScript ({
    $gpo = get-gporeport -Name $_.DisplayName -ReportType xml 
    $gpo.GPO.Computer.ExtensionData -eq $null -and $gpo.GPO.User.ExtensionData -eq $null
 })

En mettant le tout ensemble :

get-gpo -All |?({ $gpo = get-gporeport -Name $_.DisplayName -ReportType xml; $gpo.GPO.Computer.ExtensionData -eq $null -and $gpo.GPO.User.ExtensionData -eq $null}) | select DisplayName

Cependant l’utilisation du module GroupPolicy et surtout la génération du rapport (get-gporeport) utilise beaucoup trop de ressource. L’objet AD contient un champs gPCFileSysPath qui contient le chemin du paramétrage sur le sysvol, ce répertoire en contient au moins 2 autres User et Machine qui contiennent le paramétrage de la GPO.

Le check devient donc :

Get-ADObject -Filter 'ObjectClass -eq "groupPolicyContainer"' -SearchBase 'CN=Policies,CN=System,DC=fabrikam,DC=com' |% { Get-Adobject $_.distinguishedName -properties * } |?{ [bool]( gci "$($_.gPCFileSysPath)\User") -eq $false -and [bool](gci "$($_.gPCFileSysPath)\Machine") -eq $false } | select DisplayName