Script PowerShell d’extraction AD pour audit sécurité

#----------------------------------------------------
# Extraction Active Directory pour audit sécurité
# PowerShell v4
#----------------------------------------------------

$ErrorActionPreference = 'SilentlyContinue' # Erreurs non affichées et exécution se poursuit sans interruption

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#
# Import des modules PowerShell
#//////////////////////////////////////////////////////////////////////#

Import-module -Name ActiveDirectory
Import-module -Name GroupPolicy

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#
# Initialisation des Variables
#//////////////////////////////////////////////////////////////////////#

$DicGroupGPO = @{}
$DicoToken = @{}
$ADDomain = get-addomain
$sDomainName = $ADDomain.DNSRoot

# Variables pour les fichiers à créer
$PathProjet = "C:\serveur_apps\scripts\Projet"
$GroupGPOAD = $PathProjet + "\GroupGPOAD_xyz.csv"
$sxyzFilePath1 = $PathProjet + "\UserListAD_xyz.csv"
$sxyzFilePath2 = $PathProjet + "\UserGroupAD_xyz.csv"
$sxyzFilePath3 = $PathProjet + "\temp.tmp"
$GPOFileOut = $PathProjet + "\GPO.txt"

# Variables pour les logs
$dDateCourante = Get-Date
$sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss")+ " INFO - Début d'exécution "
$LogRep = "C:\serveur_apps\scripts\Projetlog\"
$sLogFile = $LogRep + "log.txt"
#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#
# Initialisation des Fonctions
#//////////////////////////////////////////////////////////////////////#

# Fonction pour convertir un chemin LDAP en canonical / le nom du groupe n'est pas gardé dans la valeur de retour
[paycontent]
Function ConverTProjetnonicalName ($strToConvert,$sDomain){
$CanonicalName = $sDomain + "/"
$Liste = $strToConvert -split ","
For ($i = -1 ; $i -gt -$Liste.count; $i -- ){
    If (($Liste[$i]).substring(0,3) -eq "OU=") {
        $CanonicalName += ($Liste[$i]).substring(3,($Liste[$i]).length-3) + "/"
    }
        If (($Liste[$i]).substring(0,3) -eq "CN=") {
            $CanonicalName += ($Liste[$i]).substring(3,($Liste[$i]).length-3) + "/"
        }
    }

    return $CanonicalName
    $CanonicalName = $Null
}

# Fonction retournant les sous groupes d'un groupe
Function Get-GroupHierarchy ($SearchGroup, $sGPO){
    If ($SearchGroup -ne "")
    If ($DicGroupGPO.ContainsKey($SearchGroup)){
    $aGroupMember = $DicGroupGPO.Get_Item($SearchGroup)
    ForEach ($GroupMember in $aGroupMember){
        $strGroupMember = $GroupMember.name
        $strGroupMemberDNWithOutGroupName = $GroupMember.DistinguishedName
        $strGroupMemberCN = ConverTProjetnonicalName $strGroupMemberDNWithOutGroupName $sdomainName
        "$strGroupMember;$sGPO;$strGroupMemberCN" | Out-File -Append -FilePath $sxyzFilePath3 -Encoding Unicode
    }
}

Else{
$GroupMembers = get-ADGroupMember $SearchGroup | where {$_.ObjectClass -eq "group"} #| select-object name
If ($GroupMembers)
{
$DicGroupGPO.add($SearchGroup,$GroupMembers)
ForEach ($GroupMember in $GroupMembers){
    $strGroupMember = $GroupMember.name
    $strGroupMemberDNWithOutGroupName = $GroupMember.DistinguishedName
    $strGroupMemberCN = ConverTProjetnonicalName $strGroupMemberDNWithOutGroupName $sdomainName
    "$strGroupMember;$sGPO;$strGroupMemberCN" | Out-File -Append -FilePath $sxyzFilePath3 -Encoding Unicode
    Get-GroupHierarchy $strGroupMember $sGPO
} # ForEach $GroupMembers
} # If $GroupMembers
} # Else
} # If($DicGroupGPO.ContainsKey($SearchGroup))
} # End of Function

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#
# Vérification du répertoire
#//////////////////////////////////////////////////////////////////////#

# Répertoire pour les fichiers de log
If(!(Test-Path $sLogFile )){
    $sResult = New-Item $LogRep -Type directory
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " INFO - SUCCES Le répertoire " + $PathProjet + " a été créé"
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
}

# Réroire pour les fichiers d'extraction
If(!(Test-Path $PathProjet)){
    Try{
        $sResult = New-Item $PathProjet -Type directory
        $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " INFO - SUCCES Le répertoire " + $PathProjet + " a été créé"
        $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
    }   

Catch{
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ERREUR - Création du répertoire " + $PathProjet + " impossible"
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode

    ForEach($ErreurMessage in $Error){
        $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ERREUR - " + ($ErreurMessage.ToString()).Replace("`n","")
        $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
    }
    $Error.clear()
    }
}

# Suppression des anciens fichiers
Remove-Item C:\Serveur_apps\Scripts\Projet\*.zip
Remove-Item C:\Serveur_apps\Scripts\Projet\*.csv
Remove-Item C:\Serveur_apps\Scripts\Projet\*.tmp
Remove-Item C:\Serveur_apps\Scripts\Projet\*.txt

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#
# Extraction des données #
#//////////////////////////////////////////////////////////////////////#

# Vérification de la présence des fichiers, suppressions si "true"
If(Test-Path $sxyzFilePath1){remove-item -path $sxyzFilePath1 -Force}
If(Test-Path $sxyzFilePath2){remove-item -path $sxyzFilePath2 -Force}
If(Test-Path $sxyzFilePath3){remove-item -path $sxyzFilePath3 -Force}
If(Test-Path $GroupGPOAD){remove-item -path $GroupGPOAD -Force}
If(Test-Path $GPOFileOut){remove-item -path $GPOFileOut -Force}

######### Création du fichier groupe GPO #########

# Extraction des GPO dans un fichier puis une variable
$oListGPOS = Get-gpo -all | Format-table DisplayName -HideTableHeaders | Out-File $GPOFileOut
$oListGPOS = Get-Content $GPOFileOut
$sResult = New-Item $sxyzFilePath3 -Type File -force

# Préparation du fichier GPO, entêtes
$sOutPutMess = "Nom du groupe;Nom de la GPO;OU Group"
$sOutPutMess | Out-File -Append -FilePath $GroupGPOAD -Encoding Unicode
$Error.clear()
ForEach ($oListGPO in $oListGPOS) # Début de traitement du tableau utilisateur et GPO{
$Error.clear()

Try{
    $oListGPO = ($oListGPO).trim()
    $oListPERMISSIONS = Get-GPPermissions -Name $oListGPO -All -DomainName $sDomainName

    # Check des permissions sur chaque GPO
    ForEach ($sListPermission in $oListPERMISSIONS ){
    If(($sListPermission.Permission -eq "GpoApply") -and ($sListPermission.Trustee.Name -ne "Utilisateurs authentIfiés")){
        # S'il y a un utilisateur ou ordinateur directement dans le filtre GPO

        If (($sListPermission.Trustee.SIDType -eq "User") -or ($sListPermission.Trustee.SIDType -eq "Computer")){
            $sGPOMessage = "ATTENTION " + $sListPermission.Trustee.SIDType + " " + $sListPermission.Trustee.Name + ";" + $oListGPO
            $sGPOMessage | Out-File -Append -FilePath $sxyzFilePath3 -Encoding Unicode
            $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ATTENTION - Des utilisateurs ou ordinateurs sont directement rattachés à la GPO :'$oListGPO'. Fichier : " + $sxyzFilePath3

            $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
}       

ElseIf ($sListPermission.Trustee.SIDType -eq "Unknown"){
    $sGPOMessage = "ATTENTION Groupe ou utilisateur inexistant;" + $oListGPO
    $sGPOMessage | Out-File -Append -FilePath $sxyzFilePath3 -Encoding Unicode
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ATTENTION - Groupe ou utilisateur inexistant pour la GPO : '$oListGPO' Fichier : $sxyzFilePath3"
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
}

Else{
    $strDSPathGroupe = $sListPermission.Trustee.DSPath
    $strCNGroupe = ConverTProjetnonicalName $strDSPathGroupe $sdomainName
    $sGPOMessage = $sListPermission.Trustee.Name + ";" + $oListGPO + ";" + $strCNGroupe
    $sGPOMessage | Out-File -Append -FilePath $sxyzFilePath3 -Encoding Unicode
    Get-GroupHierarchy $sListPermission.Trustee.Name $oListGPO
    }
}

} # ForEach ($sListPermission in $oListPERMISSIONS )
} # Try

Catch{
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ERREUR - Problème de traitement du fichier, GPO : '$oListGPO' dans " + $sxyzFilePath3 + " pour " + $GroupGPOAD

    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode

    ForEach($ErreurMessage in $Error){
        $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ERREUR - " + ($ErreurMessage.ToString()).Replace("`n","")
        $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
    }

    $Error.clear()
    }
} # ForEach ($oListGPO in $oListGPOS)

# Tri pour avoir unicite des resultats

# Le passage par un fichier temporaire et un tri est preferable à l utilisation d'un tableau pour de nombreuses donnees
Get-Content $sxyzFilePath3 | Sort | Get-Unique | Out-File -Append -FilePath $GroupGPOAD -Encoding Unicode

######### Requètes des utilisateurs #########

$oLDAPUsers = Get-ADUser -Filter * –Properties SamAccountName,Surname,GivenName,DistinguishedName,whencreated,Enabled,LockedOut,LastLogonDate,PasswordNeverExpires,PasswordLastSet,CannotChangePassword,PasswordNotRequired,AccountLockOutTime,LockedOut

Get-GroupHierarchy $sListPermission.Trustee.Name $oListGPO

######### Requètes des groupes #########

$oListGroups = Get-ADGroup -Filter * -Properties SamAccountName

# Construction des fichiers utilisateurs et groupes : new File ; création des entetes, logs,

If($oLDAPUsers -And $oListGroups){
    # Création des fichiers, des entetes et écritures dans le log
    $sResult = New-Item $sxyzFilePath1 -Type File # Création du nouveau fichier 'xyz_UserListAD.csv'

    $sOutPutMess = "Id;Nom;Prenom;DN;creation;modIfication;Statut Actif;verrouillé;connexion;password expiré;Derniere modification du password;password permanent;password optionnel;expiration;Duree depuis le verrouillage;Nombre de mauvais password;password verrouillé;Changement de password au prochain demarrage"

    $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath1 -Encoding Unicode
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " INFO - Début de traitement du fichier " + $sxyzFilePath1
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
    $sResult = New-Item $sxyzFilePath2 -Type File # Création du nouveau fichier 2
    $sOutPutMess = "IdentIfiant;Domaine;Ressources"
    $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath2 -Encoding Unicode
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " INFO - Début de traitement du fichier " + $sxyzFilePath2
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
    $iValue = 0x02
    $oCultureInfo = New-Object System.Globalization.CultureInfo("fr-FR")

ForEach ($oLDAPUser in $oLDAPUsers) # Début de traitement du tableau utilisateur{
    $Error.clear()
    Try{
        $sSAMAcName = $oLDAPUser.samaccountname
        $sLastName = $oLDAPUser.sn
        $sFirstName = $oLDAPUser.givenname
        $sdistinguishedName = $oLDAPUser.distinguishedname

        # DN du compte sans le nom de l'utilisateur, valeur 'DN du compte' dans le fichier $sxyzFilePath1
        $sDistinguishedNameWithOutUserName = ($sdistinguishedName -split(",",2))[1]

        # En remplacement du 'Get-ACL' et 'récup compte verrouillé'
        $sUserProperties = Get-ADUser -SearchScope Base -SearchBase $sdistinguishedName -Filter * -Properties CannotChangePassword,LockedOut,PasswordExpired -Server $sDomainName
        $sPwdProtected = $sUserProperties.CannotChangePassword

        If($oLDAPUser.whencreated) #Format date{
            $sWhenCreated = [datetime]::Parse($oLDAPUser.whencreated.ToString())
            $dWhenCreated = ($sWhenCreated.ToLProjetlTime()).ToString("G", $oCultureInfo)
        }

        Else {$dWhenCreated = $Null}
        If($oLDAPUser.whenchanged) #Format date{
            $sWhenChanged = [datetime]::Parse($oLDAPUser.whenchanged.ToString())
            $dWhenChanged = ($sWhenChanged.ToLProjetlTime()).ToString("G", $oCultureInfo)
        }   

        Else {$dWhenChanged = $Null}

        If($oLDAPUser.lastlogontimestamp) #Format int{

            $dLastLogOn = [datetime]::FromFileTime([Int64]::Parse($oLDAPUser.lastlogontimestamp))
            $sLastLogOn = $dLastLogOn.ToString("G", $oCultureInfo)
        }

        Else {$sLastLogOn = $Null}

        $sUserAccountLocked = $sUserProperties.LockedOut

    If($oLDAPUser.lockOuttime -gt 0) #Format int{
        $sLastlockOutTime = [datetime]::FromFileTime([Int64]::Parse($oLDAPUser.lockOuttime))
        $dLastlockOutTime = $sLastlockOutTime.ToString("G", $oCultureInfo)
    }   

    Else {$dLastlockOutTime = ""}
    $sPasswordExpired = $sUserProperties.PasswordExpired
    If(($oLDAPUser.pwdlastset -ne 0) -and ($oLDAPUser.pwdlastset -ne $NULL)) #Format int{
        $spwdLastSet = [datetime]::FromFileTime([Int64]::Parse($oLDAPUser.pwdlastset))
        $dpwdLastSet = $spwdLastSet.ToString("G", $oCultureInfo)
        $spwdToInitialize = "False"
    }

    Else{
        $spwdToInitialize = "True"
        $dpwdLastSet = ""
    }

    $DONT_EXPIRE_PASSWORD = 65536
    If($oLDAPUser.useraccountcontrol){
        If($oLDAPUser.useraccountcontrol.Value -band $DONT_EXPIRE_PASSWORD) {$sPwdPermanent = "True"}
        Else {$sPwdPermanent = "False"}
    }

    Else {$sPwdPermanent = "False"}
    $PASSWORD_NOT_REQUIRED = 32
    If($oLDAPUser.useraccountcontrol){
        If($oLDAPUser.useraccountcontrol.Value -band $PASSWORD_NOT_REQUIRED) {$sPwdNotRequired = "True"}
        Else {$sPwdNotRequired = "False"}
    }
    
    Else {$sPwdNotRequired = "False"}
    If (($oLDAPUser.accountexpires -ne 0) -and ($oLDAPUser.accountexpires -ne $NULL) -and ($oLDAPUser.accountexpires -le [DateTime]::MaxValue.Ticks)){
        $saccountExpires = [datetime]::FromFileTime([Int64]::Parse($oLDAPUser.accountexpires))
        $daccountExpires = $saccountExpires.ToString("G", $oCultureInfo)
    }

    Else {$daccountExpires = ""}
    $sbadPwdCount = $oLDAPUser.badpwdcount
    $ACCOUNT_DISABLE = 2
    If($oLDAPUser.useraccountcontrol){
        If($oLDAPUser.useraccountcontrol -band $ACCOUNT_DISABLE) {$sUserAcControl = "Disabled"}
        Else {$sUserAcControl = "Enabled"}
    }
Else {$sUserAcControl = $Null}
$aGroupMembers = Get-ADUser -SearchScope Base -SearchBase $oLDAPUser.distinguishedname -LDAPFilter '(objectClass=user)' -Properties TokenGroups -Server $sDomainName| Select-Object -ExpandProperty TokenGroups | Select-Object -ExpandProperty Value

ForEach($TokenGroup In $aGroupMembers){
    Try{
        If($sSAMAcName){
            If ($DicoToken.ContainsKey($TokenGroup)){
                $sGroupPath_strNameTokenGroup = $DicoToken.Get_Item($TokenGroup)
                $sOutPutMess = "$sSAMAcName;$sGroupPath_strNameTokenGroup"
                $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath2 -Encoding Unicode
            }

        Else{
            $strTokenGroupIndentity = Get-ADGroup -Identity $TokenGroup -Server $sDomainName
            $strNameTokenGroup = $strTokenGroupIndentity.Name
            $strDistNameTokenGroup = $strTokenGroupIndentity.DistinguishedName
            $sGroupPath = ConverTProjetnonicalName $strDistNameTokenGroup $sdomainName
            $sOutPutMess = "$sSAMAcName;$sGroupPath;$strNameTokenGroup"
            $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath2 -Encoding Unicode
            $strGroupForDico = "$sGroupPath;$strNameTokenGroup"

            $DicoToken.Add($TokenGroup,$strGroupForDico)

        }       
    }# If($sSAMAcName)
} # Try

Catch{
    ForEach($ErreurMessage in $Error){
        If (!(($ErreurMessage.CategoryInfo.Category -eq "ObjectNotFound") -and ($ErreurMessage.CategoryInfo.Reason -eq "ADIdentityNotFoundException"))){
            $sOutPutMess = "ATTENTION PROBLEME sur utilisateur $sSAMAcName et le groupe $TokenGroup (Partie Début de traitement du tableau utilisateur du script)"
            $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath2 -Encoding Unicode
            $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ATTENTION PROBLEME - sur utilisateur $sSAMAcName dans fichier $sxyzFilePath2" + " Partie Début de traitement du tableau utilisateur du script"
            $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
            $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ERREUR NON BLOQUANTE - " + ($ErreurMessage.ToString()).Replace("`n","") + "Partie Début de traitement du tableau utilisateur du script"
            $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
            }
    
            Else{
                objSID = New-Object System.Security.Principal.SecurityIdentIfier ($TokenGroup)
                objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
                sOutPutMess = "$sSAMAcName;$objUser;$TokenGroup"
                $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath2 -Encoding Unicode
            }
        } # ForEach

    $Error.clear()
    } # Catch

    If($sSAMAcName) # AjOut des données de l'utilisateur en cours de traitement dans le fichier 1 xyz{
        $sOutPutMess = "$sSAMAcName;$sLastName;$sFirstName;$sdistinguishedNameWithOutUserName;$dWhenCreated;$dWhenChanged;$sUserAcControl;$sUserAccountLocked;$sLastLogOn;$sPasswordExpired;$dpwdLastSet;$sPwdPermanent;$sPwdNotRequired;$daccountExpires;$dLastlockOutTime;$sbadPwdCount;$sPwdProtected;$spwdToInitialize"

        $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath1 -Encoding Unicode
        }
    } # ForEach($TokenGroup In $aGroupMembers)
}# Try de ForEach ($oLDAPUser in $oLDAPUsers)

Catch{
    $sOutPutMess = "ATTENTION PROBLEME sur utilisateur $sSAMAcName;$sLastName;$sFirstName;$sdistinguishedNameWithOutUserName;$dWhenCreated;$dWhenChanged;$sUserAcControl;$sUserAccountLocked;$sLastLogOn;$sPasswordExpired;$dpwdLastSet;$sPwdPermanent;$sPwdNotRequired;$daccountExpires;$dLastlockOutTime;$sbadPwdCount;$sPwdProtected;$spwdToInitialize"

    $sOutPutMess | Out-File -Append -FilePath $sxyzFilePath1 -Encoding Unicode
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ATTENTION PROBLEME - sur utilisateur $sSAMAcName dans fichier $sxyzFilePath1"
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode

ForEach($ErreurMessage in $Error){
    $sLogMessage = (Get-Date).ToString("dd/MM/yyyy HH:mm:ss") + " ERREUR NON BLOQUANTE - " + ($ErreurMessage.ToString()).Replace("`n","")
    $sLogMessage | Out-File -Append -FilePath $sLogFile -Encoding Unicode
    }

        $Error.clear()
        } # Catch
    } # ForEach ($oLDAPUser in $oLDAPUsers) # tableau utilisateur
} # If($oLDAPUsers -And $oListGroup)
[/paycontent]

# Suppression des fichiers temporaires
If(!(Test-Path $sxyzFilePath3)){Remove-Item $sxyzFilePath3}
If(!(Test-path $GPOFileOut)){Remove-Item $GPOFileOut}


Laisser un commentaire