同僚の安納さんのブログで、Active Directory と Unix/Linux のパスワードの同期機能について、Windows Server 2008 での方法が詳しく書かれています。
私も大変興味のある分野ですので、さっそく試してみました。ブログに書かれている通りに進めていくと、簡単にセットアップできました。ID の統合を検討されている方は、この同期の手法は、 Linux/Unix のログイン認証を AD に統合するよりも、わかりやすくシンプルなので、まずはここから始めてみるのもいいかもしれませんね。
ところで、その3では Linux/Unix に同期される、暗号化されたパスワード文字列を、LDAP クエリーで取り出す方法が紹介されていますが、ここでは PowerShell 版を作ってみたいと思います。以下のようなパスワード文字列を取り出します。
まずは、Active Directory に LDAP で接続し、クエリの準備をします。
$domain = [adsi]"" $searcher = New-Object System.DirectoryServices.DirectorySearcher $domain $searcher.Filter = '(&(objectClass=User)(sAMAccountName=testuser001))'
カレントの ADSI オブジェクトを取得し ($domain)、検索のための DirectorySearcher オブジェクト を作成します ($searcher)。$searcher にフィルタを設定します。LDAP サーバーや、バインドするオブジェクトを指定する場合は、パスを指定してください。
$domain = [adsi]"LDAP://localhost/dc=example1,dc=jp"
$domain の中を見てみると、ディレクトリに関する情報が入っています。(以下、確認のための操作には、プロンプト PS C:\> を付けています。)
PS C:\> $domain | format-list * objectClass : {top, domain, domainDNS} distinguishedName : {DC=example1,DC=jp} instanceType : {5} ...(略)...
次に LDAP クエリを実行し、ユーザーオブジェクトを取得します。
$user = $searcher.FindOne()
$user の Properties プロパティに属性が入っていますので unixUserPassword の値を確認してみましょう。(DirectorySearcher の PropertiesToLoad プロパティに指定がない場合は、すべての属性が Properties に返されます。) unixUserPassword は複数値ですので、最初の値を取り出すため [0] を指定します。
PS C:\> $user.Properties.unixuserpassword[0] 71 121 49 110 65 77 90 105 65 88 84 102 89 PS C:\> $user.Properties.unixuserpassword[0] | Get-Member TypeName: System.Byte[] ...(略)...
バイト列になっていますので、これを文字列に変換します。変換には、.NET Framework の System.Text のクラスが便利です。
$enc = new-object System.Text.UTF8Encoding $password = $enc.GetString($user.Properties.unixuserpassword[0])
このようにしてパスワード文字列を取り出すことができます。
PS C:\> $password Gy1nAMZiAXTfY
当初の予定を変更し、パスワードの暗号化について、ちょっとだけ触れておきたいと思います 以下では、Active Directory に格納された DES / MD5 形式のパスワードをそのままとりだしました。取り出したまま