L'un de nos clients est audité de manière régulière sur l'attribution des droits des utilisateurs aux ressources de l'entreprise, et notamment sur les autorisations d'accès données via les groupes de sécurité dans Active Directory. Chaque changement doit etre validé par un supérieur, validé une deuxième fois par le responsable informatique, puis par la personne ayant fait la modification. Ce script a pour but de synthétiser et de consigner les différents changements afin de pouvoir fournir à l'auditeur une synthèse de ce qu'il doit techniquement retrouver au format papier. Ce script, dans sa conception, permet plusieurs choses :
Il peut être exécuté à la demande, comme en tache planifiée.
Pour cela, nous nous servirons évidemment de Powershell, qui est plus qu'adapté pour lancer des requetes à Active Directory, et donc du module active directory.
Le script récupère l'intégralité des groupes dans l'AD, et en extrait les membres. Au premier lancement, il stocke tout cela dans un fichier XML, qui lui servira de reference, puis au lancement suivant, recoupera les informations dans le fichier XML de réference et le nouveau. En analysant chaque groupe cas par cas, il peut trouver les modifications dans chaque groupe, mais également detecter si un groupe est supprimé ou crée.
Les premières lignes sont modifiables. Le format de date peut être changé, l'emplacement ou il ira déposer et chercher ses fichiers, et bien entendu l'adresse d’expéditeur, destinataire, et le serveur de messagerie.
Vous pouvez le télécharger depuis mon espace git personnel.
ipmo activedirectory
Set-Location $( [environment]::GetFolderPath("MyDocuments") )
$now = Get-Date -Format dd/MM/yyyy
$from = "moi@domaine.com"
$to = "lui@domaine.com"
$smtpserver = "serveurmail.domaine.fr"
if (!(Get-Module -name ActiveDirectory)) {throw("Impossible de trouver le module Active Directory")}
function addthis([string]$groupname=$(throw("Nom de groupe obligatoire")),[string]$name=$null,$added=$null,$removed=$null)
{
if ($added -eq $null -and $removed -eq $null)
{throw("Aucun indice d'ajout / retrait pour $groupname")}
$objet = New-Object psobject
$objet | Add-Member -MemberType NoteProperty -name "Date" -value $now
$objet | Add-Member -MemberType NoteProperty -Name "Group_name" -Value $groupname
$objet | Add-Member -MemberType NoteProperty -Name "Name" -Value $name
$objet | Add-Member -MemberType NoteProperty -Name "Added" -Value $added
$objet | Add-Member -MemberType NoteProperty -Name "Removed" -Value $removed
return $objet
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
########################## CREATION DE LA BASE DES GROUPES ##################################
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
$listegroupes = Get-ADGroup -Filter * -Properties members | Select-Object -Property name,members | Sort-Object -Property name
$array = New-Object System.Collections.ArrayList
foreach ($groupe in $listegroupes)
{
$objet = New-Object psobject
$groupe.members = $($groupe.members | foreach {$_.split(",")[0] -replace("^CN=","")})
$objet | add-member -MemberType NoteProperty -Name "name" -Value $groupe.name
$objet | Add-Member -MemberType NoteProperty -Name "members" -Value $groupe.members
$array.Add($objet) | Out-Null
}
if (!(Test-Path referenceadgroupes.xml))
{
$listegroupes | Export-Clixml referenceadgroupes.xml -Force
}
else
{
$referenceadgroupes = Import-Clixml referenceadgroupes.xml
$array | Export-Clixml newgroups.xml -Force
$newgroups = Import-Clixml newgroups.xml
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
########################### VERIFICATION DE CHAQUE GROUPE ###################################
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
$arraygroups = New-Object System.Collections.ArrayList
#|~~~~~~~~~~~~~~~~~~~~~~~~~~~|#
#| Reference VS. nouveau |#
#|~~~~~~~~~~~~~~~~~~~~~~~~~~~|#
$i = 1
foreach ($groupe in $referenceadgroupes)
{
Write-Progress -Status "Analyse" -Activity $($groupe.name) -PercentComplete ($i / $($referenceadgroupes.count) * 100)
$i ++
$obj = New-Object PSobject
$compareit = $null
$compareit = $newgroups | Where-Object {$_.name -eq $($groupe.name)}
#_____________________________
#1) Le groupe n'est pas trouvé
#_____________________________
if (!$compareit)
{
#Si le groupe n'est pas présent dans la nouvelle liste il a été retiré
$arraygroups.Add($(addthis -groupname $groupe.name -removed "X")) | Out-Null
}
#_____________________________
#2) La propriété membres de reference et différence sont nuls
#_____________________________
elseif($groupe.members.Count -eq 0 -and $compareit.members.Count -eq 0)
{
#on ne fait rien
}
#_____________________________
#3) L'une ou l'autre des propriétés membres est égale à zero, mais leur count diffère
#_____________________________
#Une erreur est causée lorsque l'on compare une valeur et un $null. Il faut donc filtrer.
#Si le nombre de membres de la reference = zéro ou celle du nouveau = 0 et que groupe.members.count et compare.membre.count sont différents alors [...]
elseif(($groupe.members.count -eq 0 -or $compareit.members.count -eq 0) -and ($groupe.members.count -ne $compareit.members.count))
{
if ($groupe.members.count -gt $compareit.members.Count)
{
$toadd = $groupe.members
$groupname = $groupe.name
$removed = "X"
$added = $null
}
else
{
$toadd = $compareit.members
$groupname = $compareit.name
$removed = $null
$added = "X"
}
foreach ($membre in $toadd)
{
$arraygroups.add($(addthis -groupname $groupname -name $($membre) -added $added -removed $removed))
}
}
#_____________________________
#4) aucun des cas précedents n'est valide
#_____________________________
else
{
$changes = $null
$changes = Compare-Object -ReferenceObject $groupe.members -DifferenceObject $compareit.members
foreach ($change in $changes)
{
switch ($($change.sideindicator))
{
"=>" {$arraygroups.add($(addthis -groupname $($groupe.name) -name $($change.inputobject) -added "X"));break}
"<=" {$arraygroups.add($(addthis -groupname $($groupe.name) -name $($change.inputobject) -removed "X"));break}
default {throw("Erreur pas d'indice!")}
}#foreach ($change in $changes)
}
}
}#foreach ($groupe in $referenceadgroupes)
#|~~~~~~~~~~~~~~~~~~~~~~~~~~~|#
#| Nouveau VS. reference |#
#|~~~~~~~~~~~~~~~~~~~~~~~~~~~|#
$i = 1
foreach ($groupe in $newgroups)
{
Write-Progress -Status "Recherche de nouveaux groupes" -PercentComplete ($i / $($referenceadgroupes.Count) * 100) -Activity $groupe.name
$i++
$compareit = $null
$compareit = $referenceadgroupes | Where-Object {$_.name -eq $($groupe.name)}
if (!$compareit)
{
#Le groupe n'existe pas dans l'ancienne liste. Il est donc crée
$arraygroups.Add($(addthis -groupname $groupe.name -added "X"))
foreach ($member in $groupe.members)
{
$arraygroups.Add($(addthis -groupname $groupe.name -name $member -added "X"))
}
}
}
Move-Item .\newgroups.xml -Destination .\referenceadgroupes.xml -Force
$arraygroups | Export-Csv -Path .\changements_groupes.csv -Delimiter ";" -Encoding UTF8 -NoTypeInformation -Append
if ($arraygroups)
{
$body = $null
foreach ($line in $arraygroups)
{
[string]$body += $line -replace("@{","") -replace(";","`t") -replace ("}","`n")
}
Send-MailMessage -from $from -to $to -SmtpServer $smtpserver -Subject "Ajouts dans les groupes AD le $now" -Body "Voici les groupes modifiés : `n$body" -Attachments .\changements_groupes.csv -Encoding UTF8
}
}