[ADSI] LDAP プロバイダで PasswordExpirationDate 属性を使ったら 0x800500D
みなさんこんばんは。ういこです。
今月は色々あったので、たまっていたネタをここ二日ほどで激しく放出しております。通常の 3 倍放出されております。でも、相変わらずの View の少なさによっぽど私たち不人気なんだなーと思ってちょっと落ち込んでます。もう、なんか要件だけ書く形式にしちゃおうかな…と思い、最近「つぶやき」はオミット気味です。
そうそう、ILM 一家ですが、不人気なのでユニット解散の危機かもしれないです。来期 (7 月から) 一家解散になっちゃったりして。もう、マヤの大予言とか、カバラの大予言とか、MMR とか、普通に会話できる最高のチームなのにもったいないなあはははは。
というわけで今日のお題です。
【今日のお題】
ドメインのポリシーで 30 日間で設定しているパスワードポリシーを取得するアプリケーションを作成している。LDAP プロバイダを用いて、IADsUser プロパティの PasswordExpirationDate 属性を確認する実装を入れてみた。実行時に 「例外 0x800500D」が発生する。対処方法を知りたい。
★LDAP プロバイダ ⇒ うまくいかないんですよこれが
' *** Sample (Not good) ***
objUser = GetObject("LDAP://CN=Uiko Yokoi,OU=UserAccounts,DC=jpdsilm, DC=contoso,DC=com")
objUser.Getinfo()
Wscript.Echo(objUser.Get("PasswordExpirationDate"))
Wscript.Echo(objUser.PasswordExpirationDate)
' *** Sample (Not good) ***
★WinNT プロバイダ ⇒ うまくいっちゃうんですよこれが
' *** Sample (Good) ***
objUser = GetObject("WinNT://jpdsilm/uikou, user")
Wscript.Echo(objUser.PasswordExpirationDate)
' *** Sample (Good) ***
【回答】
IADsUser プロパティの PasswordExpirationDate 属性を用いて失効情報を取ろうと思った場合、この属性は実際には ADSI 内部で有効期限と最終変更日時から計算して値を返しています。この属性は WinNT プロバイダの場合のみサポートされますが、LDAP プロバイダを利用する際にはサポートされませんため、例外が発生します。この動作は想定されたものとなります。
AD における パスワードの失効日の取得について
Active Directory では、パスワードが失効しているかどうかのステータスや、また失効日そのものの属性はアカウントの情報には反映されません。アカウントに含まれる情報としては最終変更日時のみなのです。
また実は、ユーザー アカウントのパスワードが失効しているかどうかについてを表す属性はないため、対処方法は有効期限と最終変更日時から計算してパスワードの有効期限を取得いただき、処理時点の日付・時刻と比較し、処理時点の時間のほうが有効期限よりも先の場合失効していると判断するという方法を行う必要があります。
時間の判断処理を実装した上で、パスワードの有効期限取得処理を PasswordExpirationDate ではなく有効期限と最終変更日時を操作するように変更してみてください。
IADsUser プロパティの PasswordExpirationDate 属性のプロバイダ サポートについて
このドキュメントに図が載っています。LDAP プロバイダの場合、思いっきり PasswordExpirationDate 属性は Unsupported と書いてあります。一方、WinNT プロバイダの場合、PasswordLastChanged が Unsupported とあります。
よって、パスワードの失効期限へのアプローチ方法は、ご利用いただいているプロバイダによってそれぞれ対応を変えなくてはいけないということなのです。ちょっと面倒ですね。
Provider Support of ADSI Interfaces
https://msdn.microsoft.com/en-us/library/aa746445(VS.85).aspx
Provider Support for IADsUser |
||
Property |
LDAP |
WinNT |
Unsupported |
Supported | |
|
Supported |
Unsupported |
このように LDAP プロバイダの場合 PasswordExpirationDate属性は使用できないため、有効期限と最終変更日時から計算して取得する実装を作成しなくてはいけないのです。
まとめますと下記のような形になります。
LDAP プロバイダ
PasswordExpirationDate 属性は使用できないので、PasswordLastChanged 属性を取得し、有効期限から計算して取得する必要がある。
<まとめ>
PasswordExpirationDate × 取得不可
PasswordLastChanged ○ 取得可能
WinNT プロバイダ
PasswordExpirationDate 属性は使用可能なのでこの属性をもって失効期限を取得する。 ただし PasswordLastChanged 属性は取得できない。
<まとめ>
PasswordExpirationDate ○ 取得可能
PasswordLastChanged × 取得不可
具体的なコード例
下記サポート技術情報にバッチリございますのでご参照くださいませ。
LDAP ADSI プロバイダを使用してパスワードの有効期限を入手する方法
https://support.microsoft.com/kb/323750/ja
VBScript をご利用いただく際には下記をご参照いただくと比較的用意に対処できるかと思います。
パスワード失効日の取得
****https://www.microsoft.com/japan/technet/scriptcenter/scripts/ad/users/pwds/uspwvb08.mspx
参考 : パスワードの有効期限について
下記サポート技術情報が簡潔で明解でわかりやすいです。
パスワードの有効期間の実装のしくみ
https://support.microsoft.com/kb/236373
PasswordExpirationDate の取得方法
PasswordExpirationDate は WinNT プロバイダでのみ動作しますが、たとえば NetBIOS 名の解決が見込めないネットワーク越しの操作などの必要がない場合はこちらをご利用いただき簡単に取得いただくことも可能です。以下は Visual Basic (.NET 以降の managed ) の例となります。
' *** コードここから
DirectoryEntry entry = new DirectoryEntry("WinNT://mydomain/testuser, user");
IADsUser userdata = (IADsUser)entry.NativeObject;
userdata.GetInfo();
DateTime endtime = userdata.PasswordExpirationDate;
' *** コードここまで
あしたは暴風雨だそうです。(4/25) 病院行く予定ですが、行くの怖い…です。
それでは今日はもう眠くて死んじゃうのでお先に寝かせていただきます。週次バッチの管理者様、本当に申し訳ありません。もう限界です。おやすみなさいませ…。
~ ういこう@でっかいねむねむさんに眠り殺されそう ~