PowerShell – Superviser l’expiration des mots de passe (Centreon)

  • Auteur/autrice de la publication :
  • Dernière modification de la publication :21 janvier 2024
  • Post category:PowerShell / Supervision
  • Temps de lecture :8 min de lecture
  • Commentaires de la publication :0 commentaire

Yo, récemment, j’ai mis en place des comptes gMSA sur l’infrastructure pour renforcer la sécurité, et surtout, pour éliminer certains comptes de services dont le mot de passe n’expire jamais. Malheureusement, gMSA n’est pas compatible avec toutes les applications, et pour les rares comptes de service restants, j’ai désactivé l’option « Le mot de passe n’expire jamais ». Cela signifie que je dois maintenant surveiller la période d’expiration des mots de passe de ces comptes pour éviter toute interruption de service, et les changer tous les 180 jours.

Pour simplifier cette tâche, j’ai créé un script PowerShell dédié à la surveillance de ces comptes depuis Centreon. N’hésitez pas à l’adapter à vos besoins.

Le script peut checker 1 ou plusieurs compte à la fois

.\check_password_expiration.ps1 -account "user1,user2,user3" -warning 7 -critical 3

Il peut également checker par OU :

.\check_password_expiration.ps1 -searchbase "ou=Users,dc=example,dc=com" -warning 10 -critical 5

Il est possible de ne pas mettre les seuils. Par défaut c’est :

  • Warning = mois de 10 jours avant expiration
  • Critical = moins de 5 jours avant expiration
[int]$warning = 10, 
[int]$critical = 5,

Check Expiration Account

Pour vérifier par compte ou plusieurs

.\check_password_expiration.ps1 -account "xxxx,centreon,xxxxx,xxxxx,xxxxx,sysprep,xxxxx,xxxxx,test1"
CRITICAL: xxxxx has password set to never expire.
OK: centreon will expire in 180 days.
OK: xxxxx will expire in 175 days.
OK: xxxxx will expire in 179 days.
CRITICAL: xxxxx will expire in 2 days.
OK: sysprep will expire in 179 days.
CRITICAL: xxxxx has password set to never expire.
CRITICAL: xxxxx has password set to never expire.
CRITICAL: xxxxx has password set to never expire.
UNKNOWN: Account  test1 not found.

Remarque :
J’ai masqué les noms…
Si le compte à la case « Le mot de passe n’expire jamais » cochée, il le remonte.
Si le compte n’existe pas, il le remonte
Il remonte les comptes qui ont déjà expiré.

Check Expiration par OU

Pour vérifier par OU :

.\check_password_expiration.ps1 -searchbase "ou=USERS,ou=SYSTEM,ou=ADMIN,dc=DOM,dc=LOCAL"
CRITICAL: xxxxx will expire in 2 days.
OK: xxxxx will expire in 62 days.
WARNING: xxxxx will expire in 6 days.
OK: xxxxx will expire in 57 days.
CRITICAL: xxxxx is expired for 154468 days.
CRITICAL: xxxxx is expired for 154468 days.
OK: xxxxx will expire in 169 days.
OK: xxxxx will expire in 22 days.
CRITICAL: xxxxx has password set to never expire.
OK: xxxxx will expire in 89 days.
[...]

Remarque :
Bon, le but ce n’est pas de checker tout le monde.

Script PowerShell

Voici le script PowerShell :

<#
.SYNOPSIS
    Script for checking Active Directory user password expiration.

.DESCRIPTION
    This script checks the expiration status of passwords for Active Directory users.

.AUTHOR
    asysadminstory.fr

.VERSION
    1.0 - Initial version: Check AD user password expiration.

.PARAMETER searchbase
    Specifies the Organizational Unit (OU) to check for user password expiration.

.PARAMETER account
    Specifies one or more user accounts to check for password expiration.

.PARAMETER warning
    Sets the warning threshold for password expiration in days.

.PARAMETER critical
    Sets the critical threshold for password expiration in days.

.PARAMETER help
    Displays the script usage help.

.EXAMPLE
    .\check_password_expiration.ps1 -searchbase "ou=Users,dc=example,dc=com" -warning 10 -critical 5

    Checks password expiration for all users in the specified Organizational Unit.

.EXAMPLE
    .\check_password_expiration.ps1 -account "user1,user2,user3" -warning 7 -critical 3

    Checks password expiration for the specified user accounts.
#>

param (
    [string]$searchbase,
    [string]$account,
    [int]$warning = 10,
    [int]$critical = 5,
    [switch]$help
)

function Show-Help {
    Write-Host "Usage: Check-ADPasswordExpiration.ps1 -searchbase <OU> -account <account1,account2> [-warning <days>] [-critical <days>] [-help]"
}

function Get-PasswordExpiration {
    param (
        [string]$samAccountName
    )

    $user = Get-AdUser -Filter {SamAccountName -eq $samAccountName} -Properties "SamAccountName", "msDS-UserPasswordExpiryTimeComputed", "PasswordNeverExpires"

    if ($user) {
        # Vérifier si le mot de passe n'expire jamais
        if ($user.PasswordNeverExpires) {
            Write-Host "CRITICAL:", $($user.SamAccountName), "has password set to never expire."
            return 2
        }

        $expirationDate = [datetime]::FromFileTime($user."msDS-UserPasswordExpiryTimeComputed")
        $daysRemaining = ($expirationDate - (Get-Date)).Days

        if ($daysRemaining -lt 0) {
            Write-Host "CRITICAL:",$($user.SamAccountName), "is expired for", $($daysRemaining * -1), "days."
            return 2
        } elseif ($daysRemaining -lt $critical) {
            Write-Host "CRITICAL:",$($user.SamAccountName), "will expire in", $daysRemaining, "days."
            return 2
        } elseif ($daysRemaining -lt $warning) {
            Write-Host "WARNING:",$($user.SamAccountName), "will expire in", $daysRemaining, "days."
            return 1
        } else {
            Write-Host "OK:",$($user.SamAccountName), "will expire in", $daysRemaining, "days."
            return 0
        }
    } else {
        Write-Host "UNKNOWN: Account ",$samAccountName, "not found."
        return 3
    }
}

if ($help) {
    Show-Help
    exit 3
}

if (($searchbase -and $account) -or (-not $searchbase -and -not $account)) {
    Write-Host "ERROR: Either --searchbase or --account is required, but not both."
    exit 3
}

if ($account) {
    $accounts = $account -split ","
    $globalStatus = $null

    foreach ($acc in $accounts) {
        $status = Get-PasswordExpiration -samAccountName $acc.Trim()

        # Mettre à jour le statut global en cas de sortie critique ou inconnue
        if ($status -eq 2 -or $status -eq 3) {
            $globalStatus = $status
        }
    }

    # Sortie du statut global après avoir vérifié tous les comptes.
    if ($globalStatus -eq $null) {
        Write-Host "OK: All specified accounts are within expiration thresholds."
        exit 0
    } else {
        exit $globalStatus
    }
} elseif ($searchbase) {
    $users = Get-AdUser -Filter * -SearchBase $searchbase -Properties "SamAccountName", "msDS-UserPasswordExpiryTimeComputed", "PasswordNeverExpires"
    $globalStatus = $null

    foreach ($user in $users) {
        $status = Get-PasswordExpiration -samAccountName $user.SamAccountName

        # Mettre à jour le statut global en cas de sortie critique ou inconnue
        if ($status -eq 2 -or $status -eq 3) {
            $globalStatus = $status
        }
    }

    # Sortie du statut global après avoir vérifié tous les comptes.
    if ($globalStatus -eq $null) {
        Write-Host "OK: All accounts in the specified search base are within expiration thresholds."
        exit 0
    } else {
        exit $globalStatus
    }
} else {
    Write-Host "ERROR: Either --searchbase or --account is required."
    exit 3
}

Check via Centreon

Vous devez installer et configurer NSClient++ sur l’un de vos serveurs Active Directory. Mon fichier de conf NSClient se trouve ici : https://asysadminstory.fr/active-directory-dcdiag-avec-centreon-nsclient/

Il y a une version NSClient faite par Centreon intégrant les connecteurs de supervision.

J’ai mis le script PowerShell sur un serveur AD dans : C:\Scripts\check_password_expiration.ps1

Les commandes à mettre dans le fichier nsclient.ini

[/settings/external scripts/scripts]
# Check by account
check_account=cmd /c echo C:\Scripts\check_password_expiration.ps1 -account $ARG1$; exit $LastExitCode | powershell.exe -command -

#Check by OU
check_account_dn=cmd /c echo C:\Scripts\check_password_expiration.ps1 -searchbase $ARG1$; exit $LastExitCode | powershell.exe -command -

Se connecter à votre serveur Centreon et tester avec le plugin NSClient RestAPI:

[centreon-engine@centreon-central ~]$ /usr/lib/centreon/plugins/centreon_nsclient_restapi.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname=IP_AD --port='8443' --proto='https' --legacy-password='InNSClient.ini' --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --timeout=30 --command=check_account --arg='"xxxx,centreon,xxxx,xxxx,xxxx,sysprep,xxxx,xxxx"'
CRITICAL: xxxx has password set to never expire.
OK: centreon will expire in 179 days.
OK: xxxx will expire in 175 days.
OK: xxxx will expire in 179 days.
CRITICAL: xxxx will expire in 2 days.
OK: sysprep will expire in 179 days.
CRITICAL: xxxx has password set to never expire.
CRITICAL: xxxx has password set to never expire.
[centreon-engine@centreon-central ~]$

Vérifier les utilisateurs dans une OU

[centreon-engine@centreon-central ~]$ /usr/lib/centreon/plugins/centreon_nsclient_restapi.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname=IP_AD --port='8443' --proto='https' --legacy-password='inNSClient.ini' --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --timeout=30 --command=check_account_dn --arg='"ou=USERS,ou=SYSTEME,ou=ADMIN,dc=DOM,dc=LOCAL"'
CRITICAL: xxxxx will expire in 2 days.
OK: xxxxx  will expire in 62 days.
WARNING: xxxxx  will expire in 6 days.
OK: xxxxx will expire in 57 days.
CRITICAL: xxxxx is expired for 154468 days.
CRITICAL: xxxxx is expired for 154468 days.
OK: xxxxx will expire in 169 days.
OK: xxxxx will expire in 22 days.
CRITICAL: xxxxx has password set to never expire.
OK: xxxxx will expire in 89 days.
[...]

La commande pour Centreon WEB

  • Nom : Windows-NSClient05-RestAPI
  • Commande :
$CENTREONPLUGINS$/centreon_nsclient_restapi.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname=$HOSTADDRESS$ --port='$_HOSTNSCPRESTAPIPORT$' --proto='$_HOSTNSCPRESTAPIPROTO$' --legacy-password='$_HOSTNSCPRESTAPILEGACYPASSWORD$' $_HOSTNSCPRESTAPIEXTRAOPTIONS$ --command=$_SERVICECOMMAND$ --arg=$_SERVICEARG1$

Configurer le service depuis l’interface web :

Centreon_Service

ARG1 = '"compte1,compte2,compte3"'

Répétez l’opération pour checker via une OU si vous le souhaitez.

Check_Account_Expiration_AD

Amusez vous bien. A très bientôt.

Bonne journée .

Laisser un commentaire