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 { + "
| Nom | +SAM Account Name | +Date d'expiration | +Jours restants | +Activé | +
|---|
| Nom | +SAM Account Name | +Date d'expiration | +Jours restants | +Activé | +
|---|
| Nom | +SAM Account Name | +Date d'expiration | +Jours restants | +Activé | +
|---|
| Nom | +SAM Account Name | +Activé | +
|---|
| Nom | +SAM Account Name | +Activé | +
|---|
| Nom | +SAM Account Name | +Date d'expiration | +Jours restants | +
|---|
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 : +
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)
Généré le : $(Get-Date -Format "dd/MM/yyyy HH:mm")
+ $expiredSection + $criticalSection + $warningSection + $neverExpiresSection + $neverLoggedInSection + $disabledSection + ++ return @" +
Service Informatique
- Téléphone : +33 (0)1 XX XX XX XX
+ Téléphone : +00 (0)1 XX XX XX XX
Email : support@domain.com
Ce message est généré automatiquement, merci de ne pas y répondre directement.
') { + $bodyWithSignature = $Body -replace '(?i)', "$signature" + } else { + $bodyWithSignature = "$Body$signature" + } $mailMessage = New-Object System.Net.Mail.MailMessage $mailMessage.From = $FromAddress foreach ($recipient in $Recipients) { $mailMessage.To.Add($recipient) } $mailMessage.Subject = $Subject - $mailMessage.Body = $Body + $mailMessage.Body = $bodyWithSignature $mailMessage.IsBodyHtml = $true - if ($Attachments) { + if ($Attachments) { foreach ($att in $Attachments) { $mailMessage.Attachments.Add((New-Object System.Net.Mail.Attachment($att))) } } $smtpClient = New-Object System.Net.Mail.SmtpClient($SmtpServer, $Port) + if ($SmtpCredential) { + $smtpClient.Credentials = $SmtpCredential + } try { $smtpClient.Send($mailMessage) Write-Host "Email sent successfully." @@ -322,18 +517,84 @@ function Send-UserNotification { [string]$FromAddress ) $signature = Get-EmailSignature - if ($Body -match '') { - } else { - $bodyWithSignature = "$Body$signature" + $bodyWithSignature = $Body + if ($Body -match '(?i)') { + $bodyWithSignature = $Body -replace '(?i)', "$signature" + } else { + $bodyWithSignature = @" + + +
+ + + +
+