Filtrage de sécurité et filtrage WMI¶
Ce que couvre ce chapitre
- La structure DACL d'une GPO et les deux permissions requises — Read et Apply Group Policy — pour qu'une GPO s'applique
- Le GUID
edacfd8f-ffb3-11d1-b41d-00a0c968f939de la permission Apply Group Policy et comment le lire dans un ACL AD - Le piège classique de la suppression d'Authenticated Users : pourquoi cela casse le traitement côté machine et comment l'éviter
- La technique du filtrage par exclusion avec DENY et ses limites opérationnelles
- L'architecture des filtres WMI : objet AD
msWMI-Som, localisation dansCN=SOM,CN=WMIPolicy, évaluation côté client - La sémantique des requêtes WQL : TRUE = GPO appliquée, FALSE ou erreur = GPO ignorée
- Les Event IDs 5313, 5320 et 5321 pour diagnostiquer les refus de filtrage dans le journal opérationnel Group Policy
Si vous ne retenez qu'une chose
Le filtrage de sécurité contrôle QUI la GPO s'applique. Le filtrage WMI contrôle DANS QUEL CONTEXTE elle s'applique. Les deux sont évalués côté client — supprimer "Authenticated Users" sans ajouter un groupe de remplacement casse le traitement machine.
Les ACL d'une GPO : ce que GPMC ne montre pas¶
Une GPO est un objet AD avec une DACL¶
Dans Active Directory, chaque GPO est représentée par un objet de classe groupPolicyContainer. Comme tout objet AD, il porte une liste de contrôle d'accès discrétionnaire — une DACL.
C'est cette DACL qui implémente le filtrage de sécurité. GPMC la présente dans l'onglet "Delegation" ou "Security Filtering", mais ce n'est qu'une vue simplifiée d'une structure ACL standard.
Deux entrées ACE sont nécessaires pour qu'une GPO s'applique à un principal :
- Read — permet de lire les métadonnées et paramètres de la GPO
- Apply Group Policy — la permission effective qui déclenche l'application
Les deux doivent être présentes. Read seul : le principal voit la GPO dans GPMC mais elle ne s'applique pas. Apply Group Policy seul : la GPO ne peut pas être lue, donc elle ne s'applique pas non plus.
Le GUID de la permission Apply Group Policy
La permission "Apply Group Policy" est une extended right AD identifiée par le GUID edacfd8f-ffb3-11d1-b41d-00a0c968f939. Ce GUID est défini dans le schéma AD et est identique dans tous les domaines. Vous le retrouvez dans les ACL en utilisant Get-Acl sur le chemin AD de la GPO.
Le comportement par défaut¶
Par défaut, toute nouvelle GPO accorde Read et Apply Group Policy au groupe Authenticated Users.
Ce groupe inclut tous les utilisateurs et ordinateurs authentifiés dans le domaine. C'est intentionnel : une GPO liée à une OU s'applique à tous les objets de cette OU, sans distinction.
Modifier ce comportement est l'essence même du filtrage de sécurité.
En résumé
Une GPO s'applique à un principal si et seulement si ce principal possède les deux permissions Read et Apply Group Policy sur l'objet AD de la GPO. Par défaut, Authenticated Users possède les deux — ce qui signifie que toute GPO liée s'applique à tout le monde dans l'OU.
Lire le filtrage de sécurité en PowerShell¶
Via les cmdlets GroupPolicy¶
Le module GroupPolicy expose une cmdlet dédiée pour lire les permissions :
Get-GPPermissions -Name "CFG-Postes-EnvironnementBureau" -All |
Select-Object Trustee, Permission, Inherited |
Format-Table -AutoSize
Trustee Permission Inherited
------- ---------- ---------
CONTOSO\Domain Admins GpoEditDeleteModifySecurity False
CONTOSO\Enterprise Admins GpoEditDeleteModifySecurity False
CONTOSO\GRP-Postes-Std GpoApply False
NT AUTHORITY\Authenticated Users GpoRead False
BUILTIN\SYSTEM GpoApply False
La valeur GpoApply correspond à la permission "Apply Group Policy". La valeur GpoRead correspond à Read seul.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Via les cmdlets GroupPolicy - l'artefact technique à savoir relire sans chercher : GroupPolicy - la commande ou l'étape de validation à pouvoir rejouer en labo : Get-GPPermissions -Name "CFG-Postes-EnvironnementBureau" -All |
Via les ACL AD brutes¶
Pour obtenir le GUID de la permission et l'ACL complète :
# Retrieve the GPO's AD path first
$gpo = Get-GPO -Name "CFG-Postes-EnvironnementBureau"
$gpoDN = "CN={$($gpo.Id.ToString().ToUpper())},CN=Policies,CN=System,$(
(Get-ADDomain).DistinguishedName)"
# Read the full ACL
$acl = Get-Acl -Path "AD:$gpoDN"
$acl.Access |
Select-Object IdentityReference, ActiveDirectoryRights, AccessControlType |
Format-Table -AutoSize
IdentityReference ActiveDirectoryRights AccessControlType
----------------- --------------------- -----------------
CONTOSO\GRP-Postes-Std ExtendedRight Allow
NT AUTHORITY\Authenticated Users GenericRead Allow
BUILTIN\SYSTEM ExtendedRight Allow
ExtendedRight = Apply Group Policy
Dans la DACL AD brute, la permission "Apply Group Policy" apparaît comme ExtendedRight. Son GUID spécifique — edacfd8f-ffb3-11d1-b41d-00a0c968f939 — est encodé dans le champ ObjectType de l'ACE, visible uniquement avec $acl.Access | Where-Object { $_.ObjectType -eq 'edacfd8f-ffb3-11d1-b41d-00a0c968f939' }.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Via les ACL AD brutes - l'artefact technique à savoir relire sans chercher : ExtendedRight - la commande ou l'étape de validation à pouvoir rejouer en labo : $gpo = Get-GPO -Name "CFG-Postes-EnvironnementBureau"
En résumé
Get-GPPermissions est la méthode rapide pour le quotidien. Get-Acl sur le chemin AD donne accès aux GUIDs bruts, utile pour les audits et l'automatisation avancée.
Supprimer Authenticated Users : le piège classique¶
Ce que GPMC fait automatiquement¶
Quand vous ajoutez un groupe spécifique dans l'onglet "Security Filtering" de GPMC — par exemple GRP-Postes-Standard — GPMC supprime automatiquement Authenticated Users de la liste.
C'est le comportement par défaut de l'interface. C'est aussi la source d'un problème très courant en production.
Le problème du traitement machine¶
Le compte ordinateur s'authentifie au démarrage de la machine, avant qu'un utilisateur ne se connecte. À ce stade, il n'appartient qu'aux groupes de sécurité dont il est membre directement — et notamment à Authenticated Users.
Si une GPO contient des paramètres dans Computer Configuration et que vous avez remplacé Authenticated Users par un groupe d'utilisateurs (GRP-Postes-Standard par exemple), le compte machine ne peut plus lire la GPO. Le traitement côté machine échoue silencieusement.
Le résultat : tous les paramètres Computer Configuration — politiques de sécurité, scripts de démarrage, configuration réseau — ne s'appliquent plus.
Le diagnostic est trompeur
L'Event ID 5313 apparaît dans le journal opérationnel Group Policy, mais uniquement si le compte machine peut accéder au contrôleur de domaine. Si le problème est détecté, il indique "Access denied" sur la GPO. Dans les cas silencieux, gpresult /h montre simplement que la GPO n'est pas dans la liste des GPO appliquées, sans explication claire.
La règle des trois cas¶
Avant de modifier le filtrage de sécurité d'une GPO, identifiez ce qu'elle contient :
| Contenu de la GPO | Action recommandée |
|---|---|
| Computer Configuration uniquement | Garder Authenticated Users ou remplacer par un groupe d'ordinateurs |
| User Configuration uniquement | Remplacer Authenticated Users par un groupe d'utilisateurs — c'est sûr |
| Les deux sections | Utiliser deux groupes distincts — un pour les ordinateurs, un pour les utilisateurs |
La meilleure pratique est de désactiver la section inutilisée dans les propriétés de la GPO. Une GPO "Computer only" avec la section User Configuration désactivée est plus claire et plus performante.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - les repères de lecture du tableau précédent : Contenu de la GPO, Action recommandée - la valeur, le GUID ou le paramètre qui change réellement le résultat dans La règle des trois cas - le contrôle terrain à effectuer avant de passer à la suite de La règle des trois cas
Corriger le filtrage en PowerShell¶
# Grant GpoApply to the computer group
Set-GPPermissions -Name "CFG-Postes-EnvironnementBureau" `
-TargetName "GRP-Ordinateurs-Standard" `
-TargetType Group `
-PermissionLevel GpoApply
# Downgrade Authenticated Users to Read-only (admins can still browse settings in GPMC)
Set-GPPermissions -Name "CFG-Postes-EnvironnementBureau" `
-TargetName "Authenticated Users" `
-TargetType Group `
-PermissionLevel GpoRead
Trustee Permission Inherited
------- ---------- ---------
CONTOSO\GRP-Ordinateurs-Standard GpoApply False
NT AUTHORITY\Authenticated Users GpoRead False
Pourquoi garder Read pour Authenticated Users ?
Même si vous filtrez sur un groupe spécifique, conserver GpoRead pour Authenticated Users permet aux administrateurs de voir les paramètres de la GPO dans GPMC depuis n'importe quel poste. Sans Read, la GPO apparaît dans la liste mais les paramètres sont inaccessibles pour les non-propriétaires.
# Audit script: list all GPOs where Authenticated Users has GpoApply
Get-GPO -All | ForEach-Object {
$gpo = $_
$perms = Get-GPPermissions -Guid $gpo.Id -All -ErrorAction SilentlyContinue
$authUsers = $perms | Where-Object {
$_.Trustee.Name -eq "Authenticated Users" -and
$_.Permission -eq "GpoApply"
}
if (-not $authUsers) {
[PSCustomObject]@{
GPOName = $gpo.DisplayName
Status = "Authenticated Users NOT in GpoApply — verify computer group"
}
}
} | Format-Table -AutoSize
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Corriger le filtrage en PowerShell - l'artefact technique à savoir relire sans chercher : GpoRead - la commande ou l'étape de validation à pouvoir rejouer en labo : `Set-GPPermissions -Name "CFG-Postes-EnvironnementBureau" ``
En résumé
Supprimer Authenticated Users du filtrage sans ajouter un groupe d'ordinateurs casse le traitement Computer Configuration. Vérifiez toujours le contenu de la GPO avant de modifier son filtrage. Conservez au minimum GpoRead pour Authenticated Users pour préserver la visibilité dans GPMC.
Filtrage par exclusion : le DENY¶
:material-logic-and: La logique du DENY¶
Le filtrage de sécurité ne sert pas uniquement à cibler — il peut aussi exclure. La technique consiste à positionner un ACE DENY sur la permission Apply Group Policy pour un groupe spécifique.
Cas d'usage typique : appliquer une GPO à tous les utilisateurs de l'OU, sauf les administrateurs.
Authenticated Userspossède Read + Apply Group Policy- Le groupe
GRP-Admins-ITpossède un DENY sur Apply Group Policy
Résultat : tout utilisateur membre de GRP-Admins-IT ne reçoit pas la GPO, même s'il est dans Authenticated Users.
DENY est prioritaire — sans exception
Un DENY l'emporte toujours sur un ALLOW, quelle que soit l'appartenance aux groupes. Un administrateur qui est simultanément dans Authenticated Users (Allow) et dans GRP-Admins-IT (Deny) ne recevra pas la GPO. Vérifiez les adhésions transitives avant d'ajouter un DENY.
Limites de Set-GPPermissions avec DENY¶
La cmdlet Set-GPPermissions ne supporte pas nativement les ACE DENY. Pour ajouter un refus explicite, deux options :
Option 1 — GPMC GUI : onglet Delegation → Advanced → sélectionner le groupe → cocher Deny sur "Apply Group Policy".
Option 2 — API .NET :
# Add an explicit DENY ACE on Apply Group Policy for a group
# Apply Group Policy extended right GUID
$applyGpGuid = [Guid]"edacfd8f-ffb3-11d1-b41d-00a0c968f939"
$gpo = Get-GPO -Name "CFG-Utilisateurs-BureauStandard"
$gpoDN = "CN={$($gpo.Id.ToString().ToUpper())},CN=Policies,CN=System,$(
(Get-ADDomain).DistinguishedName)"
$acl = Get-Acl -Path "AD:$gpoDN"
# Resolve the group SID
$groupSid = (Get-ADGroup -Identity "GRP-Admins-IT").SID
# Build the DENY ACE for the extended right
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$groupSid,
[System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight,
[System.Security.AccessControl.AccessControlType]::Deny,
$applyGpGuid
)
$acl.AddAccessRule($ace)
Set-Acl -Path "AD:$gpoDN" -AclObject $acl
Write-Host "DENY ACE added for GRP-Admins-IT on $($gpo.DisplayName)"
DENY et comptes SYSTEM
Ne jamais ajouter un DENY qui affecte SYSTEM ou Domain Controllers. Ces comptes ont besoin d'accéder aux GPO pour le traitement background des politiques de sécurité. Un DENY mal ciblé peut bloquer le traitement sur tous les contrôleurs de domaine.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Limites de Set-GPPermissions avec DENY - l'artefact technique à savoir relire sans chercher : Set-GPPermissions - la commande ou l'étape de validation à pouvoir rejouer en labo : $applyGpGuid = [Guid]"edacfd8f-ffb3-11d1-b41d-00a0c968f939"
En résumé
Le DENY est un outil chirurgical pour les exclusions. Il prend la priorité sur tous les Allow, y compris les héritages de groupe. L'API .NET est nécessaire pour le scripting car Set-GPPermissions ne gère pas les ACE DENY. Utilisez cette technique avec parcimonie et documentez chaque DENY explicitement.
Les filtres WMI : architecture et fonctionnement¶
Qu'est-ce qu'un filtre WMI ?¶
Un filtre WMI est un objet Active Directory distinct de la GPO. Il appartient à la classe msWMI-Som et réside dans le conteneur :
Chaque filtre contient une ou plusieurs requêtes WQL (WMI Query Language). Une GPO peut être associée à au plus un filtre WMI.
L'association est stockée dans l'attribut gPCWQLFilter de l'objet GPO. Sa valeur est un chemin LDAP vers l'objet msWMI-Som.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Qu'est-ce qu'un filtre WMI ? - l'artefact technique à savoir relire sans chercher : msWMI-Som - la commande ou l'étape de validation à pouvoir rejouer en labo : CN=SOM,CN=WMIPolicy,CN=System,DC=contoso,DC=local
Le processus d'évaluation¶
Voici ce qui se passe quand gpsvc traite une GPO associée à un filtre WMI :
- Le client récupère la liste des GPO applicables depuis
gPLink(comme d'habitude) - Pour chaque GPO avec un filtre WMI,
gpsvcexécute la requête WQL localement - La requête s'exécute contre le service WMI local de la machine — pas contre le DC
- Si la requête retourne au moins une ligne → résultat TRUE → GPO appliquée
- Si la requête retourne zéro ligne → résultat FALSE → GPO ignorée
- Si WMI retourne une erreur → GPO ignorée (comportement identique à FALSE)
Évaluation côté client : implication importante
Le DC ne sait pas si le filtre WMI va retourner TRUE ou FALSE pour une machine donnée. Il envoie la GPO au client dans tous les cas — c'est le client qui décide. Cela signifie que les filtres WMI n'économisent pas de bande passante réseau sur le téléchargement initial de la GPO.
Diagramme de décision¶
flowchart TD
A["gpsvc : liste des GPO applicables
depuis gPLink"] --> B{"Filtrage de sécurité
Read + Apply GP ?"}
B -->|"Non — ACL refusée"| C["Event 5313
GPO ignorée"]
B -->|Oui| D{"Filtre WMI
associé ?"}
D -->|Non| F["GPO appliquée"]
D -->|Oui| E{"Requête WQL
= TRUE ?"}
E -->|"Non — Event 5320 FALSE"| C
E -->|"Erreur WMI — Event 5321"| C
E -->|"Oui — Event 5320 TRUE"| F
style C fill:#c0392b,color:#fff
style F fill:#27ae60,color:#fff Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Diagramme de décision - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Diagramme de décision - la commande ou l'étape de validation à pouvoir rejouer en labo : flowchart TD
En résumé
Un filtre WMI est un objet AD distinct qui contient une requête WQL. L'évaluation est entièrement côté client. Un résultat vide ou une erreur WMI bloque l'application de la GPO. Le DC est transparent à ce processus.
Requêtes WQL pratiques¶
Catalogue de requêtes¶
| Cas d'usage | Namespace | Requête WQL |
|---|---|---|
| Windows 11 uniquement | root\CIMv2 | SELECT * FROM Win32_OperatingSystem WHERE Version >= "10.0.22000" |
| Windows 10 uniquement | root\CIMv2 | SELECT * FROM Win32_OperatingSystem WHERE Version LIKE "10.0.%" AND Version < "10.0.22000" |
| Windows Server 2022 | root\CIMv2 | SELECT * FROM Win32_OperatingSystem WHERE Version >= "10.0.20348" AND ProductType != 1 |
| Portables uniquement | root\CIMv2 | SELECT * FROM Win32_SystemEnclosure WHERE ChassisTypes = 9 OR ChassisTypes = 10 OR ChassisTypes = 14 |
| Stations fixes uniquement | root\CIMv2 | SELECT * FROM Win32_SystemEnclosure WHERE ChassisTypes = 3 OR ChassisTypes = 4 OR ChassisTypes = 6 |
| RAM ≥ 8 Go | root\CIMv2 | SELECT * FROM Win32_ComputerSystem WHERE TotalPhysicalMemory >= 8589934592 |
| Processeur ≥ 4 cœurs logiques | root\CIMv2 | SELECT * FROM Win32_Processor WHERE NumberOfLogicalProcessors >= 4 |
| Architecture 64 bits | root\CIMv2 | SELECT * FROM Win32_Processor WHERE AddressWidth = 64 |
| Logiciel installé (méthode rapide) | root\CIMv2 | SELECT * FROM Win32_InstalledWin32Program WHERE Name LIKE "%Microsoft 365%" |
| Langue du système | root\CIMv2 | SELECT * FROM Win32_OperatingSystem WHERE MUILanguages = "fr-FR" |
| Membre d'un domaine DNS spécifique | root\CIMv2 | SELECT * FROM Win32_NTDomain WHERE DnsForestName = "contoso.local" |
| Batterie présente | root\CIMv2 | SELECT * FROM Win32_Battery WHERE BatteryStatus > 0 |
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - les repères de lecture du tableau précédent : Cas d'usage, Namespace, Requête WQL - l'artefact technique à savoir relire sans chercher : root\CIMv2 - le second repère technique à retenir avant de continuer : SELECT * FROM Win32_OperatingSystem WHERE Version >= "10.0.22000"
Tester une requête WQL localement¶
Avant de créer un filtre WMI en production, testez toujours la requête sur une machine cible :
# Test a WQL query locally before deploying as a WMI filter
$namespace = "root\CIMv2"
$query = "SELECT * FROM Win32_OperatingSystem WHERE Version >= '10.0.22000'"
$result = Get-WmiObject -Namespace $namespace -Query $query -ErrorAction SilentlyContinue
if ($result) {
Write-Host "WMI filter result: TRUE — GPO would apply on this machine"
$result | Select-Object Caption, Version | Format-Table
} else {
Write-Host "WMI filter result: FALSE — GPO would NOT apply on this machine"
}
WMI filter result: TRUE — GPO would apply on this machine
Caption Version
------- -------
Microsoft Windows 11 Professionnel 10.0.22631
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Tester une requête WQL localement - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Tester une requête WQL localement - la commande ou l'étape de validation à pouvoir rejouer en labo : $namespace = "root\CIMv2"
Win32_Product : la requête interdite¶
Win32_Product est une classe WMI qui liste les logiciels installés. Elle semble parfaite pour filtrer sur la présence d'une application.
Ne l'utilisez jamais dans un filtre WMI de GPO.
Chaque interrogation de Win32_Product déclenche une réparation MSI complète pour chaque application installée. Sur une machine avec 50 applications, cela peut prendre plusieurs minutes. Ce comportement se produit sur chaque cycle de traitement GPO — toutes les 90 à 120 minutes.
Alternatives acceptables :
# Option 1: Win32_InstalledWin32Program (faster, no MSI reconfigure)
$query1 = "SELECT * FROM Win32_InstalledWin32Program WHERE Name LIKE '%Microsoft 365%'"
# Option 2: Registry-based detection (fastest)
# Check in HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
# or HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
$query2 = "SELECT * FROM Win32_OperatingSystem" # placeholder — use ILT for registry
# Note: for registry-based software detection, prefer Item-Level Targeting (Ch. 12)
# over WMI filters — ILT can query registry keys directly without performance impact
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Win32_Product : la requête interdite - l'artefact technique à savoir relire sans chercher : Win32_Product - la commande ou l'étape de validation à pouvoir rejouer en labo : $query1 = "SELECT * FROM Win32_InstalledWin32Program WHERE Name LIKE '%Microsoft 365%'"
En résumé
Les requêtes WQL couvrent un large spectre : version OS, type de machine, matériel, langue, domaine. N'utilisez jamais Win32_Product — le coût en performance est prohibitif. Testez toujours votre requête localement avant de créer le filtre en production.
Créer et associer un filtre WMI¶
Absence de cmdlet native¶
Il n'existe pas de cmdlet PowerShell native dans le module GroupPolicy pour créer des filtres WMI. GPMC GUI permet de les créer interactivement, mais pour l'automatisation, il faut passer par l'API AD directement.
Fonction de création via l'API AD¶
function New-GPWmiFilter {
<#
.SYNOPSIS
Creates a WMI filter object in Active Directory.
.PARAMETER Name
Display name of the WMI filter.
.PARAMETER Description
Description stored in msWMI-Parm1.
.PARAMETER Namespace
WMI namespace for the query (default: root\CIMv2).
.PARAMETER Query
WQL query string.
#>
param(
[Parameter(Mandatory)][string]$Name,
[string]$Description = "",
[string]$Namespace = "root\CIMv2",
[Parameter(Mandatory)][string]$Query
)
$domain = (Get-ADDomain).DistinguishedName
$wmiFilterPath = "CN=SOM,CN=WMIPolicy,CN=System,$domain"
# Generate a unique GUID for the filter object name
$guid = [System.Guid]::NewGuid().ToString("B").ToUpper()
$now = (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmmss.ffffff-000")
# msWMI-Parm2 format: "<version>;<filtercount>;<reserved>;<querylen>;WQL;<namespace>;<query>;"
$parm2 = "1;3;10;$($Query.Length);WQL;$Namespace;$Query;"
$attributes = @{
"msWMI-Name" = $Name
"msWMI-Parm1" = $Description
"msWMI-Parm2" = $parm2
"msWMI-Author" = "$env:USERNAME@$env:USERDNSDOMAIN"
"msWMI-CreationDate" = $now
"msWMI-ChangeDate" = $now
"msWMI-ID" = $guid
"showInAdvancedViewOnly" = $true
}
New-ADObject -Name $guid `
-Type "msWMI-Som" `
-Path $wmiFilterPath `
-OtherAttributes $attributes `
-ErrorAction Stop
Write-Host "WMI filter created: '$Name' — GUID: $guid"
return $guid
}
# Create a filter for Windows 11 machines only
$filterId = New-GPWmiFilter `
-Name "WMI - Windows 11 Only" `
-Description "Apply only to Windows 11 machines (build 22000+)" `
-Query "SELECT * FROM Win32_OperatingSystem WHERE Version >= '10.0.22000'"
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Fonction de création via l'API AD - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Fonction de création via l'API AD - la commande ou l'étape de validation à pouvoir rejouer en labo : function New-GPWmiFilter {
Associer le filtre à une GPO¶
function Set-GPWmiFilterLink {
<#
.SYNOPSIS
Associates an existing WMI filter with a GPO.
.PARAMETER GPOName
Display name of the target GPO.
.PARAMETER WmiFilterName
Display name of the WMI filter to link.
#>
param(
[Parameter(Mandatory)][string]$GPOName,
[Parameter(Mandatory)][string]$WmiFilterName
)
$domain = (Get-ADDomain).DistinguishedName
$wmiFilterPath = "CN=SOM,CN=WMIPolicy,CN=System,$domain"
# Find the WMI filter object by display name (msWMI-Name attribute)
$filter = Get-ADObject -SearchBase $wmiFilterPath `
-Filter { ObjectClass -eq "msWMI-Som" } `
-Properties "msWMI-Name","msWMI-ID" |
Where-Object { $_."msWMI-Name" -eq $WmiFilterName }
if (-not $filter) {
throw "WMI filter '$WmiFilterName' not found in $wmiFilterPath"
}
# Build the gPCWQLFilter value: ["<domain>\SOM\{GUID}";]
$filterRef = "[`"$domain\SOM\$($filter.Name)`";]"
# Update the GPO AD object
$gpo = Get-GPO -Name $GPOName
$gpoDN = "CN={$($gpo.Id.ToString().ToUpper())},CN=Policies,CN=System,$domain"
Set-ADObject -Identity $gpoDN -Replace @{ "gPCWQLFilter" = $filterRef }
Write-Host "WMI filter '$WmiFilterName' linked to GPO '$GPOName'"
}
Supprimer l'association d'un filtre WMI
Pour dissocier un filtre WMI d'une GPO, utilisez Set-ADObject -Identity $gpoDN -Clear gPCWQLFilter. Ne supprimez jamais l'objet msWMI-Som tant qu'une GPO y fait référence — la GPO deviendrait en état d'erreur et serait ignorée par tous les clients.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Associer le filtre à une GPO - l'artefact technique à savoir relire sans chercher : "$domain\SOM\$($filter.Name) - la commande ou l'étape de validation à pouvoir rejouer en labo : function Set-GPWmiFilterLink {
En résumé
La création de filtres WMI requiert l'API AD directement. Le format msWMI-Parm2 est strict. L'association GPO ↔ filtre se fait via l'attribut gPCWQLFilter de l'objet GPO. Documentez chaque filtre créé : GPMC les affiche mais ne donne pas toujours le contexte métier de leur existence.
Performance : filtrage de sécurité vs filtrage WMI¶
Tableau comparatif¶
| Critère | Filtrage de sécurité | Filtre WMI |
|---|---|---|
| Évaluation | Côté DC (lecture des ACL AD) | Côté client (requête WMI locale) |
| Performance | Très rapide — lecture ACL en mémoire AD | Variable — de quelques ms à plusieurs secondes |
| Granularité | Par appartenance groupe AD | Par propriété machine (OS, matériel, logiciel) |
| Maintenance | Gérer les adhésions de groupes AD | Maintenir les requêtes WQL |
| Visibilité GPMC | Onglet "Security Filtering" | Conteneur "WMI Filters" |
| Event log succès/échec | Event 5313 (refus) | Events 5320 (résultat) et 5321 (erreur) |
| Impact bande passante | Réduit — GPO non envoyée si ACL refusée | Aucune économie — GPO envoyée avant évaluation |
| Adapté pour | Cibler un sous-ensemble d'utilisateurs ou d'ordinateurs | Cibler une configuration matérielle ou logicielle |
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - les repères de lecture du tableau précédent : Critère, Filtrage de sécurité, Filtre WMI - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Tableau comparatif - le contrôle terrain à effectuer avant de passer à la suite de Tableau comparatif
Quand utiliser quoi¶
Utilisez le filtrage de sécurité pour toutes les questions d'"à qui" :
- Ces paramètres ne s'appliquent qu'aux postes du service Comptabilité
- Cette GPO ne doit pas s'appliquer aux administrateurs
- Déployer un logiciel sur un groupe d'ordinateurs pilotes
Utilisez un filtre WMI pour toutes les questions de "dans quel contexte" :
- Ces paramètres ne s'appliquent qu'aux machines Windows 11
- Cette GPO ne doit s'appliquer qu'aux portables (batterie présente)
- Activer une fonctionnalité uniquement sur les machines avec assez de RAM
Ne les substituez pas l'un à l'autre. Un filtre WMI qui vérifie l'appartenance à une OU est fonctionnellement équivalent au filtrage de sécurité mais 10 à 100 fois plus lent.
Accumulation de filtres WMI
Chaque filtre WMI ajoute une requête WMI à chaque cycle de traitement. Sur un domaine avec 100 GPO liées et 30 filtres WMI actifs, chaque machine exécute 30 requêtes WMI supplémentaires à chaque cycle background. Mesurez l'impact en production avant de déployer massivement.
En résumé
Le filtrage de sécurité est plus rapide et doit être privilégié pour le ciblage par audience. Le filtrage WMI est réservé au ciblage contextuel (matériel, OS, logiciel). Évitez Win32_Product, limitez le nombre de filtres WMI actifs et mesurez leur impact sur les temps de traitement GPO.
Diagnostic du filtrage : Event IDs et outils¶
Tableau des Event IDs¶
| Event ID | Journal | Signification | Action recommandée |
|---|---|---|---|
| 5313 | GP Operational | GPO non appliquée — filtrage de sécurité refusé (accès refusé à l'ACL) | Vérifier les permissions Read et Apply GP sur la GPO |
| 5320 | GP Operational | Résultat d'évaluation du filtre WMI (TRUE ou FALSE) | Inspecter le message pour voir quelle requête a retourné FALSE |
| 5321 | GP Operational | Échec d'évaluation du filtre WMI (erreur WMI) | Vérifier le service WMI sur le client (winmgmt) |
| 5312 | GP Operational | Liste des GPO applicables récupérée avec succès | Contexte normal — utile pour corréler avec 5313 |
| 5314 | GP Operational | GPO ignorée en raison d'un filtre WMI — résultat FALSE | Complément de 5320 |
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - les repères de lecture du tableau précédent : Event ID, Journal, Signification - l'artefact technique à savoir relire sans chercher : winmgmt - le contrôle terrain à effectuer avant de passer à la suite de Tableau des Event IDs
Interroger le journal opérationnel¶
# Query the Group Policy Operational log for filtering-related events
Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" `
-MaxEvents 2000 -ErrorAction SilentlyContinue |
Where-Object { $_.Id -in @(5313, 5320, 5321, 5314) } |
Select-Object TimeCreated, Id,
@{
Name = "Summary"
Expression = {
# Extract the first meaningful line from the event message
($_.Message -split "`n" |
Where-Object { $_ -match "GPO|WMI|filter|policy|denied" } |
Select-Object -First 2) -join " | "
}
} |
Format-Table -AutoSize -Wrap
TimeCreated Id Summary
----------- -- -------
2024-11-15 08:32:14 5313 The GPO did not apply because it was not applicable. | Reason: The user does not have permission...
2024-11-15 08:32:15 5320 WMI filter evaluation was successful. Result: FALSE. | Filter: WMI - Windows 11 Only
2024-11-15 08:32:16 5320 WMI filter evaluation was successful. Result: TRUE. | Filter: WMI - Portables Only
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Interroger le journal opérationnel - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Interroger le journal opérationnel - la commande ou l'étape de validation à pouvoir rejouer en labo : `Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" ``
Vérifier l'état des filtres WMI sur un domaine¶
$domain = (Get-ADDomain).DistinguishedName
$wmiFilterPath = "CN=SOM,CN=WMIPolicy,CN=System,$domain"
Get-ADObject -SearchBase $wmiFilterPath `
-Filter { ObjectClass -eq "msWMI-Som" } `
-Properties "msWMI-Name","msWMI-Parm1","msWMI-Parm2","msWMI-Author","msWMI-ChangeDate" |
Select-Object `
@{N="Name"; E={ $_."msWMI-Name" }},
@{N="Description"; E={ $_."msWMI-Parm1" }},
@{N="Author"; E={ $_."msWMI-Author" }},
@{N="LastChanged"; E={ $_."msWMI-ChangeDate" }},
@{N="Query"; E={
# Extract the WQL query from the msWMI-Parm2 encoded string
$parts = $_."msWMI-Parm2" -split ";"
if ($parts.Count -ge 7) { $parts[6] } else { $_."msWMI-Parm2" }
}} |
Format-Table -AutoSize -Wrap
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Vérifier l'état des filtres WMI sur un domaine - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Vérifier l'état des filtres WMI sur un domaine - la commande ou l'étape de validation à pouvoir rejouer en labo : $domain = (Get-ADDomain).DistinguishedName
gpresult : voir le filtrage dans le rapport HTML¶
La commande gpresult capture l'état du traitement GPO sur une machine, y compris les GPO refusées et la raison :
# Generate a full HTML report on the local machine
gpresult /h "$env:TEMP\gpreport.html" /f
Start-Process "$env:TEMP\gpreport.html"
# For a remote machine (requires admin rights and WinRM)
gpresult /s NOM-POSTE /h "$env:TEMP\gpreport-remote.html" /f
# Console output: denied GPOs section
gpresult /r | Select-String -Pattern "Denied|Filtered|WMI" -Context 1,1
Section « GPOs inapplicables » dans gpresult
Le rapport HTML de gpresult contient une section "GPO(s) not applied because they were filtered out". Chaque entrée précise la raison : "Inaccessible (Access Denied)" pour un refus ACL, ou "Denied (WMI Filter)" pour un filtre WMI évalué à FALSE.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : gpresult : voir le filtrage dans le rapport HTML - l'artefact technique à savoir relire sans chercher : gpresult - la commande ou l'étape de validation à pouvoir rejouer en labo : gpresult /h "$env:TEMP\gpreport.html" /f
En résumé
Les Event IDs 5313 (ACL refusée), 5320 (résultat WMI) et 5321 (erreur WMI) sont vos premiers alliés pour diagnostiquer un problème de filtrage. gpresult /h donne le tableau de bord complet du traitement GPO sur un poste, avec la liste des GPO refusées et leur motif.
Recettes opérationnelles courantes¶
:material-recipe: Recette 1 — Déploiement progressif (pilote → production)¶
Objectif : appliquer une GPO à 10 % des postes en phase pilote, puis l'étendre.
# Step 1: Create the pilot group and add test machines
New-ADGroup -Name "GRP-Postes-Pilotes-GPO-X" `
-GroupScope DomainLocal `
-GroupCategory Security `
-Path "OU=Groupes,DC=contoso,DC=local"
# Add pilot machines to the group
Add-ADGroupMember -Identity "GRP-Postes-Pilotes-GPO-X" `
-Members "POSTE-TEST-01$","POSTE-TEST-02$"
# Step 2: Configure GPO security filtering for pilot group only
Set-GPPermissions -Name "CFG-NouvelleConfiguration" `
-TargetName "GRP-Postes-Pilotes-GPO-X" `
-TargetType Group `
-PermissionLevel GpoApply
Set-GPPermissions -Name "CFG-NouvelleConfiguration" `
-TargetName "Authenticated Users" `
-TargetType Group `
-PermissionLevel GpoRead # Read only — no apply
Write-Host "Pilot filtering configured. Link the GPO to the OU when ready."
Pour passer en production : remplacer GRP-Postes-Pilotes-GPO-X par Authenticated Users en GpoApply via Set-GPPermissions.
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Recette 1 — Déploiement progressif (pilote → production) - l'artefact technique à savoir relire sans chercher : GRP-Postes-Pilotes-GPO-X - la commande ou l'étape de validation à pouvoir rejouer en labo : `New-ADGroup -Name "GRP-Postes-Pilotes-GPO-X" ``
:material-recipe: Recette 2 — GPO par OS avec filtre WMI¶
Objectif : maintenir deux versions d'une GPO — une pour Windows 10, une pour Windows 11.
# Create WMI filters for OS targeting
$win10Guid = New-GPWmiFilter `
-Name "WMI - Windows 10 Only" `
-Description "Apply to Windows 10 machines (build < 22000)" `
-Query "SELECT * FROM Win32_OperatingSystem WHERE Version LIKE '10.0.%' AND Version < '10.0.22000'"
$win11Guid = New-GPWmiFilter `
-Name "WMI - Windows 11 Only" `
-Description "Apply to Windows 11 machines (build >= 22000)" `
-Query "SELECT * FROM Win32_OperatingSystem WHERE Version >= '10.0.22000'"
# Link filters to their respective GPOs
Set-GPWmiFilterLink -GPOName "CFG-Win10-ParametresUI" -WmiFilterName "WMI - Windows 10 Only"
Set-GPWmiFilterLink -GPOName "CFG-Win11-ParametresUI" -WmiFilterName "WMI - Windows 11 Only"
Write-Host "WMI filters created and linked. Both GPOs can be linked to the same OU."
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Recette 2 — GPO par OS avec filtre WMI - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Recette 2 — GPO par OS avec filtre WMI - la commande ou l'étape de validation à pouvoir rejouer en labo : `$win10Guid = New-GPWmiFilter ``
:material-recipe: Recette 3 — Audit complet du filtrage sur un domaine¶
$domain = (Get-ADDomain).DistinguishedName
$wmiFilterPath = "CN=SOM,CN=WMIPolicy,CN=System,$domain"
# Build a lookup table of WMI filter GUIDs to names
$wmiFilters = @{}
Get-ADObject -SearchBase $wmiFilterPath `
-Filter { ObjectClass -eq "msWMI-Som" } `
-Properties "msWMI-Name" |
ForEach-Object { $wmiFilters[$_.Name] = $_."msWMI-Name" }
Get-GPO -All | Sort-Object DisplayName | ForEach-Object {
$gpo = $_
# Get security filtering
$perms = Get-GPPermissions -Guid $gpo.Id -All -ErrorAction SilentlyContinue
$applyTargets = ($perms |
Where-Object { $_.Permission -eq "GpoApply" } |
ForEach-Object { $_.Trustee.Name }) -join ", "
# Get WMI filter link from AD object
$gpoDN = "CN={$($gpo.Id.ToString().ToUpper())},CN=Policies,CN=System,$domain"
$gpoObj = Get-ADObject -Identity $gpoDN -Properties "gPCWQLFilter" -ErrorAction SilentlyContinue
$wmiLink = "None"
if ($gpoObj."gPCWQLFilter") {
# Extract GUID from the gPCWQLFilter attribute value
if ($gpoObj."gPCWQLFilter" -match "\{([A-F0-9\-]+)\}") {
$filterGuid = $Matches[1]
$wmiLink = if ($wmiFilters[$filterGuid]) { $wmiFilters[$filterGuid] } else { $filterGuid }
}
}
[PSCustomObject]@{
GPOName = $gpo.DisplayName
Status = $gpo.GpoStatus
ApplyTargets = if ($applyTargets) { $applyTargets } else { "(none)" }
WMIFilter = $wmiLink
}
} | Format-Table -AutoSize -Wrap
Point de contrôle
Avant de continuer, vérifiez que vous avez bien compris : - le but précis de cette sous-section : Recette 3 — Audit complet du filtrage sur un domaine - la valeur, le GUID ou le paramètre qui change réellement le résultat dans Recette 3 — Audit complet du filtrage sur un domaine - la commande ou l'étape de validation à pouvoir rejouer en labo : $domain = (Get-ADDomain).DistinguishedName
En résumé
Les recettes opérationnelles couvrent les cas les plus fréquents : déploiement progressif via groupes pilotes, ciblage par OS avec filtres WMI, et audit complet du domaine. Combinez filtrage de sécurité (pour l'audience) et filtre WMI (pour le contexte) pour un ciblage précis sans prolifération de GPO.
Références croisées¶
| Sujet | Référence |
|---|---|
| Héritage LSDOU et ordre d'application | Ch. 08 — Héritage et ordre d'application |
| Item-Level Targeting (alternative aux filtres WMI pour GPP) | Ch. 12 — Item-Level Targeting |
| Diagnostic complet avec RSOP et gpresult | Ch. 20 — RSOP et diagnostic |
| Impact des filtres WMI sur les performances | Ch. 23 — Performances |
| Audit des permissions GPO en environnement sécurisé | Les GPO pour les Admins — Audits et gouvernance |
En résumé
- À relire : Héritage LSDOU et ordre d'application → Ch. 08 — Héritage et ordre d'application.
- À relire : Item-Level Targeting (alternative aux filtres WMI pour GPP) → Ch. 12 — Item-Level Targeting.
- À relire : Diagnostic complet avec RSOP et gpresult → Ch. 20 — RSOP et diagnostic.
- À relire : Impact des filtres WMI sur les performances → Ch. 23 — Performances.
- À relire : Ch. 08 — Héritage et ordre d'application.