Get-DomainPcGpoReport - Créer un rapport de déploiement de GPO
Création — Nicolas THOREZ 2019/02/19 21:49
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 PC 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=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
$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