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 :

  • Génerer un fichier CSV des modifications.
  • Créer un fichier XML contenant l'intégralité des groupes et utilisateurs et utilisable dans un autre script
  • Avertir les administrateurs d'un changement dans l'attribution des groupes.

Il peut être exécuté à la demande, comme en tache planifiée.

Comment faire?

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.

Que modifier?

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.


Script final

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
}

}

Ajouter un commentaire

Article précédent Article suivant