Ceci est une ancienne révision du document !
Get-DomainPcGpoReport - Obtenir un rapport de déploiement des GPO
Un jour, mon responsable m'a demandé un rapport sur le déploiement de certaines GPO. Je me suis dit qu'il suffisait d'interroger l'AD pour avoir ces informations et là, stupeur, après quelques recherches, je me rends compte que l'AD ne les fournit pas.
Du coup, j'ai conçu ce script afin de répondre à ce problème.
Son fonctionnement est plutôt basique :
- Il crée une liste de PC à interroger en se basant sur l'AD.
- Vérifie ceux qui sont en ligne.
- Interroge le poste pour connaître l'utilisateur connecté.
- Vérifie les GPO déployer.
- Renvoie les résultat dans un rapport.
Il vérifie aussi pour chaque poste la date de la dernière synchronisation avec l'AD.
Le rapport peut alors être traité par un script de vérification pour Nagios.
Script principal
################################################################################################## # # Script de vérification de synchronisation des postes avec le contrôleur de domaine # # Par Nicolas THOREZ # ################################################################################################## # Importation des Modules Import-Module activedirectory # Déclaration des variables $ReportFile = "C:\Scripts\GPO Report\result.xml" $LastSyncFile = "C:\Scripts\GPO Report\lastsync.csv" # Création de la liste des PS en se basant sur l'AD $ListPC = (Get-ADComputer -SearchBase "OU=PC Fixe,OU=Ordinateurs,DC=TEST,DC=LOCAL" -Filter *).Name $ListPC += (Get-ADComputer -SearchBase "OU=PC Portable,OU=Ordinateurs,DC=TEST,DC=LOCAL" -Filter *).Name $ListPC += (Get-ADComputer -SearchBase "OU=Ordinateurs,OU=Direction,DC=TEST,DC=LOCAL" -Filter *).Name $Domaine = 'TEST' # Indiquer ici le nom de domaine au format NetBIOS $FQDN = 'test.local' # Indiquer ici le nom de domaine au format DNS # La ligne suivante contient les informations d'entête du rapport dont le nom des GPO à tester $ReportHeaders = "PC;Online;User;LastSyncTime;(P:)_Personal_Folder_Mapping;BackupUsers_Xcopy_Daily_scheduled;Stratégie de groupe locale;(Z:)_Shared_Folder;Default Domain Policy" # Déclaration des fonctions Function Get-ConnectedUser($PC) { $Name = (Get-WmiObject -Comp $PC -CL Win32_ComputerSystem -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -InformationAction SilentlyContinue).UserName If ($Name -notlike '$Domaine*') { $Name = "n/a" } Return $Name } Function Get-PCOnlineStatus($PC) { # On interroge le PC via Get-WmiObject plutôt que par ping pour éviter les erreurs de pare-feu $OnlineTest = (Get-WmiObject -Comp $PC -CL Win32_ComputerSystem -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -InformationAction SilentlyContinue).Domain If ($OnlineTest -eq $FQDN) { Return $true } Else { Return $false } } Function Add-CsvLine { Param( [parameter(position=0)] $PCName, [parameter(position=1)] $OnlineStatus, [parameter(position=2)] $ConnectedUser, [parameter(position=3)] $LastSyncTime, [parameter(position=4)] $PDriveGpoStatus, [parameter(position=5)] $BackupGpoStatus, [parameter(position=6)] $LocalGpoStatus, [parameter(position=7)] $ZDriveGpoStatus, [parameter(position=8)] $DefaultGpoStatus ) $LineContent = "$PCName" + ";" + "$OnlineStatus" + ";" + "$ConnectedUser" + ";" + "$LastSyncTime" + ";" + "$PDriveGpoStatus" + ";" + "$BackupGpoStatus" + ";" + "$LocalGpoStatus" + ";" + "$ZDriveGpoStatus" + ";" + "$DefaultGpoStatus" Add-Content 'C:\Scripts\GPO Report\Report.csv' $LineContent If (Test-Path $ReportFile) { Remove-Item -Path $ReportFile -Force } } Function Get-Report { Param( [parameter(position=0)] [String]$PC, [parameter(position=1)] [String]$User ) # Suppression du précédent rapport If (Test-Path $ReportFile) { Remove-Item -Path $ReportFile -Force } # Création du rapport $GPMObject = New-Object -ComObject GPMgmt.GPM $GPMConstants = $GPMObject.GetConstants() $RSOPContent = $GPMObject.GetRSOP($GPMConstants.RSOPModeLogging,$null,0) $RSOPContent.LoggingComputer = $PC $RSOPContent.LoggingUser = $User $RSOPContent.CreateQueryResults() $RSOPContent.GenerateReportToFile($GPMConstants.ReportXML,$ReportFile) } Function Get-GPOState($Scope) { $GPOTested = ($Results.DocumentElement.UserResults.GPO | Where-Object {$_.Name -eq $Scope}) $GPOValidity = $GPOTested.IsValid If ($GPOValidity -eq $true) { $FunctiunResult = $GPOTested.Enabled Return $FunctiunResult } Else { $FunctiunResult = "n/a" Return $FunctiunResult } } Function Check-LastSync($PC) { $LastSyncVar = Import-Csv -Path $LastSyncFile -Delimiter ';' If ($LastSyncVar.$PC -eq $null) { $LastSyncVar | Add-Member -MemberType NoteProperty -Name "$PC" -Value "n/a" $LastSyncVar | Export-Csv -Path $LastSyncFile -Delimiter ';' } } Function Set-LastSync { param( [parameter(position=0)] [String]$PC, [parameter(position=1)] [String]$Time ) $LastSyncVar = Import-Csv -Path $LastSyncFile -Delimiter ';' $LastSyncVar.$PC = $Time $LastSyncVar | Export-Csv -Path $LastSyncFile -Delimiter ';' } # Création du Rapport CSV Set-Content 'C:\Scripts\GPO Report\Report.csv' $ReportHeaders # Vérification de l'existence de lastsync.csv sinon création If (!(Test-Path -Path $LastSyncFile)) { $TempVar = @{} $TempVar | Export-Csv -Path $LastSyncFile -Delimiter ';' } # Trainement Foreach ($PC in $ListPC) { echo "Analyse de $PC" [String]$PCName = $PC $OnlineStatus = Get-PCOnlineStatus($PC) [String]$ConnectedUser = "n/a" [String]$LastSyncTime = "n/a" $PDriveGpoStatus = "n/a" $BackupGpoStatus = "n/a" $LocalGpoStatus = "n/a" $ZDriveGpoStatus = "n/a" $DefaultGpoStatus = "n/a" # Inscription dans LastSync.CSV Check-LastSync($PC) # Traitement pour les postes en ligne if ($OnlineStatus -eq $true) { # Récupération de l'utilisateur et passage au PC suivant si erreur $ConnectedUser = Get-ConnectedUser($PC) If ($ConnectedUser -like "n/a") { Add-CsvLine $PCName $OnlineStatus $ConnectedUser $LastSyncTime $PDriveGpoStatus $BackupGpoStatus $LocalGpoStatus $ZDriveGpoStatus $DefaultGpoStatus Continue } # Géneration de rapport GPResult au format XML pour traitement Get-Report $PCName $ConnectedUser # Test du résultat de GPresult et en cas d'erreur, écrit les données existantes et passe à la suite If (!(Test-Path $ReportFile)) { Add-CsvLine $PCName $OnlineStatus $ConnectedUser $LastSyncTime $PDriveGpoStatus $BackupGpoStatus $LocalGpoStatus $ZDriveGpoStatus $DefaultGpoStatus Continue } # Traitement des données de GPResult $Results = [xml](Get-Content $ReportFile) # Récupération de la dernière synchronisation $GPOTime = ($Results.DocumentElement.UserResults.ExtensionStatus | Where-Object {$_.Name -eq 'Infrastructure de stratégie de groupe'}).BeginTime $LastSyncTime = [String](Get-Date $GPOTime).ToShortDateString() + " " + [String](Get-Date $GPOTime).ToShortTimeString() Set-LastSync $PCName $LastSyncTime # Vérification pour la GPO (P:)_Personal_Folder_Mapping $PDriveGpoStatus = Get-GPOState('(P:)_Personal_Folder_Mapping') # Vérification pour la GPO BackupUsers_Xcopy_Daily_scheduled $BackupGpoStatus = Get-GPOState('BackupUsers_Xcopy_Daily_scheduled') # Vérification pour la GPO Stratégie de groupe locale $LocalGpoStatus = Get-GPOState('Stratégie de groupe locale') # Vérification pour la GPO (Z:)_Shared_Folder $ZDriveGpoStatus = Get-GPOState('(Z:)_Shared_Folder') # Vérification pour la GPO Default Domain Policy $DefaultGpoStatus = Get-GPOState('Default Domain Policy') # Ajoute une ligne au rapport et passe à la suite de la boucle Add-CsvLine $PCName $OnlineStatus $ConnectedUser $LastSyncTime $PDriveGpoStatus $BackupGpoStatus $LocalGpoStatus $ZDriveGpoStatus $DefaultGpoStatus Continue } else { # Ajoute une ligne au rapport et passe à la suite de la boucle Add-CsvLine $PCName $OnlineStatus $ConnectedUser $LastSyncTime $PDriveGpoStatus $BackupGpoStatus $LocalGpoStatus $ZDriveGpoStatus $DefaultGpoStatus Continue } }
Script d'interprétation pour Nagios
################################################################################## # # # Vérification des résultats de Get-DomainPcGpoReport.ps1 pour alerte Nagios # # # # Par Nicolas THOREZ # # # ################################################################################## # Déclaration des variables $ListPC = (Get-ADComputer -SearchBase "OU=PC Fixe,OU=Ordinateurs,DC=AD,DC=MTARGET,DC=NET" -Filter *).Name $ListPC += (Get-ADComputer -SearchBase "OU=PC Portable,OU=Ordinateurs,DC=AD,DC=MTARGET,DC=NET" -Filter *).Name $SyncTimeData = Import-Csv -Path "C:\Scripts\GPO Report\lastsync.csv" -Delimiter ';' $ReportData = Import-Csv -Path "C:\Scripts\GPO Report\Report.csv" -Delimiter ';' $OutputMessage = "" $OutputMessageCore = "" $ExitCode = 3 $CheckTime = Get-Date $NeverSyncError = "" $NoSyncSinceError = "" $MaxSyncDelta = 7 # jours $PDriveError = "" $ZDriveError = "" $LocalGpoError = "" $BackupError = "" $DefaultGpoError = "" # Déclaration des fonctions Function Add-MessageData { param( [parameter(position=0)] [String]$Message, [parameter(position=1)] [String]$PC ) If ($Message -eq "") { $Message = "$PC" } Else { $Message += ", $PC" } Return $Message } # Vérification de la dernière synchronisation Foreach ($PC in $ListPC) { If ($SyncTimeData.$PC -eq "n/a") { $NeverSyncError = (Add-MessageData $NeverSyncError $PC) } Else { $Delta = Get-Date $SyncTime = $SyncTimeData.$PC $Delta = $CheckTime - (Get-Date $SyncTime) If ($Delta.Days -ge $MaxSyncDelta) { $NoSyncSinceError = (Add-MessageData $NoSyncSinceError $PC) } } } # Vérification de l'état de chaque GPO Foreach ($PC in $ReportData) { # Initialisation des variables du CSV $PCName = $PC.PC $OnlineStatus = $PC.Online $PStatus = $PC.'(P:)_Personal_Folder_Mapping' $BackupStatus = $PC.'BackupUsers_Xcopy_Daily_scheduled' $LocalStatus = $PC.'Strat�gie de groupe locale' $ZStatus = $PC.'(Z:)_Shared_Folder' $DefaultStatus = $PC.'Default Domain Policy' # Passage à la boucle suivante pour les PC hors ligne If ($OnlineStatus -eq "False") { continue } # Vérification des valeurs If ($PStatus -ne "true") { $PDriveError = (Add-MessageData $PDriveError $PCName) } If ($BackupStatus -ne "true") { $BackupError = (Add-MessageData $BackupError $PCName) } If ($LocalStatus -ne "true") { $LocalGpoError = (Add-MessageData $LocalGpoError $PCName) } If ($ZStatus -ne "true") { $ZDriveError = (Add-MessageData $ZDriveError $PCName) } If ($DefaultStatus -ne "true") { $DefaultGpoError = (Add-MessageData $DefaultGpoError $PCName) } } # Renvoie des valeurs dans Nagios If ($PDriveError -ne "") { $PDriveError = "P Drive Error : " + $PDriveError $OutputMessageCore = (Add-MessageData $OutputMessageCore $PDriveError) $ExitCode = 1 } If ($BackupError -ne "") { $BackupError = "Backup Error : " + $BackupError $OutputMessageCore = (Add-MessageData $OutputMessageCore $BackupError) $ExitCode = 1 } If ($LocalGpoError -ne "") { $LocalGpoError = "Local Policy Error : " + $LocalGpoError $OutputMessageCore = (Add-MessageData $OutputMessageCore $LocalGpoError) $ExitCode = 1 } If ($ZDriveError -ne "") { $ZDriveError = "Z Drive Error : " + $ZDriveError $OutputMessageCore = (Add-MessageData $OutputMessageCore $ZDriveError) $ExitCode = 1 } If ($DefaultGpoError -ne "") { $DefaultGpoError = "Default Domain Policy Error : " + $DefaultGpoError $OutputMessageCore = (Add-MessageData $OutputMessageCore $DefaultGpoError) $ExitCode = 1 } If ($NeverSyncError -ne "") { $NeverSyncError = "Never Synchronised : " + $NeverSyncError $OutputMessageCore = (Add-MessageData $OutputMessageCore $NeverSyncError) $ExitCode = 2 } If ($NoSyncSinceError -ne "") { $NoSyncSinceError = "No Synchronization since $MaxSyncDelta days : " + $NoSyncSinceError $OutputMessageCore = (Add-MessageData $OutputMessageCore $NoSyncSinceError) $ExitCode = 2 } If ($OutputMessageCore -eq "") { $ExitCode = 0 } If ($ExitCode -eq 2) { $OutputMessage = "CRITICAL - $OutputMessageCore" echo $OutputMessage exit $ExitCode } Elseif ($ExitCode -eq 1) { $OutputMessage = "WARNING - $OutputMessageCore" echo $OutputMessage exit $ExitCode } Elseif ($ExitCode -eq 0) { echo "OK - All GPO Applied" exit $ExitCode } Else { echo "UNKNOWN - no data to compute" exit $ExitCode }
Discussion