PowerShellでADユーザーアカウントのパスワード期限を確認する方法

AD DSユーザーのパスワード期限は、Get-ADUserでユーザーごとの msDS-UserPasswordExpiryTimeComputed を取得して確認します。全員にドメイン既定のMaxPasswordAgeを足すだけでは、詳細なパスワードポリシー(PSO)があるユーザーの期限を誤る可能性があります。この記事は読み取りと対象の抽出に限定し、アカウントの無効化やメール送信は行いません。

目次

実行前に確認すること

対象はオンプレミスのActive Directory Domain Servicesです。Microsoft Entra IDだけのユーザーやAD LDS向けの手順ではありません。RSATのActive Directory PowerShellモジュール、対象DCへの接続、属性を読む権限を確認します。必要以上のDomain Admins権限を使わず、最初はテストユーザー1名から確認してください。サーバー名、ユーザー名、OUはすべて例です。

1人のパスワード期限を確認する

次の関数は、通常の日付へ変換できない特殊値を先に分類します。期限をUTCで出力し、実行PCのタイムゾーンによる比較の混乱を避けます。PasswordLastSetは取得元の表示なので、列名と時刻の基準を区別してください。

Import-Module ActiveDirectory -ErrorAction Stop
$dc = 'dc01.example.com'   # 対象ドメインのDCへ置換
$properties = @('PasswordLastSet','PasswordNeverExpires',
                'msDS-UserPasswordExpiryTimeComputed','EmailAddress')

function Convert-PasswordExpiryReport {
    param($User)
    $raw = $User.'msDS-UserPasswordExpiryTimeComputed'
    $expiry = $null
    if ($null -eq $raw) {
        $state = '未取得・要確認'
    } elseif ([long]$raw -eq [long]::MaxValue) {
        $state = '通常の期限日時なし'
    } elseif ([long]$raw -eq 0) {
        $state = 'pwdLastSet未設定または0・要確認'
    } else {
        try {
            $expiry = [datetime]::FromFileTimeUtc([long]$raw)
            $state = if ($expiry -le [datetime]::UtcNow) {'期限切れ'} else {'期限内'}
        } catch {
            $state = '日時変換不可・要確認'
        }
    }
    [pscustomobject]@{
        SamAccountName = $User.SamAccountName
        Enabled = $User.Enabled
        PasswordLastSet = $User.PasswordLastSet
        PasswordNeverExpires = $User.PasswordNeverExpires
        ExpiryUtc = $expiry
        State = $state
        EmailAddress = $User.EmailAddress
    }
}

$user = Get-ADUser -Identity 'user01' -Server $dc -Properties $properties -ErrorAction Stop
Convert-PasswordExpiryReport $user | Format-List

結果の読み方

ExpiryUtcが実際の期限日時です。「通常の期限日時なし」はPasswordNeverExpiresだけでなく、スマートカード必須など別の条件でも返り得ます。0はpwdLastSetが未設定または0である状態として区別し、1601年などの期限として扱いません。未取得や変換不可を「期限なし」に読み替えず、DC、権限、属性、ユーザー状態を確認します。

パスワードの期限、アカウント自体の有効期限(AccountExpirationDate)、Enabled、ロックアウトは別の状態です。期限切れだからアカウントが自動的に無効になる、または無効化すべきだとは判断しません。

適用されるパスワードポリシーを確認する

Get-ADUserResultantPasswordPolicy -Identity 'user01' -Server $dc
Get-ADDefaultDomainPasswordPolicy -Server $dc

前者はユーザーに適用される詳細なパスワードポリシーを確認するためのコマンドです。該当するPSOがない場合はドメイン既定のポリシーも確認します。問い合わせ先DCを揃え、直前にパスワードやポリシーを変更した場合はレプリケーションの状況も調べてください。

指定OUの期限切れユーザーを一覧にする

先ほどの関数を定義した同じPowerShellで実行します。全ドメインへ無条件に広げず、まず対象OUを指定して結果を照合します。読み取りに失敗した場合は処理を止め、空の結果を「対象なし」と見なさないでください。

$ou = 'OU=Staff,DC=example,DC=com'
$report = @(Get-ADUser -Filter * -SearchBase $ou -Server $dc -Properties $properties -ErrorAction Stop |
    ForEach-Object { Convert-PasswordExpiryReport $_ })

$report | Where-Object { $_.Enabled -and $_.State -eq '期限切れ' } |
    Select-Object SamAccountName, ExpiryUtc, State

今後14日以内に期限が来る通知候補

既に期限切れの人を混ぜず、「現在より後、14日後まで」の範囲を抽出します。この例は表示だけで、メールを送りません。

$now = [datetime]::UtcNow
$limit = $now.AddDays(14)
$report | Where-Object {
    $_.Enabled -and $null -ne $_.ExpiryUtc -and
    $_.ExpiryUtc -gt $now -and $_.ExpiryUtc -le $limit
} | Select-Object SamAccountName, EmailAddress, ExpiryUtc

実際の通知は、宛先の正確性、サービス用アカウントの除外、重複送信防止、送信履歴、組織の承認を別途設計します。Send-MailMessageはMicrosoftが非推奨としており、新しい通知処理の前提にしません。承認されたメール基盤の認証・権限を確認し、パスワードや認証情報を本文やコードに埋め込まないでください。

期限切れユーザーを自動無効化しない

期限切れは、そのアカウントを停止する判断材料の一つにすぎません。サービス、バッチ、業務システムに使われるユーザーを一覧から一括無効化すると障害になる可能性があります。結果はまず管理者の確認用とし、所有者、用途、組織ポリシー、復旧手順を確認した別の変更作業で扱います。

運用上の注意

レポートにはアカウント名やメールアドレスが含まれます。公開サイトへ貼り付けず、アクセスを制限した場所で扱います。定期実行する場合も対象OU、問い合わせ先DC、実行日時、取得エラーを記録し、特殊値の件数が急に変わったら調べてください。本例は属性とコマンド仕様に基づくサンプルで、利用組織のAD環境での実行検証はしていません。

公式資料

Microsoft:期限計算属性の仕様/Get-ADUserResultantPasswordPolicy/Send-MailMessageの注意事項。

まとめ

ユーザーごとの計算済み期限を取得し、特殊値と通常の日付を分けて確認するのが基本です。最初は1人、次に限定OUへ広げ、期限切れ・期限前の候補を区別します。調査結果から自動でメール送信やアカウント停止へ進めないことが重要です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次