diff --git a/scripts_staging/Backend/Mail notification password expiry.ps1 b/scripts_staging/Backend/Mail notification password expiry.ps1 index ba4227fd..10ce765f 100644 --- a/scripts_staging/Backend/Mail notification password expiry.ps1 +++ b/scripts_staging/Backend/Mail notification password expiry.ps1 @@ -1,59 +1,65 @@ -<# +<# .SYNOPSIS - Script permettant de récupérer et analyser les utilisateurs dont le mot de passe est sur le point d'expirer dans Active Directory. + Analyse et notification avancée des utilisateurs dont le mot de passe Active Directory approche de l’expiration. .DESCRIPTION - Ce script se connecte à Active Directory pour rechercher les utilisateurs dans une unité organisationnelle spécifiée. - Il récupère la date de dernière mise à jour du mot de passe pour chaque utilisateur et la compare à la politique de mot de passe du domaine. - En fonction du nombre de jours restant avant l'expiration, les comptes sont classés en trois catégories : - - Expiré : Le mot de passe a déjà expiré. - - Critique : Le mot de passe est très proche de l'expiration, selon le seuil critique configuré. - - Avertissement : Le mot de passe approche de l'expiration, selon le seuil d'avertissement configuré. - Le script génère un rapport HTML contenant : - • Les détails de la politique de mot de passe du domaine (durée maximale, durée minimale, longueur minimale, complexité, historique et seuils de verrouillage). - • Un résumé statistique indiquant le nombre d'utilisateurs par catégorie. - • Une liste détaillée des comptes répartis par catégorie. - Les options de test ont été supprimées. + Ce script interroge Active Directory pour lister les utilisateurs d’une OU cible et calcule la date d’expiration de leur mot de passe selon la politique du domaine. + Les comptes sont classés selon l’urgence : + - Expiré : mot de passe déjà expiré + - Critique : expiration imminente (seuil critique) + - Avertissement : expiration proche (seuil d’avertissement) + Notifications automatiques : + • Email pour tous les utilisateurs concernés + Un rapport HTML détaillé est généré : + • Politique de mot de passe du domaine + • Statistiques par catégorie + • Liste détaillée des comptes par statut .PARAMETER TargetOU - Spécifie l'OU dans laquelle rechercher les utilisateurs. Exemple : "OU=Utilisateurs,DC=domaine,DC=local". + OU cible pour la recherche des utilisateurs (ex : "OU=Utilisateurs,DC=domaine,DC=local") .PARAMETER WarningThreshold - Nombre de jours avant expiration déclenchant un avertissement (par défaut : 15). + Jours avant expiration pour déclencher un avertissement (défaut : 15) .PARAMETER CriticalThreshold - Nombre de jours avant expiration déclenchant une alerte critique (par défaut : 7). + Jours avant expiration pour déclencher une alerte critique (défaut : 7) .PARAMETER IncludeDisabled - Indique si les comptes désactivés doivent être inclus dans le rapport (false par défaut). + Inclure les comptes désactivés dans le rapport (défaut : false) .PARAMETER IncludeNeverExpires - Indique si les comptes dont le mot de passe n'expire jamais doivent être inclus dans le rapport (false par défaut). -.EXAMPLE - .\Check-PasswordExpiration.ps1 -TargetOU "OU=Utilisateurs,DC=domaine,DC=local" - Exécute le script avec l'OU spécifiée et les seuils par défaut. -.EXAMPLE - .\Check-PasswordExpiration.ps1 -TargetOU "OU=Utilisateurs,DC=domaine,DC=local" -WarningThreshold 20 -CriticalThreshold 10 - Exécute le script avec des seuils personnalisés pour les alertes d’avertissement et critiques. + Inclure les comptes dont le mot de passe n’expire jamais (défaut : false) +.PARAMETER EmailSignature + Signature personnalisée pour les emails (optionnel) .NOTES - Author: Peter Quellennec - Date: 27/05/25 + Prérequis : + - Module ActiveDirectory + - Accès SMTP pour l’envoi d’emails + - Droits d’administration pour les tâches planifiées + Author: PQU + Date: 29/04/2025 #public +.CHANGELOG + 22.05.25 SAN – Added UTF8 encoding to resolve issues with Russian and French characters. + 06.06.25 PQU – Added support for multiple admin emails and centralized config. #> -{{CallPowerShell7Lite}} + + +{{CallPowerShell7}} + +function Convert-ToBoolean($value) { + return $value -match '^(1|true|yes)$' +} $TargetOU = $env:TARGET_OU $SmtpServer = $env:SMTP_SERVER $SmtpPort = [int]$env:SMTP_PORT -$AdminEmail = $env:ADMIN_EMAIL +$AdminEmails = $env:ADMIN_EMAIL -split '[,;]' | ForEach-Object { $_.Trim() } | Where-Object { $_ } $FromEmail = $env:FROM_EMAIL -$signmail = $env:SIGNMAIL $WarningThreshold = [int]$env:WARNING_THRESHOLD $CriticalThreshold = [int]$env:CRITICAL_THRESHOLD $EmailSignature = $env:EMAIL_SIGNATURE - -function Convert-ToBoolean($value) { - return $value -match '^(1|true|yes)$' -} - $IncludeDisabled = Convert-ToBoolean $env:INCLUDE_DISABLED $IncludeNeverExpires = Convert-ToBoolean $env:INCLUDE_NEVER_EXPIRES $GenerateReportOnly = Convert-ToBoolean $env:GENERATE_REPORT_ONLY + + + if ($env:SMTP_CREDENTIAL_USERNAME -and $env:SMTP_CREDENTIAL_PASSWORD) { try { $SecurePassword = ConvertTo-SecureString $env:SMTP_CREDENTIAL_PASSWORD -AsPlainText -Force @@ -64,25 +70,20 @@ if ($env:SMTP_CREDENTIAL_USERNAME -and $env:SMTP_CREDENTIAL_PASSWORD) { } function Test-Prerequisites { - $adFeature = Get-WindowsFeature -Name AD-Domain-Services -ErrorAction Stop if ($adFeature.InstallState -ne 'Installed') { Write-Error "AD Domain Services ne sont pas installés. Arrêt du script." exit 1 } - if (-not $SmtpServer -or -not $SmtpPort) { Write-Error "Les variables `$SmtpServer et `$SmtpPort doivent être définies avant d'appeler cette fonction." exit 1 } - if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) { Write-Error "Module ActiveDirectory non trouvé. Arrêt du script." exit 1 } - Import-Module ActiveDirectory -ErrorAction Stop - try { $dc = Get-ADDomainController -Discover -ErrorAction Stop Write-Host "Connexion réussie au contrôleur de domaine : $($dc.HostName)" @@ -91,7 +92,6 @@ function Test-Prerequisites { Write-Error "Impossible de se connecter au contrôleur de domaine. Arrêt du script." exit 1 } - try { $tcpClient = New-Object System.Net.Sockets.TcpClient $tcpClient.Connect($SmtpServer, $SmtpPort) @@ -109,7 +109,6 @@ function Get-UserPasswordExpirationInfo { $user, $maxPasswordAge ) - $result = [PSCustomObject]@{ Name = $user.Name SamAccountName = $user.SamAccountName @@ -120,23 +119,18 @@ function Get-UserPasswordExpirationInfo { Enabled = $user.Enabled PasswordNeverExpires = $user.PasswordNeverExpires } - if ($user.PasswordLastSet -eq $null) { $result.Status = "NeverLoggedIn" return $result } - if ($user.PasswordNeverExpires) { $result.Status = "NeverExpires" return $result } - $passwordExpirationDate = $user.PasswordLastSet + $maxPasswordAge $daysLeft = ($passwordExpirationDate - (Get-Date)).Days - $result.ExpirationDate = $passwordExpirationDate $result.DaysLeft = $daysLeft - if ($daysLeft -lt 0) { $result.Status = "Expired" } @@ -146,7 +140,6 @@ function Get-UserPasswordExpirationInfo { elseif ($daysLeft -le $WarningThreshold) { $result.Status = "Warning" } - return $result } @@ -164,110 +157,304 @@ function ConvertTo-HtmlReport { $criticalThreshold ) + $expiredSection = "" + if ($expiredUsers.Count -gt 0) { + $rows = $expiredUsers | ForEach-Object { + " + $($_.Name) + $($_.SamAccountName) + $($_.Email) + $($_.ExpirationDate.ToString('dd/MM/yyyy')) + $($_.DaysLeft) + $($_.Enabled) + " + } | Out-String + $expiredSection = @" +
+

Comptes expirés

+ + + + + + + + + + + + + $rows + +
NomSAM Account NameEmailDate d'expirationJours restantsActivé
+
+"@ + } + $criticalSection = "" + if ($criticalUsers.Count -gt 0) { + $rows = $criticalUsers | ForEach-Object { + " + $($_.Name) + $($_.SamAccountName) + $($_.Email) + $($_.ExpirationDate.ToString('dd/MM/yyyy')) + $($_.DaysLeft) + $($_.Enabled) + " + } | Out-String + $criticalSection = @" +
+

Comptes critiques

+ + + + + + + + + + + + + $rows + +
NomSAM Account NameEmailDate d'expirationJours restantsActivé
+
+"@ + } + $warningSection = "" + if ($warningUsers.Count -gt 0) { + $rows = $warningUsers | ForEach-Object { + " + $($_.Name) + $($_.SamAccountName) + $($_.Email) + $($_.ExpirationDate.ToString('dd/MM/yyyy')) + $($_.DaysLeft) + $($_.Enabled) + " + } | Out-String + $warningSection = @" +
+

Comptes en avertissement

+ + + + + + + + + + + + + $rows + +
NomSAM Account NameEmailDate d'expirationJours restantsActivé
+
+"@ + } + $neverExpiresSection = "" + if ($IncludeNeverExpires -and $neverExpiresUsers.Count -gt 0) { + $rows = $neverExpiresUsers | ForEach-Object { + " + $($_.Name) + $($_.SamAccountName) + $($_.Email) + $($_.Enabled) + " + } | Out-String + $neverExpiresSection = @" +
+

Comptes avec mot de passe n'expirant jamais

+ + + + + + + + + + + $rows + +
NomSAM Account NameEmailActivé
+
+"@ + } + $neverLoggedInSection = "" + if ($neverLoggedInUsers.Count -gt 0) { + $rows = $neverLoggedInUsers | ForEach-Object { + " + $($_.Name) + $($_.SamAccountName) + $($_.Email) + $($_.Enabled) + " + } | Out-String + $neverLoggedInSection = @" +
+

Comptes jamais connectés

+ + + + + + + + + + + $rows + +
NomSAM Account NameEmailActivé
+
+"@ + } + $disabledSection = "" + if ($IncludeDisabled -and $disabledUsers.Count -gt 0) { + $rows = $disabledUsers | ForEach-Object { + " + $($_.Name) + $($_.SamAccountName) + $($_.Email) + $($_.ExpirationDate.ToString('dd/MM/yyyy')) + $($_.DaysLeft) + " + } | Out-String + $disabledSection = @" +
+

Comptes désactivés

+ + + + + + + + + + + + $rows + +
NomSAM Account NameEmailDate d'expirationJours restants
+
+"@ + } + $html = @" + + Rapport d'expiration des mots de passe +

Rapport d'expiration des mots de passe

- -
+

Politique de mot de passe du domaine

-

Durée maximale du mot de passe: $($passwordPolicy.MaxPasswordAge.Days) jours

-

Durée minimale du mot de passe: $($passwordPolicy.MinPasswordAge.Days) jours

+

Durée maximale: $($passwordPolicy.MaxPasswordAge.Days) jours

+

Durée minimale: $($passwordPolicy.MinPasswordAge.Days) jours

Longueur minimale: $($passwordPolicy.MinPasswordLength) caractères

Complexité requise: $($passwordPolicy.ComplexityEnabled)

-

Historique du mot de passe: $($passwordPolicy.PasswordHistoryCount) mots de passe

-

Verrouillage de compte: $($passwordPolicy.LockoutThreshold) tentatives (durée: $($passwordPolicy.LockoutDuration.Minutes) minutes, observation: $($passwordPolicy.LockoutObservationWindow.Minutes) minutes)

+

Historique: $($passwordPolicy.PasswordHistoryCount) mots de passe

+

Verrouillage: $($passwordPolicy.LockoutThreshold) tentatives (durée: $($passwordPolicy.LockoutDuration.Minutes) min)

- -
-

Seuil d'avertissement : $warningThreshold jours

-

Seuil critique : $criticalThreshold jours

-

Statistiques : +

+

Statistiques globales

+

Expirés: $($expiredUsers.Count) Critiques: $($criticalUsers.Count) - Avertissement: $($warningUsers.Count) + Avertissements: $($warningUsers.Count) Expirent jamais: $($neverExpiresUsers.Count) Jamais connectés: $($neverLoggedInUsers.Count) Désactivés: $($disabledUsers.Count)

-"@ - - if ($expiredUsers) { - $html += "

Comptes expirés $($expiredUsers.Count)

" - $html += $expiredUsers | Select-Object Name, SamAccountName, Email, @{Name="ExpirationDate";Expression={$_.ExpirationDate.ToString("dd/MM/yyyy")}}, DaysLeft, Enabled | ConvertTo-Html -Fragment - } - - if ($criticalUsers) { - $html += "

Comptes critiques $($criticalUsers.Count)

" - $html += $criticalUsers | Select-Object Name, SamAccountName, Email, @{Name="ExpirationDate";Expression={$_.ExpirationDate.ToString("dd/MM/yyyy")}}, DaysLeft, Enabled | ConvertTo-Html -Fragment - } - - if ($warningUsers) { - $html += "

Comptes en avertissement $($warningUsers.Count)

" - $html += $warningUsers | Select-Object Name, SamAccountName, Email, @{Name="ExpirationDate";Expression={$_.ExpirationDate.ToString("dd/MM/yyyy")}}, DaysLeft, Enabled | ConvertTo-Html -Fragment - } - - if ($IncludeNeverExpires -and $neverExpiresUsers) { - $html += "

Comptes avec mot de passe n expirant jamais $($neverExpiresUsers.Count)

" - $html += $neverExpiresUsers | Select-Object Name, SamAccountName, Email, Enabled | ConvertTo-Html -Fragment - } - - if ($neverLoggedInUsers) { - $html += "

Comptes jamais connectés $($neverLoggedInUsers.Count)

" - $html += $neverLoggedInUsers | Select-Object Name, SamAccountName, Email, Enabled | ConvertTo-Html -Fragment - } - - if ($IncludeDisabled -and $disabledUsers) { - $html += "

Comptes désactivés $($disabledUsers.Count)

" - $html += $disabledUsers | Select-Object Name, SamAccountName, Email, @{Name="ExpirationDate";Expression={if($_.ExpirationDate){$_.ExpirationDate.ToString("dd/MM/yyyy")}else{"N/A"}}}, DaysLeft | ConvertTo-Html -Fragment - } - - $html += @" -

Généré le : $(Get-Date -Format "dd/MM/yyyy HH:mm")

+ $expiredSection + $criticalSection + $warningSection + $neverExpiresSection + $neverLoggedInSection + $disabledSection + +
"@ - return $html } + function Get-EmailSignature { if ($EmailSignature) { - return $EmailSignature + return "" } - - return @" -
-

+ return @" +