PowerShell が私の中で最近急上昇株になっています。そんなわけで、Active Directory に接続して、ユーザを特定の条件を元に検索し、該当したユーザのプロパティを設定するサンプルを掲載します。
検索条件として特定に日時よりパスワード変更をしていないユーザを対象とします。対象ユーザに次回ログイン時にパスワードの変更が必要を設定します。
動作確認環境
- Windows 2003 DC 上
- PowerShell 1.0
1. サンプル
パスワードを最後に変更した日時 < 2009/06/30 00:00:00 となる、特定のOU(組織)配下のユーザを検索し、次回パスワード変更が必要をセットします。ただし、パスワードが無期限の場合は、次回パスワード変更が必要をセットしないようにしています。
下記サンプルをps1ファイルに保存して、PowerShellから実行する場合は、ExecutionPolicy を RemoteSigned にする必要があります。現在の実行ポリシーはGet-ExecutionPolicy で確認できます。
サンプルで設定しているように、PageSizeと、SizeLimit を指定しないと、最大1000件までしかフィルタ条件に該当するユーザが検索されないので、注意してください。
#パスワードを最後に変更した日時 < 2009/06/30 00:00:00 のユーザを列挙します。 #ファイルとして実行する場合は、実行前にSet-ExecutionPolicy RemoteSignedが必要です # パスワードは無期限 $ADS_UF_DONT_EXPIRE_PASSWD = 0x10000 #基準日 $date = [datetime] "2009/06/30" $ou = [ADSI] "LDAP://crm1.local/OU=TestUsers,DC=crm1,DC=local" $ds = New-Object System.DirectoryServices.DirectorySearcher -argumentList $ou $ds.Filter = [string]::Format("(&(objectClass=user)(pwdLastSet<={0}))", $date.ToFileTime()) $ds.PropertiesToLoad.Add("sAMAccountName") $ds.PropertiesToLoad.Add("pwdLastSet") $ds.PropertiesToLoad.Add("userAccountControl") # 最大5000件 $ds.SizeLimit = 5000 $ds.PageSize = 1000 foreach($find in $ds.FindAll()){ $accountname = $find.Properties["samaccountname"][0] $msg = [string]::Format("{0}を次回パスワード変更が必要にセット", $accountname ) Write-Output $msg $tick = $find.Properties["pwdlastset"][0] $uac = $find.Properties["useraccountcontrol"][0] if($uac -band $ADS_UF_DONT_EXPIRE_PASSWD){ write-output "無期限に設定されています。次回パスワード変更は設定しません。" continue } if($tick -gt 0){ $pwdLastSet = [System.DateTime]::FromFileTime($tick) $msg = [string]::Format("パスワード設定日時{0}", $pwdLastSet) write-output $msg write-output "パスワードが基準日以降に変更されていません" write-output "次回ログイン時にパスワード変更必要を設定します。" $de = $find.GetDirectoryEntry() $de.pwdLastSet = 0 #実際にパスワード変更が必要な場合に下記コメントを解除 #$de.SetInfo() }else{ write-output "パスワードがすでに次回ログイン時にパスワード変更が必要に設定されています" } }
最大5000件の検索条件に該当するユーザを検索し、次回パスワードの変更が必要にセットしています。実際にDirectoryEntryのプロパティへの変更を確定するには、コメントアウトされている#$de.SetInfo()のコメントを解除してください。
サンプルから、いくつかPowerShell で使用するときの注意点がわかります。
項目 | 説明 |
論理演算子 | -eq, -gt , -lt 等を使用する |
bit 演算子 | -band 等を使用する |
[adsi],[string]などの標準変換が用意されていないインスタンスの作成 | New-Object を使用する |
スタティック(静的)なメソッド、プロパティへのアクセス | [string]::Fomrmat など、[]でクラス、static なメソッドを::で接続して呼び出します。 |
別の記事でより詳細な演算子の説明、便利なコマンドレットの説明などを行いたいと思います。
2. Active Directory ユーザとコンピュータを使用する場合
スナップインを使用して、同じようのLDAPの検索クエリを設定して条件に該当するユーザを検索できます。その方法を紹介します。
管理ツールメニューから、Active Directory ユーザとコンピュータスナップインを起動します。
メニューの表示→フィルタ オプションを表示します。フィルタオプション画面でカスタムフィルタの作成を選択肢、カスタマイズボタンをクリックします。
カスタムの検索条件ダイアログで詳細設定タブをクリックし、下図のようにLDAP検索クエリをセットします。pwdLastSet の比較で指定している値は2008年6月1日 11時11分11秒のファイル時間です。
ファイル時間の求め方は、PowerShell を起動し、次のようにファイルタイムを取得したい日時を$date に設定して、$date.ToFileTime()を呼び出して取得できます。
PS C:\Documents and Settings\user> $date = [datetime] "2008/6/1 11:11:11"
PS C:\Documents and Settings\user> $date.ToFileTime()
128567598710000000
3. まとめ
今回の説明は以上です。不慣れなPowerShell でがんばって作ったのですが、Active Directory ユーザとコンピュータスナップインのフィルタを使用すれば、さらに簡単に検索を実現できることを教えてもらったので、その方法も同時に掲載しました。
間違い、指摘点などありましたらご連絡ください。