昔、「おしいれのぼうけん」ていう絵本がありました。いまでもトラウマです...ねずみばぁさん...。
そんなノスタルジックな想いはともかく、現実に戻って OpenLDAP にパスワードを同期する方法について考察します。
以前、以下の記事で、生パスワードを PowerShell を使用して SHA1 で暗号化する方法を書きました。
【IDM】Active Directory から OpenLDAP への パスワードの同期 その1 ~ パスワードを SHA1 で暗号化
今回は、SHA1 のことはひとまずおいといて、パスワード同期機能で作成された unixUserPassword を取り出し、ADSI を使用して OpenLDAP に同期してみます。
パスワード同期機能および unixUserPassword 属性については、以下で詳しく解説していますので参考にしてください。
# ここでは、パスワードの暗号化形式は DES を使用しています。
解説はソースの中にインラインで書きます。ソースをダウンロードするには、こちらから どうぞ。
今回は、以下の環境を想定しています。
変更の手順の大きな流れは以下の通りです。
では、上記を具体的なスクリプトに落としてみます。
よろしければ、OpenLDAP に接続可能なブラウザを用意しておいてください。「LDAP Browser」で検索していただくと、Windows で使用可能な LDAP ブラウザが見つかるでしょう。これがあると、値が書き込まれているかどうかを手軽に確認することができます。
まずは変数の定義です。これはよいですよね。
On Error Resume NextstrDomain = "dc=example64,dc=jp"strUserName = "testuser01"strPassword = "ABC123@"strLdapServer = "fedora01.example-fedora.jp"strLdapUser = "uid=" & strUserName & ",ou=People,dc=example-fedora,dc=jp"strManagerDN = "cn=Manager,dc=example-fedora,dc=jp"strManagerPassword = "password"
はじめに、testuser01 のパスワードを Active Directory 上で変更します。これは、unixUserPassword にUNIXシステム用に暗号化されたパスワードを格納するためです。既に最新のパスワードが unixUserPassword に格納されているのであれば必要はありません。
testuser01 のパスワード変更にあたり、まずは Active Directory で testuser01 を検索し、DistinguishedName を取得します。
' ユーザーを検索Set objConnection = CreateObject("ADODB.Connection")objConnection.Open "Provider=ADsDSOObject;"Set objCommand = CreateObject("ADODB.Command")objCommand.ActiveConnection = objConnectionobjCommand.CommandText = _ "<LDAP://" & strDomain & ">;" & _ "(&(objectCategory=person)(objectClass=user)" & _ "(sAMAccountName=" & strUserName & "));" & _ "DistinguishedName,sAMAccountName,unixUserPassword;" & _ "subtree"Set objRecordSet = objCommand.Execute
次に、testuser01 のパスワードを変更します。パスワードの変更を ADSI で行うには、SetPassword メソッドを使用します。パスワード変更の場合、SetInfo は必要ないのですが、属性のリフレッシュのために念のために入れてあります...すいません、これは私の癖みたいなものです...。
' ユーザーのパスワード変更Do Until objRecordset.EOF strDN = objRecordset.Fields("DistinguishedName") objRecordset.movenextLoopSet objUser = GetObject("LDAP://" & strDN)objUser.SetPassword strPasswordobjUser.SetInfo
パスワードの変更後、パスワード同期機能による unixUserPassword の生成には若干のタイムラグがあります。以下では、念のために 3000ms の待ちを入れています。
' AD内でunixUserPassword が同期されるまで待つWscript.Sleep 3000
unixUserPassword が生成されたことを想定し、以前にも解説した方法で DES で暗号化されたパスワードを取得します。なお、unixUserPassword を取得するに当たり、冒頭で事前に ADSI に対してクエリーを再実行しています。
なお、取得したパスワードは、strUnixUserPassword に格納されます。
' 変更後のパスワードを取得' クエリーを再実行Set objRecordSet2 = objCommand.Execute
Do Until objRecordset2.EOF arrUNIXUSERPASSWORD = objRecordset2.Fields("unixUserPassword") For i = 1 To LenB(arrUNIXUSERPASSWORD(0)) strA = MidB(arrUNIXUSERPASSWORD(0), i, 1) strB = AscB(strA) strUnixUserPassword = strUnixUserPassword & Chr(strB) Next objRecordset2.movenextLoop
さて、ここからが OpenLDAP に対する操作の始まりです。
はじめに、OpenLDAP 上の testuser01 に接続し、objUser オブジェクトを生成します。このとき使用するのが、OpenDSObject というメソッドです。引数に指定するのは、以下の通りです。
OpenDSObject は、LDAPサーバーへの認証でも使用するメソッドです。覚えておくと、ユーザーIDとパスワードの整合性をチェックするときにも使えて便利です。このメソッドは、変更後のパスワードが正しく同期されているかどうかをチェックする際にも使用します。
' OpenLDAPに接続してユーザーオブジェクトを取得set objLDAP = GetObject("LDAP:")set objUser = objLDAP.OpenDSObject("LDAP://" & strLdapServer & "/" & strLdapUser, _ strManagerDN, _ strManagerPassword, _ 0)
OpenLDAP 上のユーザーのパスワードを変更する際は、Active Directory のときのように SetPassword を使用しません。通常の属性変更用のメソッドである、Put を使用して、userPassword 属性に直接暗号化されたパスワードを格納します。
パスワードの格納にあたり、頭に {CRYPT} を付加します。これは、OpenLDAP 上の userPassword 属性が DES で暗号化されていることを示しています。この部分は、環境に合わせて {MD5} や {SHA} 等に変更します。
パスワードの変更後は、Active Directory 同様、SetInfo でコミットしてください。
'パスワードを変更objUser.Put "userPassword", "{CRYPT}" & strUnixUserPasswordobjUser.SetInfo
最後に、本当にパスワードが同期されたかどうかを、OpenDSObject を使用して確認します。ただし、これができるのは、生パスワードがわかっているときだけです。単純に、unixUserPassword の中身を userPassword に同期する場合には、生パスワードがわかりませんから、このチェックは行いようがありません。
'パスワードが変更されたかどうかをチェックset objChkUser = objLDAP.OpenDSObject("LDAP://" & strLdapServer, _ strLdapUser, _ strPassword, _ 0)
If Err.Number = 0 then Wscript.Echo "パスワードは正しく同期されました(" & strLdapUser & ")"else Wscript.Echo "パスワードの同期でエラーが発生しました(" & strLdapUser & ")"End If
以上で完了です。
意外に簡単なスクリプトで実現できることに驚きませんか?
小規模なシステムや負荷が小さなシステムでは十分使える方法だと思いますので、是非試してみてください。
PingBack from http://blogs.technet.com/junichia/pages/adsi-openldap.aspx
※2008/08/29 Tech・Ed会場にてリンク切れを指摘していただきましたので修正いたしました。(汗) ある調べごとがあり、「'watch node'」 という単語を 某検索エンジンに放り込んだところ、以下の表示が。