System.DirectoryServices.ProtocolsでActive Directoryへアクセス

 
2010年2月27日に
Tech Fielders の集い 特別編 『おかげさまで Active Directory 10周年』
というイベントが開催されるようですね。
 
私も参加させていただく予定でいるのですが、 
様々な参加者の方にお会いできることを今から楽しみにしています。
募集のサイトには、受講対象者に
”日頃 Active Directory にかかわっている ITエンジニアの方々で、ブログや社内勉強会、コミュニティなどでの情報発信をしている方”
とあり、そういえば最近ADネタを投稿していなかったなあ、と思いました。
 
そんなわけで、今回はSystem.DirectoryServices.Protocolsを使って、
Active Directoryへアクセスする方法を試してみた、という話をしたいと思います。
 
 
Windows 2000の頃から、Active Directoryの処理を自動化させようと思ったら、
ADSIを使うのが定石でしたね。
WSHで、 
Set objRootDSE = GetObject("LDAP://RootDSE")
Set objDom = GetObject(LDAP://ou=Lab, & objRootDSE.GET("DefaultNamingContext"))
 などのような操作を行いながら作ったものです。
 
しかし、最近ではActive Directoryにアクセスするための方法が多様化されていて
なかでも、.NETの名前空間であるSystem.DirectoryServices.Protocols名前空間は特筆すべきものがあります。
 
 
上の図はWindows Server 2008 R2のActive Directory アーキテクチャー図です。 
従来(Windows Server 2008まで)はADSI経由のアクセスになっていましたが、
Windows Server 2008 R2からは、ADSIを経由しないアクセスをサポートしています。
そのひとつに、System.DirectoryServices.Protocols名前空間(以下、S.DS.P)によるアクセス(図の赤字S.DS.P部分)があります。
この方法では、
 
・ネイティブなLDAPを使うので、Active Directory以外のディレクトリサービスにも流用できる
・ADSIへの命令の変換処理が必要ないためパフォーマンスがよい
 
という特徴があるようです。
S.DS.Pの名前空間で定義されているクラス等については、MSDNのサイトに掲載されています。
 
私らしい確認方法で試してみよう、ということでPowerShellで試してみました。
 
まず、S.DS.P名前空間を利用するためにはアセンブリのロード処理を行います。
次に、S.DS.P名前空間を使ったオブジェクトの作成を行います。
何をする場合でも、この2つの処理がS.DS.Pを使う上で、必須の処理となります。 
この2つの処理を行っているのが、下のコマンドです。
(赤字で書いてあるところはドメイン名ですから、環境に合わせて変えてください)
 


PS C:> [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")PS C:> New-Object System.DirectoryServices.Protocols.LdapConnection("example.com")

 
この2行が実行できたら、後は自分のやりたいことを書くだけです。
試しに、ユーザーの作成を行ってみました。 
 


PS C:> [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")PS C:> $dom=New-Object System.DirectoryServices.Protocols.LdapConnection("example.com")
PS C:> $user=New-Object System.DirectoryServices.Protocols.AddRequest("cn=kunii,ou=Lab,dc=example,dc=com", "user")
PS C:> $dom.SendRequest($user)

 

この手順だと本当にユーザーアカウントしか作らないので、userPrincipalNameやsAMAccountNameなどの属性は
別途、New-Object System.DirectoryServices.Protocols.ModifyRequest~と記述して設定します。
このあたりの設定方法は、他のサイトで紹介されているのを見かけたので、そちらに話は譲ることにして、
私のところでは、”ADSIへの命令の変換処理が必要ないためパフォーマンスがよい”というのを確認しようとしました。
なぜなら、S.DS.Pは.NET Frameworkで既にサポートされている機能であり(Windows Server 2008 R2の新機能ではない!)、
Windows Server 2008 R2とその他のOSで動きが違うものなのか?ということを確かめたかったからです。
ところが、SysinternalsのADInsightで内部的な処理を見てみようとすると、ADInsightが動かない!
という問題に遭遇してしまいました。
Sysinternals Forumでも話題になっているのですが、
これと言った解決策がないようですね。 
きちんと動いてくれれば、世界が変わるような気がするのに..(言い過ぎ?)