Open棟梁Project - マイクロソフト系技術情報 Wiki
Lightweight Directory Access Protocol(以下、LDAPと略す)は、X.500に基づいたディレクトリ サービス上のデータを参照・操作(追加・更新・削除)するためのプロトコルであるが、LDAPを使用するには、ディレクトリ サービス、LDAPの構文の知識が必要になる。そこで本ページでは、LDAPを使用して、ディレクトリ サーバへアクセスするプログラムを作成する上で最低限必要となるディレクトリ サービス、LDAP、LDAPの構文について説明した上で、.NET Frameworkから利用可能なAPIライブラリであるADSI(Active Directory Services Interfaces) を使用し、LDAPを使用して、ディレクトリ・サーバへアクセスするプログラムについて説明する。
LDAPとはRFC2251~2256で定義されている、X.500に基づいたディレクトリ サービスを利用するために定められたクライアント・サーバ型のプロトコルであり、インターネットやイントラネットなどのTCP/IPネットワーク上で利用することができる。X.500ディレクトリ サービスで定義されるDAP(Directory Access Protocol)は複雑であったため、現在、DAPをベースにして軽量化したLDAPがディレクトリ サービス プロトコルの標準となっている。
RFC2251~2256については、以下のURLを参照のこと。
LDAPを実装した、ディレクトリ サービス(LDAPサーバ)は、『DIB(Directory Information Base)』と呼ばれるデータベースを保有している。LDAPクライアントは、LDAPプロトコルを使用してLDAPサーバに接続~質問をする。この質問に対してサーバは回答を返すか、クライアントがさらに情報を探し出せる場所へのポインタを返す。
LDAPクライアント・サーバシステムの機能を簡単に説明する。
元々LDAPはAPI定義も含めた標準仕様であるため、環境を用意しやすく、さまざまなAPIライブラリが存在している。これらのAPIを利用すれば、LDAPのプロトコルレベルの仕様を知らなくとも簡単に情報の検索や変更処理が実装できる。以下は、その中の主なAPIである。
「ディレクトリ」という単語には「人名簿」・「住所録」という意味がある。つまりディレクトリ サービスとは、「人名簿」・「住所録」などを基に案内をしてくれるサービスのことである。コンピュータ ネットワークにおけるディレクトリ サービスとは、ネットワーク上に存在するさまざまな資源(リソース)や情報をまとめ、管理・検索するためのサービスのことを指す。ネットワーク サービスの多様化にともない、最適なネットワーク サービスの選択を支援するメカニズム、通信相手を容易に指定するためのメカニズムが求められるようになった。そこで、通信相手に関する情報をデータベースに格納し、必要なときに検索できるようにする通信支援サービスがディレクトリ サービスである。
ディレクトリ サービスは、CCITT(International Telegraph and Telephone Consultative Committee:国際電信電話諮問委員会、現在のITU-T)とISO(International Organization for Standardization:国際標準化機構)によりX.500シリーズとして標準化されている。
※ ただし、X.500の構造が非常に複雑で扱い難いため、完全に準拠しているディレクトリ サービスはほとんど無い。そのため、多くのディレクトリ サービスは、X.500を簡素化したものを採用している。例えば、現在、IP電話が実用化されつつあり、このとき、最適なITG(インターネットと電話網のゲートウエイ)を見つめるために、DAPなどを使用してディレクトリ サービスにアクセスする。その他、DNSサービスもディレクトリ サービスの一種といえる(次節参照)。
ディレクトリ サービスの提供方法には色々な種類がある。ローカルに限ってサービスを提供する場合もあるが、大域的にサービスを提供する場合もある。X.500準拠のディレクトリ サービスは、大域的にサービスを提供するための分散型ディレクトリの機能を実装している。クライアントからは、どのディレクトリ・サーバに接続してもディレクトリは同じように見える。あるディレクトリ・サーバに提示した名前は別のディレクトリ・サーバでも同じエントリを参照する。これは、大域的ディレクトリ サービスの重要な特性である。大域的なサービスを提供する場合には、大抵、X.500の分散型ディレクトリの機能が用いられる。分散型ディレクトリの機能には、稼働率と信頼性を向上、かつレスポンスタイムを減らすために、情報を広く複製し、一時的な不整合が発生しないように、定期的に同期をとる機能などがある。通信支援サービスやDNSサービスが分散型のディレクトリ サービスとして有名である。また、LDAPサーバの中にも、大域的ディレクトリ サービスの機能を実装したものがある。
LDAPを実装した、ディレクトリ サービス(LDAPサーバ)は、ネットワーク環境でネーム サービスを提供するために開発されたDNS、NISなどとは異なり、多様な情報(ネットワークを利用するユーザ名やマシン名、メールアドレスや環境に関する情報)を扱う汎用的な情報検索を目的としている。最近では、単純なユーザ管理だけでなく、プリンタなどの、ネットワーク上の共有資源の管理に応用する動きも活発になっている。このように、LDAPサーバでは、何を検索するのか?どういうことが可能になるのか?ということが厳密に決まっていない。LDAPサーバはいくつかのベンダから提供されているが、何を検索できるかは製品ごとに異なる。しかし「登録した情報を検索する」という基本機能は変わらない。
LDAPサーバ ソフトウェアには、以下のものがある。
ディレクトリ サービス(LDAPサーバ)は主に、検索・認証システムなどに使用される。格納されるデータは、ユーザ情報、コンピュータリソースなどが格納される。データ構造は木構造(階層型データベース構造)で、大量の照会あるいは検索操作に即応できるように最適化されている。
ディレクトリ サービス(LDAPサーバ)と、LDAPの関係は、RDBMSとSQLの関係に似ている。
しかし、ディレクトリ サービスとRDBMSでは、以下の点が異なる。
項番 | 項目 | ディレクトリ サービス(LDAPサーバ) | RDBMS |
1 | 使用システム | 検索・認証システム | 業務システム(例:流通・会計システム) |
2 | 用途 | 格納データの検索 | 格納データの参照・更新 |
3 | データ形式 | 木構造 | テーブル(表) |
4 | 格納データ | ユーザ情報、コンピュータリソース | 業務データ(例:商品情報、顧客情報) |
5 | スキーマ定義 | 標準が存在(スキーマ、プロトコル、API) | スキーマはユーザが決定 |
6 | トランザクション | 単純な書き換え | ACID機能を実装 |
ディレクトリ サービス(LDAPサーバ)では、オブジェクトは『属性』から構成されている。オブジェクトは『DIT(Directory Information Tree)』形式の、木構造のデータのノードに配置され、『DIB(Directory Information Base)』と呼ばれるデータベースに保存される。また、このオブジェクト(『DIT』のノード)は『エントリ』と呼ばれている。
以下に、LDAPサーバの『DIT』の例を示す。
『DIT』のデータ構造に関する詳細は、本ページ:「ディレクトリ・サービスの基本事項」で詳しく説明する。
Active Directory は、Windows 2000 Server、Windows Server 2003に搭載されているディレクトリ サービス(LDAPサーバ)である。Active Directory では、ネットワーク上に存在するクライアント・サーバコンピュータ、共有フォルダ・プリンタなどの共有資源情報や、それらを使用するユーザのユーザアカウント、グループ、アクセス権、組織単位(OU)の情報などの情報を中央で集中制御できるようになり、管理者の負担が軽減される。
Windows NTドメインでは、クライアント・サーバコンピュータ、ユーザ アカウント、グループ、アクセス権などの情報しか格納できかなった。しかし、Active Directory では情報スキーマを定義し情報を格納することで、ドメインや共有資源情報に階層構造を設けて管理することができるようになった。また、データオブジェクトの格納件数や、検索機能の強化、LDAPへの対応など、ディレクトリ サービスとして十分な機能を持つようになった。
Active Directoryでは、インターネットの標準技術を採用しており、インターネットとの相互運用性を強化している。具体的には、以下の標準技術を採用している。
Active Directoryの採用するインターネットの標準技術
項番 | 機能 | 技術名 |
1 | 名前解決 | DNS |
2 | データベース | ディレクトリ サービス(X.500規格) |
3 | 情報検索 | LDAP |
4 | 認証 | Kerberos |
ディレクトリ サービス(LDAPサーバ)では、オブジェクトは『属性』から構成されている。オブジェクトは、『DIT(Directory Information Tree)』形式の、木(階層型データベース)構造のデータのノードに配置され、『DIB(Directory Information Base)』と呼ばれるデータベースに保存される。また、このオブジェクト(『DIT』のノード)は『エントリ』と呼ばれている。
以下に、LDAPサーバの『DIT』の例を示す。
本章では、LDAPにおける『DIT』形式でデータの
などについて説明する。
LDAPにおける『エントリ』への名前付けの方法について簡単に説明する。『エントリ』にはそれぞれ固有の名前を付けることができる。例えば、下記のような『DIT』の場合、各『エントリ』の名前「A,B,C,D」を、『相対識別名』(RelativeDN:RDN)と呼ぶ。
下記のような『DIT』の場合、同一の『相対識別名』の『エントリ』を名前だけで区別することはできない。こうなると、『相対識別名』だけでは特定の『エントリ』を識別できないので、確実に『エントリ』を特定するための手段として、『識別名』(Distungnished Name:DN)を使用する。
『識別名』は、上位の『エントリ』の『相対識別名』を「,」を使って全て並べて作成する。例えば、図の3つの『A』エントリの『識別名』はそれぞれ次のようになる。
これにより、『DIT』上の『エントリ』を特定することができる。これで『エントリ』を特定できない場合は、エントリを区別するために、親エントリを追加する必要がある。また、兄弟で同じ『相対識別名』にすると『エントリ』を区別できなくなるため兄弟間では同じ『相対識別名』をつけてはいけない。
ディレクトリという単語には「人名簿」・「住所録」という意味がある。実際、ディレクトリ サービスは、「人名簿」・「住所録」などを基に案内をする。通常、「人名簿」・「住所録」といえば、50音順で構成されている「個人情報」の一覧表を持っている。各個人情報は「あ行」・「か行」のような行毎に分類され、各「個人情報」が『エントリ』になる。
LDAPに於ける『DIT』では、50音順の一覧ではなく、木構造によって「個人情報」を分類する。
LDAPに於ける『DIT』上の『エントリ』の各項目を『属性』と呼ぶ。木構造では、共通の『属性』が親の『エントリ』に抜き出される特徴があり、各『エントリ』に登録する情報を集約すると、階層構造をとれなくなる点に注意する。例えば、上記のエントリに、「姓情報」という属性を追加すると、親のエントリに「姓情報」を抜き出した、階層構造が取れなくなる。
『エントリ』を構成する『属性』は『属性型』(属性の種類)と『属性値』(属性の内容)から構成される。また、『属性』は、次のように記述する。
例えば、『属性』「生年月日」は、
から構成され、以下のように記述する。
『エントリ』の『相対識別名』を表の外に書いた場合、『相対識別名』を保持するための概念が、『エントリ』の『属性』の他に新たに必要となってしまう。このため、LDAPでは『相対識別名』を1つの『属性』として管理している。この『相対識別名』を『属性値』として持つ『属性』を、『名前付け属性』という。
『相対識別名』から『識別名』を生成する場合、『属性型』の「:」と『属性値』の「:」を区別するため、『相対識別名』は、次のように記述する。
例えば、「太郎」の『識別名』を『属性』の表記方法で記述すると次のようになる。
これに、『識別名』という『属性』を明記すると以下のようになる。
この表記では、『属性型』の「:」と、『属性値』の「:」を区別し難い。
このため、『識別名』の『属性値』の要素である『相対識別名』を規定の記述方法で記述する。
これにより、『識別名』の『属性値』の要素である『相対識別名』の『属性型』が解かり易くなる。
『エントリ』の中に自由に情報を書き込めれば、融通がきく側面もあるが、あまり自由に使用されると、脈絡のない見づらい情報になる。このため、『エントリ』が保持できる『属性型』の一覧を保持する『属性』を『エントリ』内に埋め込む。これによって各『エントリ』が保持する『属性型』を定義できる。なお、LDAPでは、『エントリ』が保持できる『属性型』の一覧を保持する『属性』の『属性型』『objectClass』という。
先に示した、個人情報『エントリ』の例では、『属性』として、 『属性型』=「objectClass」、『属性値』=「個人情報」を埋め込む。
同様に、姓情報『エントリ』の例では、『属性』として、 『属性型』=「objectClass」、『属性値』=「姓情報」を埋め込む。
このように、『objectClass』という『エントリ』が保持できる『属性型』の一覧を保持する『属性』を追加することで、各『エントリ』が保持する『属性』を定義できる。標準的に使用される『属性型』と、それに対応する『objectClass』は既に用意されており、これについては、本ページ:「LDAPで利用される属性型」の「標準の属性型」で説明する。
『objectClass』は、その『エントリ』に格納する『属性型』を規定するものである。例えば、「個人情報」という『objectClass』の場合、個人の「名前」・「生年月日」などの『属性』を格納する。
objectClass: 個人情報 ─ ┬ ─ 『必須(MUST)属性』 ─ → 「名前」・「生年月日」 └ ─ 『補足(MAY)属性』 ─ → 「電話番号」・「備考欄」
存在しなかった『属性』が後から必要になる場合がある。そういう状況に柔軟に対応できるように、LDAPでは、1つの『エントリ』が複数の『objectClass』を保持できるようにしている。このため、「個人情報」という『objectClass』を保持する『エントリ』に、別の『objectClass』を追加できる。例えば、「電子メールアドレス情報」という『objectClass』を『エントリ』に追加できる。
『objectClass』には2つの種類がある。ひとつはエントリの大枠を決めるもの、もうひとつはそのエントリに存在する捕捉情報を決めるものである。
それぞれ、
と呼ぶ。
なお、『structual objectClass』は、エントリの中に必ず存在しなければいけない。また、ふたつ以上あってもいけない。逆に『auxiliary objectClass』は、エントリ中に何個指定しても良い。
上記の例では、
である。
LDAP では、各『エントリ』の『名前付け属性』として、「c」、「o」、「ou」など、標準的な『名前付け属性』を使用する。これらは「c」で国を、「o」で組織/会社を、「ou」で組織単位を、「cn」で固有の名称(氏名など)を示す。この標準的な『名前付け属性』を使用することで、世の中のすべての存在が1つのツリー内で定義することができる。これは、「組織ツリー」と呼ばれている(これには、世界に存在するディレクトリのルートのエントリが1つである必要がある)。
代表的な『名前付け属性』と、対応する『objectClass』を以下に示す。
項番 | 名前付け属性 その他の属性 | オブジェクトクラス | 説明 |
1 | objectClass | top(共通) | そのクラス自身および全ての親クラス |
2 | c (countryName) | country(国) | 国の名前 |
description | 国の説明 | ||
3 | o (organizationName) | organization(組織) | 組織の名前 |
l (localityName) | 都市、地域 | ||
4 | ou (organizationUnitName?) | organizationUnit(組織単位) | 部署などの名前 |
l (localityName) | 都市、地域 |
※ 黄色網掛けは、『名前付け属性』
※ LDAPで使用される『属性型』の文法はRFC2552で、種類はRFC2556で定義されている。
組織ツリー
ただし、ディレクトリ サービス(LDAPサーバ)製品毎に『属性』・『名前付け属性』に違いがある。例えば、LDAP とActive Directory の『名前付け属性』の対応は、以下のようになっている。
LDAPとActive Directoryの『名前付け属性』の対応
項番 | 名前付け属性 | |
LDAP | Active Directory | |
1 | c(国) | (サポートされていない) |
2 | o(組織) | dc(ドメイン構成要素) |
3 | ou(組織単位) | ou(組織単位) |
4 | cn(一般名) | cn(一般名) |
Active Directoryの『名前付け属性』を見る限り、「c」(国)、「o」(組織/会社)ではなく、「dc」(ドメイン構成要素)で世の中のすべての存在を1つのツリー内で定義しようとしている。
「dc」(ドメイン構成要素)という『属性型』はRFC2552でも定義されていない(Active Directoryのマニュアルでは、拡張仕様と表現されている)。このように『属性型』は製品毎にある程度変更されている。特に「dc」(ドメイン構成要素)を使用した組織ツリーは、別のディレクトリ サービス(LDAPサーバ)製品でも使われており、これは「ドメイン構成要素ツリー」と呼ばれている。
Active Directoryの『名前付け属性』と、対応する『objectClass』を以下に示す。
項番 | 名前付け属性 | objectClass |
1 | dc(ドメイン構成要素) | domainDns |
2 | ou(組織単位) | organizationalUnit |
3 | cn(一般名) | user |
ドメイン構成要素ツリー
『LDIF (LDAPデータ交換フォーマット)』は、
LDAPの『エントリ』を簡単なテキスト形式で表現するために利用される。
LDAPツール(LDAPのAPIライブラリ)は、入出力に『LDIF』を使用する。
『LDIF』による『エントリ』の基本的なテキスト形式については下記URLのページが参考になる。
LDAPは、クライアントからの要求にサーバが応答する、クライアント・サーバ型のプロトコルである。
LDAPシステムは、以下の流れでディレクトリ内を検索する。
<LDAPの検索オペレーション> ・LDAPクライアントが、検索条件を指定し、検索要求を送信する。 ・要求を受けたLDAPサーバは、その内容に対応する『エントリ』を探索する。 ・『エントリ』が見つかったら、さらに指定された『属性』を探索する。 ・問い合わせのあった『属性』をクライアントに返却する。
以上が、LDAPで『エントリ』を検索する実際の流れとなる。
上記の一連の流れを『オペレーション』という。『オペレーション』には、その内容に応じて複数のパターンが用意されている。例えば、前述の『オペレーション』は『検索オペレーション』という。LDAPには、『検索オペレーション』以外に、代表的なものとして『エントリ』の『追加、変更、削除を行う各オペレーション』、LDAPサーバを不正に利用させないようにするための『認証オペレーション』がある。LDAPの場合、認証をするための手続きをバインドという。
LDAPには複数の『オペレーション』が存在するが、ディレクトリ サービスにアクセスするためのプロトコルであることを考慮し、検索用に最適化されている。
『検索オペレーション』では、LDAPクライアントが、検索要求を送信する。
検索要求とは、SQLのSELECT文のような、LDAPサーバの理解できる言葉である。
例えば、以下は、電話番号が03から始まる病院の住所を検索する。
検索要求は、主に2つの引き数『フィルタ式』と『取得する属性』を指定する。
filter: (&(telNumber=03*)(businessCategory=病院)) attribute: cn address | ⇒ 『フィルタ式』 ⇒ 『取得する属性』 |
『フィルタ式』とはディレクトリの中から対象とする『エントリ』を識別するための条件のことである。
上記の例でいえば、「03から始まる病院」が『フィルタ式』になる。
取得する『属性』は、条件に一致した『エントリ』のどの『属性値』を取り出すかを指定する。
※ LDAPで使用される『フィルタ式』の書式は、RFC2254に定義されている。
『フィルタ式』の記述方法について詳しく説明する。
filter: (&(telNumber=03*)(businessCategory=病院))
(telNumber=03*)
この条件は、「03で始まる」電話番号の『エントリ』を検索することを意味する。
「telNumber」という『属性型』の『属性値』が「03で始まる」『エントリ』ということになる。
「03*」が「03で始まる」ことを表し、「*」がない場合は「03」そのものを意味する。
(businessCategory=病院)
同様に、この条件も「businessCategory」という『属性型』の『属性値』が「病院」である『エントリ』を検索することを意味する。ここには「*」がないため、「病院」そのものを意味する。
(&
これは、かっこで括られたその後に続くすべての条件がすべて成り立っていなければならないことを表す。例えば以下の『フィルタ』があった場合、
(&(A)(B))
これはAとBの両方の条件にマッチしていなければいけないことを表す。
『フィルタ式』で使える主な演算子を示す。
=:属性が指定した内容を持っている。 >=:属性値が指定した値より大きいか等しい <=:属性値が指定した値より小さいか等しい ~=:属性値が指定した内容に似ている
&:指定した条件がすべて成り立っている |:複数の条件のうち、ひとつが成り立っている !:指定した条件が成り立っていない
前述の『フィルタ式』を用いて特定の『エントリ』を探し出すことができる。
次に、見つかった『エントリ』の情報を取り出す方法について説明する。
必要のない情報まで取り出すと、ネットワークやサーバ、クライアントに余計な負荷をかけてしまう。
そのため、『検索オペレーション』には、『エントリ』を探すための『フィルタ式』に加え、
見つかった『エントリ』のどの『属性』を取得するかを指定できる。
先程のディレクトリから電話番号が「03」で始まる「病院」で見つかった『エントリ』の、
「名前」と「住所」の『属性』を取り出す検索要求は以下のとおりになる。
filter: (&(telNumber=03*)(businessCategory=病院)) attribute: cn address