Les stratégies de groupe (Group Policy Objects - GPO) constituent un mécanisme central dans Windows Server 2022 pour gérer et configurer de manière centralisée les paramètres des ordinateurs et des utilisateurs dans un environnement Active Directory. Elles permettent aux administrateurs de définir des politiques de sécurité, de déployer des logiciels, d'exécuter des scripts et de configurer l'environnement de travail des utilisateurs de façon uniforme et automatisée.
L'application des GPO suit un ordre hiérarchique précis, connu sous l'acronyme LSDOU :
L - Local : Les stratégies de groupe locales s'appliquent en premier. Elles sont stockées directement sur chaque ordinateur et constituent le premier niveau de configuration.
S - Site : Les GPO liées au site Active Directory s'appliquent ensuite. Un site représente un emplacement physique dans l'infrastructure réseau.
D - Domain (Domaine) : Les stratégies liées au domaine s'appliquent après celles du site. Elles affectent tous les objets du domaine, sauf indication contraire.
OU - Organizational Unit (Unité d'Organisation) : Les GPO liées aux unités d'organisation s'appliquent en dernier et peuvent remplacer les paramètres précédents. Si plusieurs OU sont imbriquées, l'ordre d'application va de la plus éloignée à la plus proche de l'objet.
Principe important : En cas de conflit entre plusieurs GPO, c'est le dernier paramètre appliqué qui prévaut. Ainsi, une GPO liée à une OU peut remplacer un paramètre défini au niveau du domaine.
Ordre d'application des GPO multiples : Lorsque plusieurs GPO sont liées au même niveau (par exemple, plusieurs GPO sur une même OU), elles s'appliquent de bas en haut dans la liste affichée dans la console GPMC. La GPO située en haut de la liste a donc la priorité la plus élevée.
La Group Policy Management Console (GPMC) est l'outil graphique principal pour administrer les stratégies de groupe dans Windows Server 2022.
Installation de GPMC : Sur Windows Server 2022, GPMC s'installe automatiquement lors de la promotion du serveur en contrôleur de domaine. Pour l'installer manuellement sur un serveur membre ou un poste d'administration (en powershell) :
Install-WindowsFeature GPMC
Accès à GPMC :
gpmc.mscInterface et fonctionnalités principales :
L'interface GPMC se compose de plusieurs sections :
Forêt : Niveau racine affichant la forêt Active Directory et ses domaines.
Domaines : Contient les domaines de la forêt avec leur structure d'unités d'organisation.
Objets de stratégie de groupe : Dossier central contenant toutes les GPO créées dans le domaine. C'est ici que les GPO sont physiquement stockées.
Filtres WMI : Permet de créer des requêtes WMI pour appliquer conditionnellement des GPO en fonction des caractéristiques matérielles ou logicielles.
Objets GPO Starter : Modèles de GPO prédéfinis servant de base à la création de nouvelles stratégies.
Fonctionnalités clés de GPMC :
Les GPO Starter (objets de stratégie de groupe de démarrage) sont des modèles de GPO qui contiennent une collection prédéfinie de paramètres de modèles d'administration. Ils servent de point de départ pour créer de nouvelles GPO avec des configurations standardisées.
Avantages des GPO Starter :
Création d'une GPO Starter :
Utilisation d'une GPO Starter :
Lors de la création d'une nouvelle GPO, vous pouvez sélectionner une GPO Starter comme modèle source :
Gestion des GPO Starter :
# Sauvegarder une GPO Starter Backup-GPStarterGPO -Name "Modèle Sécurité" -Path "C:\GPOBackup" # Créer une GPO depuis un Starter New-GPO -Name "GPO Production" -StarterGPOName "Modèle Sécurité"
Remarque importante : Les GPO Starter ne contiennent que des paramètres de modèles d'administration (registre). Elles n'incluent pas les paramètres de sécurité, les scripts ou les préférences.
Les Client-Side Extensions (CSE) sont des composants DLL qui s'exécutent sur les ordinateurs clients pour traiter et appliquer les différents types de paramètres contenus dans les GPO.
Fonctionnement des CSE :
Lorsqu'un ordinateur démarre ou qu'un utilisateur ouvre une session, le service Client de stratégie de groupe télécharge les GPO applicables depuis le contrôleur de domaine. Les CSE appropriées sont ensuite invoquées pour traiter chaque section de la GPO.
Principales CSE dans Windows Server 2022 :
| Extension | GUID | Fonction |
|---|---|---|
| Registry | {35378EAC-683F-11D2-A89A-00C04FBBCFA2} | Applique les paramètres du registre |
| Security | {827D319E-6EAC-11D2-A4EA-00C04F79F83A} | Configure les politiques de sécurité |
| Scripts | {42B5FAAE-6536-11D2-AE5A-0000F87571E3} | Exécute les scripts de démarrage/arrêt |
| Folder Redirection | {25537BA6-77A8-11D2-9B6C-0000F8080861} | Redirige les dossiers utilisateurs |
| Software Installation | {C6DC5466-785A-11D2-84D0-00C04FB169F7} | Déploie les applications |
| Group Policy Preferences | {00000000-0000-0000-0000-000000000000} | Traite les préférences |
Traitement des CSE :
Les CSE peuvent fonctionner de deux manières :
Traitement synchrone : Les extensions s'exécutent les unes après les autres. L'utilisateur doit attendre la fin du traitement avant d'accéder à son bureau. Ce mode garantit que tous les paramètres sont appliqués avant le début de la session.
Traitement asynchrone : Les extensions s'exécutent en arrière-plan pendant que l'utilisateur accède à son bureau. Plus rapide, mais certains paramètres peuvent ne pas être immédiatement disponibles.
Configuration du traitement :
Le comportement peut être contrôlé via les paramètres de stratégie :
Diagnostic des CSE :
Pour vérifier quelles CSE ont été traitées en powershell :
# Afficher le dernier traitement des GPO gpresult /r
# Générer un rapport détaillé HTML gpresult /h rapport.html
# Forcer la mise à jour des GPO gpupdate /force
Journalisation des CSE :
Les événements liés au traitement des CSE sont enregistrés dans l'Observateur d'événements :
Intervalles de rafraîchissement :
Par défaut, les GPO sont rafraîchies selon les intervalles suivants :
Ces intervalles peuvent être modifiés via la stratégie "Intervalle d'actualisation de la stratégie de groupe pour les ordinateurs/utilisateurs".
Le traitement en boucle (Loopback Processing) est une fonctionnalité avancée des stratégies de groupe qui modifie le comportement normal d'application des GPO utilisateur. Dans des circonstances normales, les paramètres utilisateur proviennent des GPO liées à l'emplacement de l'objet utilisateur dans Active Directory. Le traitement en boucle permet d'appliquer des paramètres utilisateur basés sur l'emplacement de l'ordinateur plutôt que sur celui de l'utilisateur.
Cas d'usage typiques :
Environnements de bureau partagés : Dans les salles de formation, bibliothèques ou espaces publics où différents utilisateurs se connectent sur les mêmes ordinateurs, il est nécessaire d'imposer une configuration uniforme indépendamment de l'identité de l'utilisateur.
Serveurs Terminal Server / RDS : Pour garantir une expérience cohérente sur les serveurs de sessions distantes, quelle que soit l'OU d'appartenance de l'utilisateur.
Postes à usage spécifique : Kiosques d'information, caisses enregistreuses ou stations de travail dédiées nécessitant des configurations verrouillées.
Salles de réunion : Ordinateurs de présentation où tous les utilisateurs doivent avoir les mêmes applications et restrictions.
Fonctionnement du traitement en boucle :
Sans traitement en boucle, le processus d'application suit ce schéma :
Avec le traitement en boucle activé :
Configuration du traitement en boucle :
Le paramètre se trouve dans :
Trois options sont disponibles :
Mode Fusion (Merge) :
Dans ce mode, les GPO utilisateur sont traitées dans l'ordre suivant :
Les GPO de l'ordinateur s'appliquent en dernier et ont donc la priorité en cas de conflit.
Exemple pratique - Mode Fusion :
Contexte :
Résultat en mode Fusion :
Si les deux GPO configuraient le même paramètre (ex : fond d'écran), c'est la GPO-Formation qui l'emporterait.
Mode Remplacer (Replace) :
Dans ce mode beaucoup plus restrictif :
Exemple pratique - Mode Remplacer :
Avec le même contexte que précédemment :
Résultat en mode Remplacer :
Comparaison des modes :
| Aspect | Mode Fusion | Mode Remplacer |
|---|---|---|
| GPO utilisateur originales | Appliquées en premier | Ignorées complètement |
| GPO utilisateur de l'ordinateur | Appliquées en second | Seules appliquées |
| Priorité en cas de conflit | GPO de l'ordinateur | N/A (pas de conflit possible) |
| Flexibilité | Plus grande | Plus restrictive |
| Usage recommandé | Environnements semi-partagés | Kiosques et postes verrouillés |
Configuration via PowerShell :
# Créer une GPO avec traitement en boucle en mode Fusion New-GPO -Name "GPO-BoucleFusion" -Comment "Mode Fusion activé" Set-GPRegistryValue -Name "GPO-BoucleFusion" `
-Key "HKLM\Software\Policies\Microsoft\Windows\System" `
-ValueName "UserPolicyMode" -Type DWord -Value 1
# Mode Remplacer (Value 2) Set-GPRegistryValue -Name "GPO-BoucleRemplacer" `
-Key "HKLM\Software\Policies\Microsoft\Windows\System" `
-ValueName "UserPolicyMode" -Type DWord -Value 2
Vérification du mode appliqué :
Pour vérifier quel mode est actif sur un poste en powershell :
# Afficher le résultat de stratégie gpresult /r /scope:user
# Dans la section "La stratégie de groupe a été appliquée depuis" # Si traitement en boucle actif, le nom de l'ordinateur apparaîtra
Considérations importantes :
La création et la liaison d'une GPO sont deux opérations distinctes qui peuvent être effectuées simultanément ou séparément.
Création d'une GPO via GPMC :
Méthode 1 - Création et liaison simultanées :
Méthode 2 - Création puis liaison séparée :
Création via PowerShell :
# Créer une GPO simple New-GPO -Name "GPO-Config-Serveurs" -Comment "Configuration des serveurs de production" # Créer et lier immédiatement à une OU New-GPO -Name "GPO-Users-RH" -Comment "Paramètres utilisateurs RH" |
New-GPLink -Target "OU=RessourcesHumaines,DC=entreprise,DC=local" # Créer depuis une GPO Starter New-GPO -Name "GPO-Standard-Desktop" -StarterGPOName "Modèle Desktop" # Lier une GPO existante New-GPLink -Name "GPO-Config-Serveurs" -Target "OU=Serveurs,DC=entreprise,DC=local" # Créer avec un ordre de lien spécifique (1 = priorité la plus haute) New-GPLink -Name "GPO-Securite-Critique" `
-Target "OU=Finance,DC=entreprise,DC=local" -LinkEnabled Yes -Order 1
Configuration initiale de la GPO :
Après création, il faut configurer les paramètres :
Structure des sections :
Chaque configuration (ordinateur/utilisateur) contient :
Stratégies :
Préférences :
Exemple de configuration complète en powershell :
# Créer une GPO de sécurité pour les postes de travail $GPOName = "GPO-Securite-Postes" $TargetOU = "OU=Postes,OU=Workstations,DC=entreprise,DC=local" # Création New-GPO -Name $GPOName -Comment "Politique de sécurité des postes de travail" # Liaison New-GPLink -Name $GPOName -Target $TargetOU -LinkEnabled Yes
# Configuration - Désactiver l'invite de commande Set-GPRegistryValue -Name $GPOName `
-Key "HKCU\Software\Policies\Microsoft\Windows\System" `
-ValueName "DisableCMD" -Type DWord -Value 1
# Configuration - Définir un fond d'écran Set-GPRegistryValue -Name $GPOName `
-Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "Wallpaper" -Type String -Value "\\serveur\partage\wallpaper.jpg" # Configuration - Complexité du mot de passe Set-GPRegistryValue -Name $GPOName `
-Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" `
-ValueName "PasswordComplexity" -Type DWord -Value 1
Bonnes pratiques de création :
Nommage cohérent : Adopter une convention de nommage claire (ex : GPO-[Type]-[Cible]-[Description])
Une GPO = Un objectif : Éviter les GPO fourre-tout. Préférer plusieurs GPO ciblées.
Documentation : Utiliser le champ "Commentaire" pour décrire l'objectif et le contexte.
Tests : Créer d'abord dans une OU de test avant déploiement en production.
Désactivation des sections inutiles : Si une GPO ne contient que des paramètres ordinateur, désactiver la section utilisateur pour optimiser le traitement.
# Désactiver la section utilisateur (Get-GPO -Name "GPO-Config-Serveurs").GpoStatus = "UserSettingsDisabled" # Désactiver la section ordinateur (Get-GPO -Name "GPO-Profils-Users").GpoStatus = "ComputerSettingsDisabled" # Désactiver complètement une GPO (Get-GPO -Name "GPO-Temporaire").GpoStatus = "AllSettingsDisabled"
Vérification après création :
# Lister toutes les GPO du domaine Get-GPO -All | Select-Object DisplayName, GpoStatus, CreationTime
# Afficher les liens d'une GPO Get-GPOReport -Name "GPO-Securite-Postes" -ReportType Html -Path "C:\Rapports\GPO.html" # Vérifier les paramètres configurés Get-GPRegistryValue -Name "GPO-Securite-Postes" -Key "HKCU\Software\Policies"
La suppression d'une liaison de GPO déconnecte la stratégie de groupe d'une unité d'organisation sans supprimer l'objet GPO lui-même. C'est une opération réversible et sans risque pour la GPO.
Distinction importante :
Suppression via GPMC :
Alternative :
Suppression via PowerShell :
# Supprimer un lien spécifique Remove-GPLink -Name "GPO-Config-Temporaire" `
-Target "OU=Test,DC=entreprise,DC=local" # Supprimer tous les liens d'une GPO Get-GPO -Name "GPO-Obsolete" | Remove-GPLink -Target * -Confirm:$false # Supprimer le lien avec confirmation Remove-GPLink -Name "GPO-Production" `
-Target "OU=Serveurs,DC=entreprise,DC=local" -Confirm
# Supprimer uniquement si le lien est désactivé $Link = Get-GPInheritance -Target "OU=Marketing,DC=entreprise,DC=local" $Link.GpoLinks | Where-Object {$_.Enabled -eq $false} | ForEach-Object { Remove-GPLink -Name $_.DisplayName -Target "OU=Marketing,DC=entreprise,DC=local" }
Désactivation temporaire d'un lien :
Plutôt que supprimer, il est souvent préférable de désactiver temporairement :
# Désactiver un lien Set-GPLink -Name "GPO-Maintenance" `
-Target "OU=Postes,DC=entreprise,DC=local" -LinkEnabled No
# Réactiver un lien Set-GPLink -Name "GPO-Maintenance" `
-Target "OU=Postes,DC=entreprise,DC=local" -LinkEnabled Yes
# Lister les liens désactivés Get-GPO -All | ForEach-Object { $gpo = $_ Get-GPInheritance -Target "OU=Postes,DC=entreprise,DC=local" |
Select-Object -ExpandProperty GpoLinks |
Where-Object {$_.Enabled -eq $false -and $_.DisplayName -eq $gpo.DisplayName} }
Vérification après suppression :
# Vérifier les GPO liées à une OU Get-GPInheritance -Target "OU=Finance,DC=entreprise,DC=local" |
Select-Object -ExpandProperty GpoLinks
# Vérifier où une GPO est encore liée (Get-GPO -Name "GPO-Securite").GpoLinks
# Générer un rapport des liens Get-GPOReport -All -ReportType Html -Path "C:\Rapports\Liens-GPO.html"
Impact de la suppression :
Après suppression d'un lien :
gpupdate /force sur les clients supprimera les paramètres (sauf certains paramètres de sécurité)Suppression définitive d'une GPO :
Si vous souhaitez réellement supprimer la GPO :
# Supprimer tous les liens puis la GPO Remove-GPO -Name "GPO-Obsolete" # Avec sauvegarde préalable Backup-GPO -Name "GPO-Archive" -Path "C:\Backups\GPO" -Comment "Avant suppression" Remove-GPO -Name "GPO-Archive"
Les filtres permettent d'affiner l'application des GPO en ciblant spécifiquement certains objets plutôt que tous les objets d'une OU. Windows Server 2022 propose trois mécanismes principaux de filtrage.
1. Filtrage de sécurité
Le filtrage de sécurité utilise les permissions pour contrôler quels utilisateurs ou ordinateurs peuvent appliquer une GPO.
Principe : Pour qu'une GPO s'applique, l'objet doit avoir les permissions "Lecture" ET "Appliquer la stratégie de groupe".
Configuration via GPMC :
Exemple pratique :
Objectif : Appliquer une GPO uniquement aux ordinateurs portables.
Via PowerShell :
# Supprimer les utilisateurs authentifiés Set-GPPermission -Name "GPO-Config-Portables" `
-TargetName "Utilisateurs authentifiés" -TargetType Group `
-PermissionLevel None
# Ajouter un groupe avec droit d'application Set-GPPermission -Name "GPO-Config-Portables" `
-TargetName "GRP-Portables" -TargetType Group `
-PermissionLevel GpoApply
# Créer un filtre pour les ordinateurs d'un site spécifique Set-GPPermission -Name "GPO-Site-Paris" `
-TargetName "GRP-Ordinateurs-Paris" -TargetType Group `
-PermissionLevel GpoApply
Exclusion d'objets :
Pour exclure certains objets de l'application d'une GPO :
# Refuser explicitement l'application à un groupe Set-GPPermission -Name "GPO-Standard" `
-TargetName "GRP-Admins-IT" -TargetType Group `
-PermissionLevel GpoApply -Replace $false # Puis définir le refus explicite (nécessite manipulation des ACL) $GPO = Get-GPO -Name "GPO-Standard" $GPO.SetSecurityInfo([Microsoft.GroupPolicy.GPPermissionType]::GpoApply,
"GRP-Admins-IT", [System.Security.AccessControl.AccessControlType]::Deny)
2. Filtres WMI
Les filtres WMI (Windows Management Instrumentation) permettent d'appliquer des GPO en fonction de critères matériels ou logiciels dynamiques.
Cas d'usage :
Création d'un filtre WMI :
Exemples de requêtes WMI courantes (en sql) :
-- Ordinateurs avec plus de 8 Go de RAM (8192 Mo) SELECT * FROM Win32_ComputerSystem WHERE TotalPhysicalMemory > 8589934592 -- Systèmes d'exploitation Windows 11 SELECT * FROM Win32_OperatingSystem WHERE Caption LIKE "%Windows 11%" -- Ordinateurs portables uniquement SELECT * FROM Win32_SystemEnclosure WHERE ChassisTypes = 8 OR ChassisTypes = 9 OR ChassisTypes = 10 -- Disque C: avec plus de 100 Go libres SELECT * FROM Win32_LogicalDisk WHERE DeviceID = "C:" AND FreeSpace > 107374182400 -- Machines virtuelles (Hyper-V) SELECT * FROM Win32_ComputerSystem WHERE Model LIKE "%Virtual%" -- Ordinateurs d'un site spécifique selon leur adresse IP SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPAddress LIKE "192.168.10.%" -- Processeurs avec plus de 4 cœurs SELECT * FROM Win32_Processor WHERE NumberOfCores > 4
Association du filtre WMI à une GPO :
# Créer un filtre WMI via PowerShell nécessite des manipulations ADSI # Voici un exemple pour Windows 11 uniquement $FilterName = "Windows11-Uniquement" $FilterDesc = "Applique uniquement aux postes Windows 11" $FilterQuery = "SELECT * FROM Win32_OperatingSystem WHERE Caption LIKE '%Windows 11%'" # Création (nécessite module spécifique ou script personnalisé) # La gestion WMI via PowerShell est limitée nativement
Association manuelle :
# Lier un filtre WMI existant (par manipulation de propriétés AD) $GPO = Get-GPO -Name "GPO-Config-Win11" $FilterGuid = (Get-ADObject -Filter "Name -eq 'Windows11-Uniquement'" `
-SearchBase "CN=SOM,CN=WMIPolicy,CN=System,DC=entreprise,DC=local").ObjectGUID
Set-ADObject -Identity $GPO.Path -Replace @{gPCWQLFilter=$FilterGuid}
Test d'un filtre WMI :
Sur un ordinateur client (en powershell):
# Tester une requête WMI localement Get-WmiObject -Query "SELECT * FROM Win32_ComputerSystem WHERE TotalPhysicalMemory > 8589934592" # Si le résultat est vide, la GPO ne s'appliquera pas # Si le résultat retourne des informations, la GPO s'appliquera
3. Ciblage au niveau des éléments (Préférences)
Pour les préférences de stratégie de groupe, un ciblage encore plus fin est disponible au niveau de chaque élément individuel.
Critères de ciblage disponibles :
Configuration du ciblage :
Exemple avec PowerShell :
# Le ciblage des préférences se configure principalement via l'interface graphique # Mais on peut vérifier les préférences configurées Get-GPOReport -Name "GPO-Preferences" -ReportType Xml | Select-Xml -XPath "//User//Drive"
Comparaison des méthodes de filtrage :
| Méthode | Avantages | Inconvénients | Usage |
|---|---|---|---|
| Filtrage de sécurité | Simple, rapide | Nécessite groupes | Ciblage par identité |
| Filtres WMI | Très flexible, dynamique | Impact performance | Ciblage matériel/logiciel |
| Ciblage préférences | Très granulaire | Seulement pour préférences | Éléments individuels |
Bonnes pratiques :
Les modèles d'administration définissent les paramètres de registre que les administrateurs peuvent configurer via les stratégies de groupe. Windows Server 2022 utilise le format ADMX/ADML, une évolution du format ADM utilisé dans les versions antérieures.
Évolution des formats :
Format ADM (ancien) :
Format ADMX/ADML (actuel) :
Structure des fichiers :
Fichiers ADMX :
C:\Windows\PolicyDefinitions\.admxFichiers ADML :
C:\Windows\PolicyDefinitions\[code-langue]\.admlC:\Windows\PolicyDefinitions\fr-FR\Exemples de fichiers :
| Fichier ADMX | Fonction | Fichier ADML associé |
|---|---|---|
| Windows.admx | Paramètres Windows de base | fr-FR\Windows.adml |
| inetres.admx | Internet Explorer | fr-FR\inetres.adml |
| MSEdge.admx | Microsoft Edge | fr-FR\MSEdge.adml |
| WindowsDefender.admx | Windows Defender | fr-FR\WindowsDefender.adml |
| Office16.admx | Microsoft Office 2016/2019 | fr-FR\Office16.adml |
Structure d'un fichier ADMX (en xml) :
<?xml version="1.0" encoding="utf-8"?> <policyDefinitions xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <policyNamespaces> <target prefix="exemple" namespace="Exemple.Policies.Exemple"/> </policyNamespaces>
<resources minRequiredRevision="1.0" />
<categories> <category name="ExempleCategory" displayName="$(string.ExempleCategory)"/> </categories>
<policies> <policy name="ExemplePolicy" class="Machine" displayName="$(string.ExemplePolicy)"
explainText="$(string.ExemplePolicy_Help)" key="Software\Policies\Exemple"
valueName="Parametre"> <parentCategory ref="ExempleCategory"/> <supportedOn ref="windows:SUPPORTED_Windows_10_0"/> <enabledValue> <decimal value="1"/> </enabledValue> <disabledValue> <decimal value="0"/> </disabledValue> </policy> </policies> </policyDefinitions>
Structure d'un fichier ADML (en xml) :
<?xml version="1.0" encoding="utf-8"?> <policyDefinitionResources xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <displayName>Nom affiché</displayName> <description>Description</description>
<resources> <stringTable> <string id="ExempleCategory">Paramètres Exemple</string> <string id="ExemplePolicy">Activer la fonctionnalité</string> <string id="ExemplePolicy_Help"> Ce paramètre permet d'activer ou désactiver la fonctionnalité exemple.
Si vous activez ce paramètre, la fonctionnalité sera activée.
Si vous désactivez ce paramètre, la fonctionnalité sera désactivée.
Si vous ne configurez pas ce paramètre, le comportement par défaut s'appliquera.
</string> </stringTable> </resources> </policyDefinitionResources>
Ajout de nouveaux modèles :
Pour ajouter des modèles tiers (Office, Chrome, Firefox, Adobe, etc.) :
C:\Windows\PolicyDefinitions\C:\Windows\PolicyDefinitions\fr-FR\Via PowerShell :
# Copier des modèles Office $Source = "\\serveur\partage\Templates\Office" $Dest = "C:\Windows\PolicyDefinitions" Copy-Item "$Source\*.admx" -Destination $Dest Copy-Item "$Source\fr-FR\*.adml" -Destination "$Dest\fr-FR\" # Vérifier les modèles installés Get-ChildItem "C:\Windows\PolicyDefinitions\*.admx" |
Select-Object Name, Length, LastWriteTime
# Lister les catégories disponibles Get-ChildItem "C:\Windows\PolicyDefinitions\*.admx" | ForEach-Object { [xml]$Content = Get-Content $_.FullName
$Content.policyDefinitions.categories.category | Select-Object name
}
Modèles tiers courants :
Microsoft Office :
Google Chrome :
Mozilla Firefox :
Adobe Reader :
Dépannage des modèles :
# Vérifier les erreurs de syntaxe XML $ADMXPath = "C:\Windows\PolicyDefinitions" Get-ChildItem "$ADMXPath\*.admx" | ForEach-Object { try { [xml]$xml = Get-Content $_.FullName
Write-Host "✓ $($_.Name) : Valide" -ForegroundColor Green
} catch { Write-Host "✗ $($_.Name) : ERREUR" -ForegroundColor Red
$_.Exception.Message
} } # Vérifier la présence des fichiers ADML correspondants Get-ChildItem "$ADMXPath\*.admx" | ForEach-Object { $ADMLFile = "$ADMXPath\fr-FR\$($_.BaseName).adml" if (Test-Path $ADMLFile) { Write-Host "✓ $($_.Name) a son ADML" -ForegroundColor Green
} else { Write-Host "✗ $($_.Name) MANQUE son ADML" -ForegroundColor Yellow
} }
Création de modèles personnalisés :
Pour créer vos propres modèles ADMX :
Exemple simple de modèle personnalisé :
Fichier : CompanySettings.admx
<?xml version="1.0" encoding="utf-8"?> <policyDefinitions xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <policyNamespaces> <target prefix="company" namespace="Company.Policies.Settings"/> </policyNamespaces> <resources minRequiredRevision="1.0"/>
<categories> <category name="CompanyCategory" displayName="$(string.CompanyCategory)"/> </categories>
<policies> <policy name="ProxyServer" class="Machine"
displayName="$(string.ProxyServer)"
explainText="$(string.ProxyServer_Help)"
key="Software\Company\NetworkSettings" valueName="ProxyAddress"> <parentCategory ref="CompanyCategory"/> <supportedOn ref="windows:SUPPORTED_Windows_10_0"/> <elements> <text id="ProxyAddress" valueName="ProxyAddress" required="true"/> </elements> </policy> </policies> </policyDefinitions>
Fichier : fr-FR\CompanySettings.adml
<?xml version="1.0" encoding="utf-8"?> <policyDefinitionResources xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <displayName>Paramètres Entreprise</displayName> <description>Modèles personnalisés de l'entreprise</description>
<resources> <stringTable> <string id="CompanyCategory">Paramètres Entreprise</string> <string id="ProxyServer">Configurer le serveur proxy</string> <string id="ProxyServer_Help"> Définit l'adresse du serveur proxy pour l'accès Internet.
Format : adresse:port (exemple : proxy.entreprise.local:8080)
</string> <string id="ProxyAddress">Adresse du proxy:</string> </stringTable> </resources> </policyDefinitionResources> ```
### 4.2 Création d'un magasin central
Le **magasin central de stratégies** (Central Store) est un emplacement de stockage centralisé pour les fichiers ADMX/ADML, permettant de standardiser les modèles d'administration disponibles dans tout le domaine.
**Avantages du magasin central** :
**Cohérence** : Tous les administrateurs utilisent les mêmes versions de modèles
**Centralisation** : Un seul emplacement à maintenir au lieu de chaque poste
**Performance** : Réduit la taille des GPO (les modèles ne sont plus dupliqués)
**Gestion simplifiée** : Mise à jour des modèles en un seul endroit
**Réplication automatique** : Les fichiers sont répliqués via SYSVOL sur tous les DC
**Emplacement du magasin central** :
Le magasin central doit être créé dans SYSVOL :
```
\\domaine.local\SYSVOL\domaine.local\Policies\PolicyDefinitions\
```
Ou localement sur le DC :
```
C:\Windows\SYSVOL\domain\Policies\PolicyDefinitions\
Création du magasin central - Méthode manuelle :
C:\Windows\SYSVOL\domain\Policies\PolicyDefinitionsC:\Windows\PolicyDefinitions\fr-FR, en-US)Création via PowerShell :
# Variables $DomainName = $env:USERDNSDOMAIN
$SysvolPath = "\\$DomainName\SYSVOL\$DomainName\Policies" $CentralStore = "$SysvolPath\PolicyDefinitions" $LocalADMX = "C:\Windows\PolicyDefinitions" # Création du magasin central Write-Host "Création du magasin central..." -ForegroundColor Cyan
# Créer le dossier principal if (-not (Test-Path $CentralStore)) { New-Item -Path $CentralStore -ItemType Directory -Force
Write-Host "✓ Dossier PolicyDefinitions créé" -ForegroundColor Green
} else { Write-Host "! Le magasin central existe déjà" -ForegroundColor Yellow
} # Copier les fichiers ADMX Write-Host "Copie des fichiers ADMX..." -ForegroundColor Cyan
Copy-Item "$LocalADMX\*.admx" -Destination $CentralStore -Force
Write-Host "✓ Fichiers ADMX copiés" -ForegroundColor Green
# Copier les dossiers de langue Write-Host "Copie des fichiers de langue..." -ForegroundColor Cyan
$LanguageFolders = Get-ChildItem $LocalADMX -Directory
foreach ($Folder in $LanguageFolders) { $DestLang = "$CentralStore\$($Folder.Name)"
if (-not (Test-Path $DestLang)) { New-Item -Path $DestLang -ItemType Directory -Force
}
Copy-Item "$LocalADMX\$($Folder.Name)\*.adml" -Destination $DestLang -Force
Write-Host "✓ Langue $($Folder.Name) copiée" -ForegroundColor Green
} # Vérification Write-Host "`nVérification du magasin central..." -ForegroundColor Cyan
$ADMXCount = (Get-ChildItem "$CentralStore\*.admx").Count
$ADMLCount = (Get-ChildItem "$CentralStore\fr-FR\*.adml" -ErrorAction SilentlyContinue).Count
Write-Host "Fichiers ADMX : $ADMXCount" -ForegroundColor White
Write-Host "Fichiers ADML (fr-FR) : $ADMLCount" -ForegroundColor White
Write-Host "`n✓ Magasin central créé avec succès!" -ForegroundColor Green
Write-Host "Emplacement : $CentralStore" -ForegroundColor White
Script complet avec gestion des erreurs :
function New-CentralStore { [CmdletBinding()] param( [string]$SourcePath = "C:\Windows\PolicyDefinitions", [string[]]$Languages = @("fr-FR", "en-US") )
try { # Récupération du domaine $Domain = $env:USERDNSDOMAIN
if (-not $Domain) { throw "Impossible de déterminer le domaine. Êtes-vous sur un DC?" }
$CentralStore = "\\$Domain\SYSVOL\$Domain\Policies\PolicyDefinitions"
Write-Host "=== Création du magasin central ===" -ForegroundColor Cyan
Write-Host "Domaine : $Domain" Write-Host "Destination : $CentralStore`n"
# Test de l'accès if (-not (Test-Path "\\$Domain\SYSVOL")) { throw "Impossible d'accéder à SYSVOL. Vérifiez les permissions." }
# Création du dossier principal if (-not (Test-Path $CentralStore)) { New-Item -Path $CentralStore -ItemType Directory -Force | Out-Null Write-Host "[OK] Dossier PolicyDefinitions créé" -ForegroundColor Green
} else { Write-Host "[INFO] Le magasin central existe déjà" -ForegroundColor Yellow
}
# Copie des ADMX Write-Host "`nCopie des fichiers ADMX..." $ADMXFiles = Get-ChildItem "$SourcePath\*.admx"
foreach ($File in $ADMXFiles) { Copy-Item $File.FullName -Destination $CentralStore -Force
} Write-Host "[OK] $($ADMXFiles.Count) fichiers ADMX copiés" -ForegroundColor Green
# Copie des langues Write-Host "`nCopie des fichiers de langue..." foreach ($Lang in $Languages) { $SourceLang = "$SourcePath\$Lang" $DestLang = "$CentralStore\$Lang"
if (Test-Path $SourceLang) { if (-not (Test-Path $DestLang)) { New-Item -Path $DestLang -ItemType Directory -Force | Out-Null }
$ADMLFiles = Get-ChildItem "$SourceLang\*.adml" foreach ($File in $ADMLFiles) { Copy-Item $File.FullName -Destination $DestLang -Force
} Write-Host "[OK] Langue $Lang : $($ADMLFiles.Count) fichiers" -ForegroundColor Green
} else { Write-Host "[WARN] Langue $Lang non trouvée" -ForegroundColor Yellow
} }
# Statistiques finales Write-Host "`n=== Résumé ===" -ForegroundColor Cyan
$TotalADMX = (Get-ChildItem "$CentralStore\*.admx").Count
Write-Host "Total ADMX : $TotalADMX"
foreach ($Lang in $Languages) { $LangPath = "$CentralStore\$Lang" if (Test-Path $LangPath) { $TotalADML = (Get-ChildItem "$LangPath\*.adml").Count
Write-Host "Total ADML ($Lang) : $TotalADML" } }
Write-Host "`n[SUCCESS] Magasin central créé!" -ForegroundColor Green
} catch { Write-Host "`n[ERREUR] $($_.Exception.Message)" -ForegroundColor Red
return $false }
return $true } # Exécution New-CentralStore -Languages @("fr-FR", "en-US")
Ajout de modèles supplémentaires au magasin central :
# Fonction pour ajouter des modèles (Office, Chrome, etc.) function Add-ADMXToCentralStore { param( [Parameter(Mandatory=$true)] [string]$SourceFolder,
[Parameter(Mandatory=$true)] [string]$ProductName )
$Domain = $env:USERDNSDOMAIN
$CentralStore = "\\$Domain\SYSVOL\$Domain\Policies\PolicyDefinitions"
Write-Host "Ajout des modèles $ProductName..." -ForegroundColor Cyan
# Copier les ADMX $ADMXFiles = Get-ChildItem "$SourceFolder\*.admx" foreach ($File in $ADMXFiles) { Copy-Item $File.FullName -Destination $CentralStore -Force
Write-Host " ✓ $($File.Name)" -ForegroundColor Green
}
# Copier les ADML $LangFolders = Get-ChildItem $SourceFolder -Directory
foreach ($Lang in $LangFolders) { $DestLang = "$CentralStore\$($Lang.Name)"
if (-not (Test-Path $DestLang)) { New-Item -Path $DestLang -ItemType Directory -Force | Out-Null }
$ADMLFiles = Get-ChildItem "$SourceFolder\$($Lang.Name)\*.adml" foreach ($File in $ADMLFiles) { Copy-Item $File.FullName -Destination $DestLang -Force
} Write-Host " ✓ Langue $($Lang.Name) : $($ADMLFiles.Count) fichiers" -ForegroundColor Green
}
Write-Host "✓ $ProductName ajouté au magasin central" -ForegroundColor Green
} # Exemples d'utilisation Add-ADMXToCentralStore -SourceFolder "C:\Temp\Office_Templates" -ProductName "Microsoft Office" Add-ADMXToCentralStore -SourceFolder "C:\Temp\Chrome_Templates" -ProductName "Google Chrome"
Vérification du magasin central :
# Script de vérification function Test-CentralStore { $Domain = $env:USERDNSDOMAIN
$CentralStore = "\\$Domain\SYSVOL\$Domain\Policies\PolicyDefinitions"
Write-Host "=== Vérification du magasin central ===" -ForegroundColor Cyan
Write-Host "Emplacement : $CentralStore`n"
if (-not (Test-Path $CentralStore)) { Write-Host "[ERREUR] Le magasin central n'existe pas!" -ForegroundColor Red
return $false }
# Compter les fichiers $ADMXCount = (Get-ChildItem "$CentralStore\*.admx" -ErrorAction SilentlyContinue).Count
Write-Host "Fichiers ADMX : $ADMXCount" -ForegroundColor White
# Langues disponibles $Languages = Get-ChildItem $CentralStore -Directory
Write-Host "`nLangues disponibles :" foreach ($Lang in $Languages) { $ADMLCount = (Get-ChildItem "$($Lang.FullName)\*.adml").Count
Write-Host " - $($Lang.Name) : $ADMLCount fichiers ADML" -ForegroundColor White
}
# Produits détectés Write-Host "`nProduits détectés :" $Products = @{ "Office16.admx" = "Microsoft Office 2016/2019/2021" "chrome.admx" = "Google Chrome" "firefox.admx" = "Mozilla Firefox" "inetres.admx" = "Internet Explorer" "MSEdge.admx" = "Microsoft Edge" }
foreach ($File in $Products.Keys) { if (Test-Path "$CentralStore\$File") { Write-Host " ✓ $($Products[$File])" -ForegroundColor Green
} else { Write-Host " ✗ $($Products[$File])" -ForegroundColor Gray
} }
return $true } # Exécution Test-CentralStore
Utilisation du magasin central :
Une fois créé, le magasin central est automatiquement utilisé :
Priorité de chargement :
L'éditeur de GPO charge les modèles dans cet ordre :
C:\Windows\PolicyDefinitionsMaintenance du magasin central :
# Synchroniser le magasin central avec les modèles locaux function Sync-CentralStore { $Domain = $env:USERDNSDOMAIN
$CentralStore = "\\$Domain\SYSVOL\$Domain\Policies\PolicyDefinitions" $LocalStore = "C:\Windows\PolicyDefinitions"
Write-Host "Synchronisation du magasin central..." -ForegroundColor Cyan
# Synchroniser les ADMX robocopy $LocalStore $CentralStore "*.admx" /MIR /NJH /NJS /NDL /NC /NS
# Synchroniser les langues robocopy "$LocalStore\fr-FR" "$CentralStore\fr-FR" "*.adml" /MIR /NJH /NJS /NDL /NC /NS
robocopy "$LocalStore\en-US" "$CentralStore\en-US" "*.adml" /MIR /NJH /NJS /NDL /NC /NS
Write-Host "✓ Synchronisation terminée" -ForegroundColor Green
}
Dépannage :
# Vérifier quel magasin est utilisé # L'éditeur de GPO utilise le magasin central si disponible $Domain = $env:USERDNSDOMAIN
$CentralStore = "\\$Domain\SYSVOL\$Domain\Policies\PolicyDefinitions" if (Test-Path $CentralStore) { Write-Host "Magasin central ACTIF" -ForegroundColor Green
Write-Host "Les GPO utilisent : $CentralStore" } else { Write-Host "Magasin LOCAL utilisé" -ForegroundColor Yellow
Write-Host "Les GPO utilisent : C:\Windows\PolicyDefinitions" }
L'héritage des stratégies de groupe suit la structure hiérarchique d'Active Directory. Les GPO liées aux conteneurs parents sont héritées par les conteneurs enfants, mais ce comportement peut être modifié de deux manières principales.
Le blocage de l'héritage (Block Inheritance) empêche les GPO des conteneurs parents de s'appliquer aux objets d'une unité d'organisation. C'est une option configurée au niveau de l'OU, pas de la GPO.
Fonctionnement :
Lorsque le blocage de l'héritage est activé sur une OU :
Cas d'usage typiques :
Environnements isolés : Une OU contenant des serveurs de test qui ne doivent pas recevoir les politiques de production.
Divisions autonomes : Des filiales ou départements ayant leurs propres politiques de sécurité distinctes de l'entreprise.
Environnements de développement : Des zones où les développeurs ont besoin de plus de liberté que les utilisateurs standards.
Zones DMZ : Des serveurs en zone démilitarisée nécessitant des configurations de sécurité spécifiques.
Configuration via GPMC :
Configuration via PowerShell :
# Activer le blocage de l'héritage Set-GPInheritance -Target "OU=Developpement,DC=entreprise,DC=local" `
-IsBlocked Yes
# Désactiver le blocage Set-GPInheritance -Target "OU=Developpement,DC=entreprise,DC=local" `
-IsBlocked No
# Vérifier l'état du blocage $Inheritance = Get-GPInheritance -Target "OU=Developpement,DC=entreprise,DC=local" $Inheritance.GpoInheritanceBlocked
# Bloquer plusieurs OU $OUs = @( "OU=Test,DC=entreprise,DC=local", "OU=Lab,DC=entreprise,DC=local", "OU=Sandbox,DC=entreprise,DC=local" ) foreach ($OU in $OUs) { Set-GPInheritance -Target $OU -IsBlocked Yes
Write-Host "✓ Héritage bloqué pour $OU" -ForegroundColor Green
}
Vérification de l'héritage :
# Afficher toutes les GPO héritées (ou bloquées) function Show-GPOInheritance { param( [Parameter(Mandatory=$true)] [string]$TargetOU )
$Inheritance = Get-GPInheritance -Target $TargetOU
Write-Host "=== Héritage pour $TargetOU ===" -ForegroundColor Cyan
Write-Host "Blocage activé : $($Inheritance.GpoInheritanceBlocked)" -ForegroundColor $(if($Inheritance.GpoInheritanceBlocked){"Red"}else{"Green"})
Write-Host "`nGPO héritées :" foreach ($Link in $Inheritance.InheritedGpoLinks) { $Status = if($Link.Enforced) {"[APPLIQUÉ]"} else {"[Normal]"} $Enabled = if($Link.Enabled) {"Activé"} else {"Désactivé"}
Write-Host " $Status $($Link.DisplayName) - $Enabled" -ForegroundColor $(if($Link.Enforced){"Yellow"}else{"White"}) Write-Host " Depuis : $($Link.Target)" -ForegroundColor Gray
}
Write-Host "`nGPO liées directement :" foreach ($Link in $Inheritance.GpoLinks) { $Enabled = if($Link.Enabled) {"Activé"} else {"Désactivé"} Write-Host " • $($Link.DisplayName) - $Enabled" -ForegroundColor Green
} } # Exemple d'utilisation Show-GPOInheritance -TargetOU "OU=Comptabilite,DC=entreprise,DC=local" ```
**Impact du blocage** :
Exemple de structure :
```
Domaine entreprise.local (GPO-Domaine) └── OU=Utilisateurs (GPO-Utilisateurs) └── OU=Comptabilite [Blocage activé] (GPO-Compta) └── OU=Finance (GPO-Finance)
Sans blocage sur OU=Comptabilite :
Avec blocage sur OU=Comptabilite :
Rapport d'héritage complet :
# Générer un rapport d'héritage pour toutes les OU function Export-InheritanceReport { param( [string]$OutputPath = "C:\Rapports\Inheritance-Report.html" )
$Report = @() $Domain = Get-ADDomain $AllOUs = Get-ADOrganizationalUnit -Filter * -SearchBase $Domain.DistinguishedName
foreach ($OU in $AllOUs) { $Inheritance = Get-GPInheritance -Target $OU.DistinguishedName
$Report += [PSCustomObject]@{ OU = $OU.Name
Path = $OU.DistinguishedName
Blocked = $Inheritance.GpoInheritanceBlocked
InheritedGPOs = ($Inheritance.InheritedGpoLinks | Measure-Object).Count
LinkedGPOs = ($Inheritance.GpoLinks | Measure-Object).Count
EnforcedGPOs = ($Inheritance.InheritedGpoLinks | Where-Object {$_.Enforced} | Measure-Object).Count
} }
$Report | ConvertTo-Html -Title "Rapport d'héritage GPO" -PreContent "<h1>Rapport d'héritage des stratégies de groupe</h1>" |
Out-File $OutputPath
Write-Host "✓ Rapport généré : $OutputPath" -ForegroundColor Green
} Export-InheritanceReport
Précautions avec le blocage :
L'option Appliqué (Enforced, anciennement "No Override") force l'application d'une GPO en lui donnant la priorité absolue. C'est une propriété configurée au niveau du lien de la GPO.
Fonctionnement :
Une GPO marquée "Appliqué" :
Cas d'usage typiques :
Politiques de sécurité critiques : Imposer des paramètres de sécurité à toute l'organisation sans exception.
Conformité réglementaire : Garantir l'application de politiques légales ou industrielles obligatoires.
Stratégies anti-virus : Forcer les paramètres de protection sur tous les postes.
Restrictions légales : Bloquer l'accès à certains contenus ou fonctionnalités de manière impérative.
Configuration via GPMC :
Configuration via PowerShell :
# Activer l'option Appliqué sur un lien existant Set-GPLink -Name "GPO-Securite-Critique" `
-Target "DC=entreprise,DC=local" -Enforced Yes
# Désactiver l'option Appliqué Set-GPLink -Name "GPO-Securite-Critique" `
-Target "DC=entreprise,DC=local" -Enforced No
# Créer un lien avec l'option Appliqué directement New-GPLink -Name "GPO-Conformite" `
-Target "DC=entreprise,DC=local" -Enforced Yes -Order 1
# Appliquer sur plusieurs niveaux $Targets = @( "DC=entreprise,DC=local", # Domaine "OU=Utilisateurs,DC=entreprise,DC=local", "OU=Ordinateurs,DC=entreprise,DC=local" ) foreach ($Target in $Targets) { Set-GPLink -Name "GPO-Antivirus" -Target $Target -Enforced Yes
Write-Host "✓ GPO appliquée sur $Target" -ForegroundColor Green
} ```
**Priorité avec plusieurs GPO "Appliqué"** :
Si plusieurs GPO sont marquées "Appliqué" :
- L'ordre de liaison compte toujours
- Les GPO "Appliqué" de niveaux plus bas (OU enfants) ont priorité sur celles des niveaux plus hauts (domaine)
Exemple avec structure :
```
Domaine (GPO-Domaine [Appliqué])
└── OU=IT (GPO-IT [Appliqué])
└── OU=Admins (GPO-Admins [Appliqué])
```
Ordre d'application final pour un objet dans OU=Admins :
1. Local
2. Site
3. GPO-Domaine [Appliqué] 4. GPO-IT [Appliqué] 5. GPO-Admins [Appliqué] ← Priorité la plus haute
**Combinaison Blocage + Appliqué** :
```
Domaine (GPO-Securite [Appliqué]) └── OU=Standard (GPO-Standard) └── OU=Developpement [Blocage activé] (GPO-Dev)
Pour un objet dans OU=Developpement :
Script de diagnostic :
function Test-GPOEnforcement { param( [Parameter(Mandatory=$true)] [string]$TargetOU )
Write-Host "=== Analyse de l'application forcée ===" -ForegroundColor Cyan
Write-Host "Cible : $TargetOU`n"
$Inheritance = Get-GPInheritance -Target $TargetOU
# Vérifier le blocage if ($Inheritance.GpoInheritanceBlocked) { Write-Host "[ATTENTION] Blocage de l'héritage activé" -ForegroundColor Red
}
# Lister les GPO appliquées Write-Host "`nGPO avec option 'Appliqué' :" $EnforcedGPOs = $Inheritance.InheritedGpoLinks | Where-Object {$_.Enforced}
if ($EnforcedGPOs) { foreach ($GPO in $EnforcedGPOs) { Write-Host " 🔒 $($GPO.DisplayName)" -ForegroundColor Yellow
Write-Host " Depuis : $($GPO.Target)" -ForegroundColor Gray
Write-Host " Ordre : $($GPO.Order)" -ForegroundColor Gray
} } else { Write-Host " Aucune GPO avec option 'Appliqué'" -ForegroundColor Green
}
# Lister les GPO normales Write-Host "`nGPO normales (peuvent être bloquées) :" $NormalGPOs = $Inheritance.InheritedGpoLinks | Where-Object {-not $_.Enforced}
if ($NormalGPOs) { foreach ($GPO in $NormalGPOs) { $Status = if ($Inheritance.GpoInheritanceBlocked) {"[BLOQUÉE]"} else {"[Active]"} Write-Host " $Status $($GPO.DisplayName)" -ForegroundColor $(if($Inheritance.GpoInheritanceBlocked){"Red"}else{"White"}) } }
# Résumé Write-Host "`n=== Résumé ===" -ForegroundColor Cyan
Write-Host "Total GPO héritées : $(($Inheritance.InheritedGpoLinks | Measure-Object).Count)" Write-Host "GPO appliquées : $(($EnforcedGPOs | Measure-Object).Count)" Write-Host "GPO bloquées : $(if($Inheritance.GpoInheritanceBlocked){($NormalGPOs | Measure-Object).Count}else{0})" } # Utilisation Test-GPOEnforcement -TargetOU "OU=Developpement,DC=entreprise,DC=local"
Bonnes pratiques :
Utiliser avec parcimonie : N'appliquer que pour les politiques réellement critiques.
Documentation obligatoire : Commenter pourquoi une GPO doit être appliquée.
Privilégier le niveau domaine : Les GPO appliquées au domaine affectent toute l'organisation.
Tester l'impact : Vérifier que l'application forcée ne crée pas de conflits majeurs.
Audit régulier : Lister périodiquement toutes les GPO appliquées pour vérifier leur pertinence.
# Rapport de toutes les GPO appliquées dans le domaine function Get-EnforcedGPOs { $Domain = Get-ADDomain $Report = @()
# Parcourir tous les conteneurs $Containers = @($Domain.DistinguishedName) $Containers += Get-ADOrganizationalUnit -Filter * | Select-Object -ExpandProperty DistinguishedName
foreach ($Container in $Containers) { $Inheritance = Get-GPInheritance -Target $Container $EnforcedLinks = $Inheritance.GpoLinks | Where-Object {$_.Enforced}
foreach ($Link in $EnforcedLinks) { $Report += [PSCustomObject]@{ GPO = $Link.DisplayName
LinkedTo = $Container Order = $Link.Order
Enabled = $Link.Enabled
} } }
Write-Host "=== GPO avec option 'Appliqué' dans le domaine ===" -ForegroundColor Cyan
$Report | Format-Table -AutoSize
Write-Host "`nTotal : $(($Report | Measure-Object).Count) GPO appliquées" -ForegroundColor White
} Get-EnforcedGPOs
Comparaison Blocage vs Appliqué :
| Aspect | Bloquer l'héritage | Appliqué |
|---|---|---|
| Configuré sur | L'OU (conteneur) | Le lien de la GPO |
| Objectif | Empêcher les GPO parentes | Forcer une GPO spécifique |
| Portée | Toutes les GPO parentes | Une seule GPO |
| Peut être contourné | Oui, par "Appliqué" | Non |
| Icône | Exclamation bleue | Cadenas |
| Usage recommandé | Environnements isolés | Sécurité critique |
Les préférences de stratégie de groupe (Group Policy Preferences - GPP) étendent les capacités des GPO traditionnelles en permettant de configurer des paramètres qui n'imposent pas de restrictions permanentes. Contrairement aux stratégies classiques, les préférences peuvent être modifiées localement par les utilisateurs.
Différence entre Stratégies et Préférences :
Stratégies (Policies) :
Préférences (Preferences) :
Catégories de préférences :
Les préférences sont organisées en deux grandes catégories :
Paramètres Windows :
Paramètres du Panneau de configuration :
Actions disponibles :
Chaque préférence peut être configurée avec différentes actions :
| Action | Description | Usage |
|---|---|---|
| Créer | Crée l'élément s'il n'existe pas | Première configuration |
| Remplacer | Supprime et recrée l'élément à chaque application | Forcer une configuration |
| Mettre à jour | Modifie uniquement les propriétés spécifiées | Ajustements partiels |
| Supprimer | Supprime l'élément | Nettoyage |
Options communes :
Onglet "Commun" disponible pour chaque préférence :
Avantages des préférences :
Exemple 1 : Mappage de lecteurs réseau
Configuration d'un lecteur partagé pour tous les utilisateurs :
Via interface graphique :
Via PowerShell :
# Les préférences se configurent principalement via l'interface # Mais on peut créer les éléments XML manuellement $GPOName = "GPO-Lecteurs-Reseau" $GPO = Get-GPO -Name $GPOName # Chemin du fichier de préférences utilisateur $GPOPath = "\\entreprise.local\SYSVOL\entreprise.local\Policies\{$($GPO.Id)}\User\Preferences\Drives" if (-not (Test-Path $GPOPath)) { New-Item -Path $GPOPath -ItemType Directory -Force
} # Créer le fichier Drives.xml avec la configuration $DrivesXML = @"
<?xml version="1.0" encoding="utf-8"?>
<Drives clsid="{8FDDCC1A-0C3C-43cd-A6B4-71A6DF20DA8C}">
<Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}"
name="P:" status="P:"
image="2" changed="2025-01-15 10:00:00" uid="{GUID-UNIQUE}">
<Properties action="U" thisDrive="NOCHANGE"
allDrives="NOCHANGE"
userName=""
path="\\serveur\partage\commun"
label="Documents partagés"
persistent="1"
useLetter="1"
letter="P"/>
</Drive>
</Drives>
"@
$DrivesXML | Out-File "$GPOPath\Drives.xml" -Encoding UTF8
Exemple 2 : Création de raccourcis
Placer un raccourci vers une application sur le bureau de tous les utilisateurs :
Exemple 3 : Variables d'environnement
Définir une variable d'environnement personnalisée :
Exemple 4 : Tâches planifiées
Créer une tâche de nettoyage automatique :
powershell.exe-Command "Remove-Item C:\Temp\* -Recurse -Force"Exemple 5 : Configuration du registre
Modifier une clé de registre spécifique :
Script PowerShell - Exemple complet de configuration :
# Configuration complète de préférences via GPO function Configure-GPPreferences { param( [string]$GPOName = "GPO-Preferences-Standard" )
Write-Host "=== Configuration des préférences GPO ===" -ForegroundColor Cyan
# Vérifier si la GPO existe $GPO = Get-GPO -Name $GPOName -ErrorAction SilentlyContinue
if (-not $GPO) { Write-Host "Création de la GPO $GPOName..." -ForegroundColor Yellow
$GPO = New-GPO -Name $GPOName -Comment "Préférences standards utilisateurs" }
# 1. Mappage de lecteurs Write-Host "`n[1/5] Configuration du mappage de lecteurs..." -ForegroundColor Cyan
# Via interface graphique nécessaire ou XML manuel
# 2. Raccourci bureau Write-Host "[2/5] Création de raccourcis..." -ForegroundColor Cyan
# Via interface graphique ou XML
# 3. Variable d'environnement via registre Write-Host "[3/5] Configuration des variables d'environnement..." -ForegroundColor Cyan
Set-GPRegistryValue -Name $GPOName `
-Key "HKCU\Environment" `
-ValueName "COMPANY_SHARE" `
-Type String `
-Value "\\serveur\partage"
# 4. Imprimante par défaut Write-Host "[4/5] Configuration imprimante..." -ForegroundColor Cyan
# Préférence Imprimantes via interface
# 5. Options Internet Write-Host "[5/5] Configuration navigateur..." -ForegroundColor Cyan
Set-GPRegistryValue -Name $GPOName `
-Key "HKCU\Software\Microsoft\Internet Explorer\Main" `
-ValueName "Start Page" `
-Type String `
-Value "https://intranet.entreprise.local"
Write-Host "`n✓ Configuration terminée!" -ForegroundColor Green
Write-Host "Lier la GPO avec : New-GPLink -Name '$GPOName' -Target 'OU=Users,DC=entreprise,DC=local'" -ForegroundColor White
} # Exécution Configure-GPPreferences
Ciblage avancé d'une préférence :
Exemple : Mapper un lecteur uniquement pour les ordinateurs portables du département IT :
SELECT * FROM Win32_SystemEnclosure WHERE ChassisTypes = 9Dépannage des préférences :
# Activer la journalisation détaillée des préférences Set-GPRegistryValue -Name "GPO-Preferences-Standard" `
-Key "HKLM\Software\Policies\Microsoft\Windows\Group Policy\{35378EAC-683F-11D2-A89A-00C04FBBCFA2}" `
-ValueName "LogLevel" `
-Type DWord `
-Value 1
# Afficher les événements de préférences Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 50 |
Where-Object {$_.Message -like "*preference*"} | Format-Table TimeCreated, LevelDisplayName, Message -Wrap
Vérification sur un poste client :
# Forcer la mise à jour des GPO gpupdate /force
# Vérifier les lecteurs mappés Get-PSDrive -PSProvider FileSystem | Where-Object {$_.DisplayRoot -like "\\*"} # Vérifier les raccourcis créés Get-ChildItem "$env:USERPROFILE\Desktop\*.lnk" # Vérifier les variables d'environnement Get-ChildItem Env: | Where-Object {$_.Name -like "COMPANY*"} # Afficher le résultat complet des GPO avec préférences gpresult /h C:\Temp\gpresult.html
Bonnes pratiques :
Les stratégies de groupe permettent d'exécuter des scripts PowerShell lors du démarrage/arrêt de l'ordinateur ou de l'ouverture/fermeture de session utilisateur. Cette fonctionnalité permet d'automatiser des tâches administratives complexes.
Objectif : Créer automatiquement un compte utilisateur local sur tous les ordinateurs du domaine via une GPO.
Scénario : Créer un compte "TechSupport" local avec droits administrateur pour intervention à distance.
Étape 1 : Créer le script PowerShell
Créer le fichier Create-LocalUser.ps1 :
# Create-LocalUser.ps1 # Script de création d'un utilisateur local via GPO # Configuration $UserName = "TechSupport" $FullName = "Compte Support Technique" $Description = "Compte local pour interventions support" $Password = "P@ssw0rd2025!" # À sécuriser avec méthode appropriée $LogFile = "C:\Windows\Logs\GPO-CreateUser.log" # Fonction de journalisation function Write-Log { param([string]$Message) $TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "$TimeStamp - $Message" | Out-File -FilePath $LogFile -Append
} try { Write-Log "Début de l'exécution du script"
# Vérifier si l'utilisateur existe déjà $UserExists = Get-LocalUser -Name $UserName -ErrorAction SilentlyContinue
if ($UserExists) { Write-Log "L'utilisateur $UserName existe déjà" exit 0
}
# Créer le mot de passe sécurisé $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
# Créer l'utilisateur New-LocalUser -Name $UserName `
-Password $SecurePassword `
-FullName $FullName `
-Description $Description `
-PasswordNeverExpires `
-UserMayNotChangePassword `
-AccountNeverExpires
Write-Log "Utilisateur $UserName créé avec succès"
# Ajouter au groupe Administrateurs Add-LocalGroupMember -Group "Administrateurs" -Member $UserName Write-Log "Utilisateur $UserName ajouté au groupe Administrateurs"
# Désactiver le compte (à activer manuellement lors d'intervention) Disable-LocalUser -Name $UserName Write-Log "Compte $UserName désactivé par défaut"
Write-Log "Script terminé avec succès" exit 0
} catch { Write-Log "ERREUR: $($_.Exception.Message)" exit 1
}
Version améliorée avec mot de passe crypté :
# Create-LocalUser-Secure.ps1 # Version sécurisée avec mot de passe crypté # Le mot de passe est stocké dans un fichier crypté créé au préalable $PasswordFile = "\\serveur\scripts$\TechSupport.pwd" $UserName = "TechSupport" $LogFile = "C:\Windows\Logs\GPO-CreateUser.log" function Write-Log { param([string]$Message) $TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "$TimeStamp - $Message" | Out-File -FilePath $LogFile -Append -Force
} try { # Créer le dossier de logs si nécessaire $LogDir = Split-Path $LogFile if (-not (Test-Path $LogDir)) { New-Item -Path $LogDir -ItemType Directory -Force | Out-Null }
Write-Log "=== Début exécution script création utilisateur ==="
# Vérifier l'existence de l'utilisateur $User = Get-LocalUser -Name $UserName -ErrorAction SilentlyContinue
if ($User) { Write-Log "L'utilisateur $UserName existe déjà - Aucune action" exit 0
}
# Récupérer le mot de passe crypté if (-not (Test-Path $PasswordFile)) { Write-Log "ERREUR: Fichier de mot de passe introuvable : $PasswordFile" exit 1
}
$SecurePassword = Get-Content $PasswordFile | ConvertTo-SecureString
# Création de l'utilisateur Write-Log "Création de l'utilisateur $UserName..." $NewUser = New-LocalUser -Name $UserName `
-Password $SecurePassword `
-FullName "Support Technique" `
-Description "Compte support - Créé par GPO" `
-PasswordNeverExpires `
-AccountNeverExpires
Write-Log "Utilisateur créé - SID: $($NewUser.SID)"
# Ajout au groupe Administrateurs local Write-Log "Ajout au groupe Administrateurs..." Add-LocalGroupMember -Group "Administrateurs" -Member $UserName -ErrorAction Stop
# Désactiver par défaut Disable-LocalUser -Name $UserName Write-Log "Compte désactivé par défaut (sécurité)"
Write-Log "=== Script terminé avec succès ===" exit 0
} catch { Write-Log "=== ERREUR CRITIQUE ===" Write-Log "Message: $($_.Exception.Message)" Write-Log "Ligne: $($_.InvocationInfo.ScriptLineNumber)" Write-Log "Commande: $($_.InvocationInfo.Line)" exit 1
}
Préparation du fichier de mot de passe crypté :
# À exécuter une fois pour créer le fichier de mot de passe $Password = Read-Host "Entrez le mot de passe" -AsSecureString
$Password | ConvertFrom-SecureString | Out-File "\\serveur\scripts$\TechSupport.pwd"
Étape 2 : Configurer la GPO
Via interface graphique :
Create-LocalUser.ps1 dans ce dossierVia PowerShell :
# Configuration automatisée de la GPO avec script $GPOName = "GPO-Create-LocalUser" $ScriptContent = Get-Content "C:\Scripts\Create-LocalUser-Secure.ps1" -Raw
# Créer la GPO $GPO = New-GPO -Name $GPOName -Comment "Création compte local TechSupport" # Obtenir le chemin SYSVOL de la GPO $GPOPath = "\\$env:USERDNSDOMAIN\SYSVOL\$env:USERDNSDOMAIN\Policies\{$($GPO.Id)}" $StartupScriptPath = "$GPOPath\Machine\Scripts\Startup" # Créer les dossiers nécessaires if (-not (Test-Path $StartupScriptPath)) { New-Item -Path $StartupScriptPath -ItemType Directory -Force | Out-Null } # Copier le script $ScriptContent | Out-File "$StartupScriptPath\Create-LocalUser.ps1" -Encoding UTF8
# Créer le fichier scripts.ini pour référencer le script $ScriptsIni = @"
[Startup]
0CmdLine=Create-LocalUser.ps1
0Parameters=
"@
$ScriptsIni | Out-File "$StartupScriptPath\..\scripts.ini" -Encoding ASCII
Write-Host "✓ GPO configurée avec script de démarrage" -ForegroundColor Green
Write-Host "Lier la GPO avec : New-GPLink -Name '$GPOName' -Target 'OU=Workstations,DC=entreprise,DC=local'"
Étape 3 : Liaison et test
# Lier la GPO à l'OU des ordinateurs New-GPLink -Name "GPO-Create-LocalUser" `
-Target "OU=Workstations,DC=entreprise,DC=local" `
-LinkEnabled Yes
# Forcer la mise à jour sur un poste test Invoke-Command -ComputerName PC-TEST01 -ScriptBlock { gpupdate /force
} # Redémarrer le poste pour déclencher le script de démarrage Restart-Computer -ComputerName PC-TEST01 -Force
# Après redémarrage, vérifier la création Invoke-Command -ComputerName PC-TEST01 -ScriptBlock { Get-LocalUser -Name "TechSupport" Get-LocalGroupMember -Group "Administrateurs" | Where-Object {$_.Name -like "*TechSupport"} }
Script de vérification sur tous les postes :
# Vérifier la création de l'utilisateur sur tous les ordinateurs de l'OU $Computers = Get-ADComputer -Filter * -SearchBase "OU=Workstations,DC=entreprise,DC=local" $Results = @() foreach ($Computer in $Computers) { $Status = Invoke-Command -ComputerName $Computer.Name -ScriptBlock { $User = Get-LocalUser -Name "TechSupport" -ErrorAction SilentlyContinue
[PSCustomObject]@{ UserExists = [bool]$User Enabled = $User.Enabled
LastLogon = $User.LastLogon
} } -ErrorAction SilentlyContinue
$Results += [PSCustomObject]@{ Computer = $Computer.Name
UserExists = $Status.UserExists
Enabled = $Status.Enabled
LastLogon = $Status.LastLogon
Online = [bool]$Status } } $Results | Format-Table -AutoSize
$Results | Export-Csv "C:\Rapports\TechSupport-Status.csv" -NoTypeInformation
Write-Host "`nRésumé:" Write-Host "Ordinateurs vérifiés : $($Results.Count)" Write-Host "Utilisateur créé : $(($Results | Where-Object UserExists).Count)" Write-Host "Ordinateurs hors ligne : $(($Results | Where-Object {-not $_.Online}).Count)"
Objectif : Changer périodiquement le mot de passe d'un compte local via GPO pour conformité sécurité.
Scénario : Réinitialiser le mot de passe du compte "TechSupport" tous les 90 jours.
Script de modification de mot de passe :
# Change-LocalUserPassword.ps1 # Modification du mot de passe d'un utilisateur local via GPO param( [string]$UserName = "TechSupport", [string]$PasswordFile = "\\serveur\scripts$\TechSupport-New.pwd", [string]$LogFile = "C:\Windows\Logs\GPO-ChangePassword.log" ) function Write-Log { param([string]$Message, [string]$Level = "INFO") $TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $LogMessage = "$TimeStamp [$Level] $Message" $LogMessage | Out-File -FilePath $LogFile -Append -Force
switch ($Level) { "ERROR" { Write-Host $LogMessage -ForegroundColor Red } "WARN" { Write-Host $LogMessage -ForegroundColor Yellow } "SUCCESS" { Write-Host $LogMessage -ForegroundColor Green } default { Write-Host $LogMessage } } } try { Write-Log "=== Début modification mot de passe ===" "INFO" Write-Log "Utilisateur cible: $UserName" "INFO" Write-Log "Ordinateur: $env:COMPUTERNAME" "INFO"
# Vérifier l'existence de l'utilisateur $User = Get-LocalUser -Name $UserName -ErrorAction Stop
Write-Log "Utilisateur $UserName trouvé - SID: $($User.SID)" "INFO"
# Vérifier le fichier de mot de passe if (-not (Test-Path $PasswordFile)) { Write-Log "Fichier de mot de passe introuvable: $PasswordFile" "ERROR" exit 1
}
Write-Log "Fichier de mot de passe accessible" "INFO"
# Charger le nouveau mot de passe $SecurePassword = Get-Content $PasswordFile | ConvertTo-SecureString
# Changer le mot de passe $User | Set-LocalUser -Password $SecurePassword Write-Log "Mot de passe modifié avec succès" "SUCCESS"
# Enregistrer la date de modification dans le registre $RegPath = "HKLM:\SOFTWARE\Company\PasswordManagement" if (-not (Test-Path $RegPath)) { New-Item -Path $RegPath -Force | Out-Null }
$ChangeDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" Set-ItemProperty -Path $RegPath -Name "LastPasswordChange_$UserName" -Value $ChangeDate Write-Log "Date de changement enregistrée: $ChangeDate" "INFO"
# Optionnel: Forcer la déconnexion de l'utilisateur s'il est connecté $LoggedUsers = quser 2>$null | Select-Object -Skip 1
if ($LoggedUsers -match $UserName) { Write-Log "ATTENTION: L'utilisateur $UserName est actuellement connecté" "WARN" # logoff $SessionID # Décommenter pour forcer la déconnexion }
Write-Log "=== Script terminé avec succès ===" "SUCCESS" exit 0
} catch { Write-Log "=== ERREUR CRITIQUE ===" "ERROR" Write-Log "Message: $($_.Exception.Message)" "ERROR" Write-Log "Type: $($_.Exception.GetType().FullName)" "ERROR" Write-Log "Ligne: $($_.InvocationInfo.ScriptLineNumber)" "ERROR" exit 1
}
Script avec rotation de mot de passe automatique :
# Change-Password-Rotation.ps1 # Rotation automatique avec génération de mot de passe complexe function New-ComplexPassword { param([int]$Length = 16)
Add-Type -AssemblyName System.Web
$Password = [System.Web.Security.Membership]::GeneratePassword($Length, 4)
# S'assurer de la complexité $Password = $Password -replace '[<>]', '$' # Remplacer caractères problématiques
return $Password } function Write-Log { param([string]$Message, [string]$Level = "INFO") $LogFile = "C:\Windows\Logs\GPO-PasswordRotation.log" $TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "$TimeStamp [$Level] $Message" | Out-File -FilePath $LogFile -Append -Force
} # Configuration $UserName = "TechSupport" $PasswordHistoryPath = "\\serveur\scripts$\PasswordHistory" $RotationDays = 90
try { Write-Log "Vérification de la nécessité de rotation" "INFO"
# Vérifier la dernière rotation $RegPath = "HKLM:\SOFTWARE\Company\PasswordManagement" $LastChange = Get-ItemProperty -Path $RegPath -Name "LastPasswordChange_$UserName" -ErrorAction SilentlyContinue
if ($LastChange) { $LastChangeDate = [DateTime]::ParseExact($LastChange."LastPasswordChange_$UserName",
"yyyy-MM-dd HH:mm:ss", $null) $DaysSinceChange = (Get-Date) - $LastChangeDate
Write-Log "Dernier changement: $LastChangeDate ($([Math]::Round($DaysSinceChange.TotalDays)) jours)" "INFO"
if ($DaysSinceChange.TotalDays -lt $RotationDays) { Write-Log "Rotation non nécessaire (< $RotationDays jours)" "INFO" exit 0
} }
Write-Log "Rotation nécessaire - Génération nouveau mot de passe" "INFO"
# Générer un nouveau mot de passe $NewPassword = New-ComplexPassword -Length 20
$SecurePassword = ConvertTo-SecureString $NewPassword -AsPlainText -Force
# Modifier le mot de passe $User = Get-LocalUser -Name $UserName -ErrorAction Stop
$User | Set-LocalUser -Password $SecurePassword Write-Log "Mot de passe modifié avec succès" "SUCCESS"
# Sauvegarder dans l'historique crypté $HistoryFile = "$PasswordHistoryPath\$env:COMPUTERNAME-$UserName.pwd" $NewPassword | ConvertTo-SecureString -AsPlainText -Force |
ConvertFrom-SecureString |
Out-File $HistoryFile
Write-Log "Mot de passe sauvegardé dans historique crypté" "INFO"
# Envoyer notification email (optionnel) $EmailParams = @{ To = "admin@entreprise.local" From = "gpo@entreprise.local" Subject = "Rotation mot de passe - $env:COMPUTERNAME" Body = "Le mot de passe du compte $UserName sur $env:COMPUTERNAME a été modifié automatiquement." SmtpServer = "smtp.entreprise.local" }
Send-MailMessage @EmailParams -ErrorAction SilentlyContinue
# Enregistrer la date if (-not (Test-Path $RegPath)) { New-Item -Path $RegPath -Force | Out-Null } Set-ItemProperty -Path $RegPath -Name "LastPasswordChange_$UserName" -Value (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
Write-Log "=== Rotation terminée avec succès ===" "SUCCESS" exit 0
} catch { Write-Log "ERREUR: $($_.Exception.Message)" "ERROR" exit 1
}
Configuration de la GPO pour exécution périodique :
# Créer une tâche planifiée via GPO pour exécution régulière $GPOName = "GPO-Password-Rotation" $ScriptPath = "\\serveur\scripts$\Change-Password-Rotation.ps1" # Créer la GPO $GPO = New-GPO -Name $GPOName -Comment "Rotation automatique mots de passe locaux" # Configurer via Préférences > Tâches planifiées # (Configuration manuelle recommandée via interface graphique) Write-Host "Configuration de la tâche planifiée:" Write-Host "1. Éditer la GPO $GPOName" Write-Host "2. Configuration ordinateur > Préférences > Paramètres du Panneau de configuration > Tâches planifiées" Write-Host "3. Nouveau > Tâche planifiée (Windows Vista+)" Write-Host "4. Général:" Write-Host " - Nom: PasswordRotation" Write-Host " - Exécuter avec les autorisations maximales" Write-Host " - Compte: SYSTEM" Write-Host "5. Déclencheurs:" Write-Host " - Hebdomadaire, tous les lundis à 03h00" Write-Host "6. Actions:" Write-Host " - Programme: powershell.exe" Write-Host " - Arguments: -ExecutionPolicy Bypass -File `"$ScriptPath`""
Vérification et reporting :
# Script de vérification des derniers changements de mot de passe function Get-PasswordChangeReport { param( [string]$OUPath = "OU=Workstations,DC=entreprise,DC=local" )
$Computers = Get-ADComputer -Filter * -SearchBase $OUPath $Report = @()
foreach ($Computer in $Computers) { $Result = Invoke-Command -ComputerName $Computer.Name -ScriptBlock { $RegPath = "HKLM:\SOFTWARE\Company\PasswordManagement"
if (Test-Path $RegPath) { $Props = Get-ItemProperty -Path $RegPath $Props.PSObject.Properties | Where-Object {$_.Name -like "LastPasswordChange_*"} | ForEach-Object { [PSCustomObject]@{ Account = $_.Name -replace "LastPasswordChange_", "" LastChange = $_.Value
DaysAgo = ((Get-Date) - [DateTime]::ParseExact($_.Value, "yyyy-MM-dd HH:mm:ss", $null)).Days
} } } } -ErrorAction SilentlyContinue
if ($Result) { foreach ($Item in $Result) { $Report += [PSCustomObject]@{ Computer = $Computer.Name
Account = $Item.Account
LastChange = $Item.LastChange
DaysAgo = $Item.DaysAgo
Status = if ($Item.DaysAgo -gt 90) {"⚠️ À renouveler"} else {"✓ OK"} } } } }
$Report | Format-Table -AutoSize
$Report | Export-Csv "C:\Rapports\Password-Change-Report.csv" -NoTypeInformation
# Résumé Write-Host "`n=== Résumé ===" -ForegroundColor Cyan
Write-Host "Total ordinateurs: $($Computers.Count)" Write-Host "Comptes trouvés: $(($Report | Measure-Object).Count)" Write-Host "À renouveler: $(($Report | Where-Object DaysAgo -gt 90 | Measure-Object).Count)" -ForegroundColor Yellow
} Get-PasswordChangeReport
Sécurisation des scripts :
# Protéger les fichiers de scripts avec permissions appropriées $ScriptPath = "\\serveur\scripts$" # Retirer l'accès en écriture pour tous sauf admins $ACL = Get-Acl $ScriptPath $ACL.SetAccessRuleProtection($true, $false) # Désactiver l'héritage # Administrateurs: Contrôle total $AdminRule = New-Object System.Security.AccessControl.FileSystemAccessRule( "BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow" ) # SYSTEM: Contrôle total $SystemRule = New-Object System.Security.AccessControl.FileSystemAccessRule( "NT AUTHORITY\SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow" ) # Ordinateurs du domaine: Lecture + Exécution uniquement $ComputersRule = New-Object System.Security.AccessControl.FileSystemAccessRule( "Domain Computers", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow" ) $ACL.SetAccessRule($AdminRule) $ACL.SetAccessRule($SystemRule) $ACL.SetAccessRule($ComputersRule) Set-Acl -Path $ScriptPath -AclObject $ACL Write-Host "✓ Permissions sécurisées appliquées sur $ScriptPath" -ForegroundColor Green
Conclusion
Ce chapitre a couvert les aspects essentiels de l'infrastructure des stratégies de groupe dans Windows Server 2022, de la gestion de base à l'automatisation avancée par scripts PowerShell. La maîtrise de ces concepts permet une administration centralisée efficace et une standardisation cohérente des configurations à travers l'environnement Active Directory.