Active Directoryパスワードの有効期限通知

背景



全体の話は、次のIT監査の時が来たという事実から始まりました。 Price Waterhouse Coopersからの深刻な叔父が来て、ログを送信するためにドメインコントローラーで実行する必要のある多くの指示といくつかのスクリプトを提供してくれました。 スクリプトのテキストに慣れ親しんだ後(そして、何がわからないのか、何よりセキュリティが重要)、ログがスクリプトに提供されました。 そして、それが始まりました。



セキュリティポリシーに関連するほとんどの場合のPWC要件。 その1つは、パスワードの複雑さのポリシーとパスワードの有効期間を導入することでした。 もちろん、これを行うのは非常に簡単でしたが、すぐに次の問題が発生しました。外部ネットワークからVPNを介して接続している場合、Windowsはユーザーにパスワードの有効期限を通知しません。 このようなユーザーのパスワードを更新し、アカウントをロック解除するだけではもはや十分ではないため、問題は非常に深刻であることが判明しました。 ラップトップがネイティブオフィスネットワークにあることが必要でした。 一部のユーザーが永遠の出張で「生きている」ことを考えると、問題は非常に深刻であることが判明しました。 それらを手動で追跡することは依然として頭痛の種であり、どういうわけか管理者にはありません。 ここで、自動通知の配信を整理するというアイデアが生まれました。 検索に少し時間を費やした後、必要なアクションをリモートで実行しようとした優れたスクリプトが見つかりました。 私はそれを完成させなければなりませんでした。



PowerShellでスクリプトを記述したのはこれが初めてだったので、多くの時間が費やされました(ほぼ1日)。



スクリプト



そして、ここに私が得たものがあります:



Import-Module ActiveDirectory #System globalization #$ci = New-Object System.Globalization.CultureInfo("ru-RU") #SMTP server name $smtpServer = "mail.domain.local" #Creating a Mail object $msg = new-object Net.Mail.MailMessage #Creating a Mail object for report $msgr = new-object Net.Mail.MailMessage #Creating SMTP server object $smtp = new-object Net.Mail.SmtpClient($smtpServer) #E-mail structure Function EmailStructure($to,$expiryDate,$upn) { $msg.IsBodyHtml = $true $msg.From = "notification@domain.com" $msg.To.Clear() $msg.To.Add($to) $msg.Subject = "Password expiration notice" $msg.Body =</pre><code> "<html><body><font face='Arial'>This is an automatically generated message from Exchange service.<br><br><b>Please note that the password for your account <i><u>Domain\$upn</u></i> will expire on $expiryDate.</b><br><br>Please change your password immediately or at least before this date as you will be unable to access the service without contacting your administrator.</font></body></html>"</code><pre> } Function EmailStructureReport($to) { $msgr.IsBodyHtml = $true $msgr.From = "notification@domain.com" $msgr.To.Add($to) $msgr.Subject = "Script running report" $msgr.Body = </pre><code>"<html><body><font face='Arial'><b>This is a daily report.<br><br>Script has successfully completed its work.<br>$NotificationCounter users have recieved notifications:<br><br>$ListOfAccounts<br><br></b></font></body></html>"</code><pre> } #Set the target OU that will be searched for user accounts $OU = "OU=Organisation,DC=domain,DC=local" </pre><code>$ADAccounts = Get-ADUser -LDAPFilter "(objectClass=user)" -searchbase $OU -properties PasswordExpired, extensionAttribute15, PasswordNeverExpires, PasswordLastSet, Mail, Enabled | Where-object {$_.Enabled -eq $true -and $_.PasswordNeverExpires -eq $false}</code><pre> $NotificationCounter = 0 $ListOfAccounts = "" Foreach ($ADAccount in $ADAccounts) { $accountFGPP = Get-ADUserResultantPasswordPolicy $ADAccount if ($accountFGPP -ne $null) { $maxPasswordAgeTimeSpan = $accountFGPP.MaxPasswordAge } else { $maxPasswordAgeTimeSpan</pre><code> = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge</code><pre> } #Fill in the user variables $samAccountName = $ADAccount.samAccountName $userEmailAddress = $ADAccount.ExtensionAttribute15 $userPrincipalName = $ADAccount.UserPrincipalName if ($ADAccount.PasswordExpired) { Write-host "The password for account $samAccountName has expired!" } else { $ExpiryDate = $ADAccount.PasswordLastSet + $maxPasswordAgeTimeSpan $TodaysDate = Get-Date $DaysToExpire = $ExpiryDate - $TodaysDate #Calculating DaysToExpireDD to DD format (w/o fractional part and dot) $DaysToExpireDD = $DaysToExpire.ToString() -Split ("\S{17}$") Write-host </pre><code>"The password for account $samAccountName expires on: $ExpiryDate. Days left: $DaysToExpireDD"</code><pre> if (($DaysToExpire.Days -eq 15) -or </pre><code>($DaysToExpire.Days -eq 7) -or ($DaysToExpire.Days -le 3))</code><pre> { $expiryDate = $expiryDate.ToString("d",$ci) #Generate e-mail structure and send message if ($userEmailAddress) { EmailStructure $userEmailAddress $expiryDate $samAccountName $smtp.Send($msg) Write-Host </pre><code>"NOTIFICATION - $samAccountName :: e-mail was sent to $userEmailAddress"</code><pre> $NotificationCounter = $NotificationCounter + 1 $ListOfAccounts = </pre><code>$ListOfAccounts + $samAccountName + " - $DaysToExpireDD days left. Sent to $userEmailAddress<br>"</code><pre> } } } } Write-Host "SENDING REPORT TO IT DEPARTMENT" EmailStructureReport("itdepartment@domain.com") $smtp.Send($msgr)
      
      







これをテキストとして拡張子.ps1のファイルに保存します。



起動コマンド



次に-拡張子が.cmdのファイルを作成し、スクリプト起動パラメーターをそのファイルに書き込みます。 私にとってはこのように見えます:



powershell D:\ExchangeTools\pwde.ps1









どちらのファイルもメールサーバーにあります。 オプションを試すことができます。



タイムラインを作成する



次に、.cmdファイルの毎日の起動をスケジュールします。 毎日午前11時に実行しています。

[スタート]> [すべてのプログラム]> [アクセサリ]> [システムツール]> [タスクスケジューラ]。

[アクション]> [新しいタスクの作成]をクリックします。



[全般]タブで[ユーザーの変更]ボタンをクリックし、すべての作業を行うユーザーを選択します。 ユーザーには、ADからスクリプトに必要なパラメーターを読み取る権限が必要です。 「ユーザーがログオンしているかどうかに関係なく実行する」を設定します(ユーザーがログインしているかどうかに関係なく実行します)。 タスクを保存するとき、システムはユーザーパスワードの入力を求めます。



次は「トリガー」タブです。 ここではすべてが簡単です-必要に応じて起動時間を設定します。



[アクション]タブで、[新規]をクリックし、[プログラムの開始]を選択して、.cmdファイルへのパスを指定します。 最後の2つのタブはタッチできませんが、必要に応じて、必要に応じて変更を加えてください。



通知は15、7、3日以内に送信されます。



ご注意

Exchangeサーバーは、ドメイン外のアドレス(たとえば、個人アドレスへの複製)に送信する予定の場合、独自のアドレスをリレーとして指定する必要があります。



「ユーザーの電子メールを含む標準フィールドがある場合、なぜExtensionAttributeからアドレスを取得するのですか?」 答えは簡単です-各通知のコピーもIT部門に送信されます。ユーザーは複数のアドレスを持ち、一部のシステムアカウントには原則としてメールボックスがありませんが、管理者自身の作業を楽にするためにそれらに関する通知が必要です。 ExtensionAttribute15にアドレスを入力するには、管理者権限を持つドメインコントローラーのActive Directoryツリーに移動します。 アカウントのプロパティには、「属性エディター」タブがあります。 フィールドに複数のアドレスがある場合は、コンマで区切る必要があります。



All Articles