LDAP - Lightweght Directory Access Protocol

コンピュータを使う上で、検索はよく使う機能のひとつです。例えばユーザ名 からユーザIDやホームディレクトリ、シェルなどはpasswdデータベースを検索 することで得ることができます。このようにあるものをキーとして、それに付 随する情報を検索できるようなサービスを提供するサービスのことをディレク トリサービスといいます。ディレクトリ自体はコンピュータ上だけのものとは 限りません。例えば電話帳や住所録などは典型的なディレクトリの一種です。 これらは人の名前をキーとして、電話番号や住所などを得るためのディレクト リです。これらの例でわかる通りディレクトリというのは基本的に検索を主な 目的とするものです。電話帳や住所録は電話番号や住所をひくのが主で、普通 これに追加するのは情報をひくよりも稀なことです。

UNIXでも既に多くのディレクトリサービスが動いています。UNIXにおけるディ レクトリサービスとして代表的なものとしては以下のようなものがあります。

例えば、ファイルシステムはまさにディレクトリとよぶものでファイル名から ファイルの実体を参照するようになっています。/etc/passwdやNISというもの は、ユーザ名をキーとしてホームディレクトリやシェル、パスワードをひくた めのディレクトリだといえます。DNSはホスト名からIPアドレス、または逆に IPアドレスからホスト名の情報をひく世界にひろがった大規模なディレクトリ システムです。

つまり、ディレクトリサービスというのは既にシステムを動かすにはなくては ならない必要なサービスなのです。

LDAPとは

このようなディレクトリサービスを汎用的に扱うようにできるようにするため の仕組として作られたのがLDAP(Lightweight Directory Access Protocol)で す。LDAPはディレクトリサービスを提供するために必要となる操作をおこなえ るプロトコルを定義したものです。LDAPは特定のディレクトリサービスを提供 するような限られたディレクトリシステムではなく、アプリケーションに必要 な情報を提供できるような枠組を提供しています。また、このプロトコルを利 用するためのAPI(Application Programming Interface)がさまざまなプログラ ミング言語で規定されています。既にC, C++, Java, Perl, Ruby, Pythonなど のプログラミング言語むけのAPIが存在しています。これらのAPIがそろってい るので、LDAPを利用したアプリケーションも作りやすくなっていますし、ディ レクトリそれ自体とそれを使うアプリケーションを分離することができます。

LDAPの由来

LDAPの前に、もともとCCITT/ITU-T(国際電気通信連合電気通信標準化部門)で X.500と呼ばれるディレクトリシステムの規格がさだめられていました。この X.500ディレクトリを使うための低コストで実現できるPCベースのフロントエ ンドを作ろうとしてLDAPが開発されました。当時のPCでも動くようにするため に、もともと複雑になりすぎていたX.500をTCP/IPの世界だけに限定すること で単純なものになりました。単純になったことでさまざまなシステムでも動く ようになっていき、結果的にひろく使えるようになっていったのです。X.500 ディレクトリにアクセスするためのプロトコルはDAP(Directory Access Protocol)と呼ばれていました。これを単純にしたものなので、Lightiweight DAPすなわちLDAPと呼ぶようになったのです。

LDAPのディレクトリ構造

LDAPを使ったシステムでは、LDAPで通信するクライアントサーバシステムとな ります。サーバ側にディレクトリ情報を格納しておき、クライアント側からそ れを検索したり、新たに登録したり、既にある情報を修正したり、削除したり することができます。LDAPでは、ディレクトリに格納する情報は階層構造をし ています(図1)。これをDIT(Directory Information Tree)と呼びます。UNIXのファイルシステムのディレクトリや、 DNSのドメイン名のような構造と同じような感じだと思えばいいでしょう。

図1 Directory Information Tree
|                          <root>
|                            |
|                          dc=jp
|                            |
|                          dc=example
|              +-------------+----------------+
|              |                              |
|            ou=People                     ou=hosts
|           |         |                    |
|       uid=foo   uid=bar               host=master

ファイルシステムでのフルパス名もしくはDNSでのFQDN(Fully Qualified Domain Name)に相当する、LDAPディレクトリ内でのエントリを一意に識別する ための名前を識別名(Distinguish Name;略してDN)と呼びます。ファイルシス テムのフルパス名ではパス名を/でつなげて記述していますし、DNSではドメイ ン名をドット(.)でつなげて記述していますが、LDAPでは識別名(DN)は相対識 別名(Relative Distinguish Name;略してRDN)をコンマ(,)でつなげて記述した ものです。

相対識別名(RDN)は「属性名(アトリビュート名)=属性値(アトリビュートの値)」 という形式で表現します。例えば「ou=People」のような表現になるわけです。

LDAPではDNSと同じように階層構造のトップから枝をたどるにしたがって前に 追加していって表現します。「dc=jp」から相対識別名(RDN) 「dc=example」でたどり、さらに相対識別名(RDN)「ou=People」 でたどり、さらに相対識別名(RDN)「uid=foo」でたどった時の識別名 (DN)は、これらを後からコンマ(,)でつないでいって 「uid=foo,ou=People,dc=example,dc=jp」と表現します (図2)。

図2 Distinguish Name
|            <root>
|              |
|        dc(domain component)がjp:  dc=jp
|              |
|        dc(domain component)がexample: dc=example
|              |
|        ou(organizational unit)がPeople: ou=People
|              |
|        uid(user id)がfoo: uid=foo
|              ↓
|    dn: uid=foo, ou=People, dc=example, dc=jp

DNSでサブドメインをきる時と同様に、LDAPでもある識別名(DN)に相対識別名 (RDN)を追加していくことでサブツリーを作っていくことになります。ひとつ のドメインに複数のサブドメインが作れるように、一つの識別名(DN)から複数 のサブツリーを作れます。もちろんその識別名(DN)からサブツリーを作る相対 識別名(RDN)はそれぞれ異なっていなければいけません。相対識別名(RDN)こそ がサブツリーを区別するものだからです。識別名(DN)では大文字小文字は区別 しません。従って「uid=foo,ou=people,dc=example,dc=jp」も 「UID=FOO,OU=PEOPLE,DC=EXAMPLE,DC=JP」も同じものを表しています。 またコンマ(,)の後の空白も無視されるので、「uid=foo, ou=people, dc=example,dc=jp」も同じものを表わすことになります。

LDAPのディレクトリエントリ

それぞれの識別名(DN)は属性値(アトリビュート名)と属性値(アトリビュート の値)のペアの集りからなる情報を持つことができます。それがその識別名 (DN)によって表されるディレクトリエントリと呼びます。LDAPでよく使われる 属性名としてはリスト1のようなものがあ ります。ディレクトリエントリはこの属性名とその値のペアを一行づつ記述し ます。

リスト1 アトリビュートの例
cn

common name, 人の名前

objectclass

object class

dc

domain component、ドメインの要素

ou

organizational unit 組織の部局

o

organization 組織

c

country 国

st

street 住所

l

location 場所の名前

uid

user id

sn

surname ファミリーネーム

telephonenumber

電話番号

例えばリスト2のように記述します。この記述方法を LDIF(LDAP Data Interchange Format)と呼びます。LDAPにおいてディレクトリ エントリの情報をテキストで表現する時にこのLDIF と呼ばれる表現形式を使 います。リスト2の情報を説明していくと次のようになり ます。

リスト2 LDIF
dn: uid=foo,ou=People,dc=example,dc=jp
uid: foo
objectclass: posixAccount
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/foo
loginShell: /bin/bash
cn: foo bar
dn: uid=foo,ou=People,dc=example,dc=jp

これはou=People,dc=example,dc=jpに相対識別名(RDN)uid=fooを追加したものです(図2) ouというのは組織の部局、dcというのはドメインの要素なのでou=People,dc=example,dc=jpというのはドメイン example.jpの Peopleという部局(人に関する情報をあつめたツリー)という意味になります。これに相対識別名(RDN)uid=fooを追加したものですから、example.jpドメインの人に関する組織の部局のユーザIDがfooの人のエントリであることを表現しています。

uid: foo

ユーザID(uid)がfooという情報を表しています。 この識別名(DN)の相対識別名(RDN)であるuid=fooと同じ情報です。これもディレクトリエントリの中に含めておきます。LDAPでは検索する時はディレクトリエントリの情報しか検索しないので、この行がないとuidがfooであるディレクトリエントリを探そうとしてもこのディレクトリエントリをみつけることができません。

objectclass; posixAccount

このディレクトリエントリのobject classがposixAccountであるということをあらわしています。簡単に言ってしまうと、このディレクトリエントリはposixAccountであればもつべき情報をもっているということを表しているという意味になります。objectclassとは何かについては後述します。

uidNumber: 1001

ユーザID番号(uidNumber)が1001であることをあらわしています。

gidNumber: 1001

グループID番号(gidNumber)が1001であることをあらわしています。

homeDirectory: /home/foo

ホームディレクトリ(homeDirectory)が/home/fooであることをあらわしています。

loginShell: /bin/bash

ログインシェル(loginShell)が/bin/bashであることをあらわしています。

cn: foo bar

この人の一般名(common name。略してcn)がfoo barであることをあらわしています。

このように識別名(DN)によって特定されるディレクトリエントリは属性値の集合によってその情報を表現することになります。

objectclass

objectclassとは、そのディレクトリエントリがどのような属性を持たないと いけないか、どのような属性を持つことができるのかということをあらわすた めの特別な属性です。objectclass属性の値によって、そのディレクトリエン トリがどのような情報をもっているかを知ることができます。オブジェクト指 向でのオブジェクト(インスタンス)に対するクラスがなにかを表しているのと 同じような感じです。またデータベースでいうとスキーマ(schema)情報に相当 します。例えばposixAccountというobjectclassはRFC2307: An Approach for Using LDAP as a Network Information Serviceで次のように定義されていま す。

従ってobjectclass属性がposixAccountであるディレクトリエントリは必ずcn、uid、uidNumber、gidNumber、homeDirectory属性があることがわかるようになっています。

LDAPでの検索

最初に説明した通り、ディレクトリサービスの基本機能は検索です。LDAPでも検索がよくおこなう操作となっています。LDAPで検索する時は次の情報を指定します。

LDAPサーバの場所、つまりホスト名とポート番号。

ポート番号を指定しなかった時のLDAPのデフォルトのポート番号は389です。

検索ベース

既に説明した通り、LDAPではディレクトリ情報は階層構造になっています。検索をする時はその階層構造のどのサブツリーを検索するかを指定します。この時サブツリーのトップとなる識別名(DN)を指定します。これを検索ベース(basedn)と呼びます。

検索スコープ

特に指定しないと、LDAPは検索ベースをトップとするサブツリー全部を検索対象とします。サブツリー全部を検索対象にするのでこれを検索スコープがsubであるといいます。 LDAPでは検索スコープsub以外にいくつか検索範囲を指定することができます。 検索ベースとその子供のディレクトリエントリだけを検索する時、つまり階層を辿って再帰的に孫のディレクトリエントリなどは検索しない時、一段階だけを検索対象とするのでこれを検索スコープがoneであるといいます。 また、検索ベースであらわされている識別名(DN)のディレクトリエントリだけを検索対象とすることもできます。これは検索ベースだけを検索対象とするので検索スコープがbaseになります(図3)。

図3 検索ベースと検索スコープ
|                              <root>
|                                |
|                              dc=jp
|                                |
|  ____________________________  |
|  |        |  scope=base -->  dc=example  <--- basedn dc=example,dc=jp
|  |        |                    |
|  |        |                    |
|  |        |      +-------------+----------------+
|  |   scope=one   |                              |
|  |        +->   ou=People                     ou=hosts
|  |             |         |                    |
|  |             |         |                    |
|  |           uid=foo   uid=bar               host=master
|  V scope=sub
検索フィルター

LDAPでは検索するための条件はRFC2254で定義されている検索フィルターで表現します。検索フィルターでは次のような条件を記述することができます。

LDAPでできないこと

LDAPはディレクトリサービスを提供するためのプロトコルです。あらゆる問題を解決できる魔法の道具ではありません。ディレクトリサービスというのはデータベースが提供する機能と似ているために、データベースでやるべきことまでディレクトリサービスでやろうとしてしまいがちになります。

LDAPはリレーショナルデータベースのかわりにはなりません。

リレーショナルデータベースでは、大量の更新をとりあつかうことができます。またトランザクションの概念もあります。SQLを使った真にリレーショナルな処理もおこなうことができます。LDAPにはこのような仕組はありません。

LDAPはファイルシステムのようには使えない

LDAPもファイルシステムもディレクトリ構造をもっていますが、LDAPには巨大なオブジェクトを扱うのは苦手ですし、そもそも検索用のシステムですから書きこみ処理はそれほど速くはありません。またエントリ内のデータをバイト単位でアクセスしたりすることもできませんし、ロックの概念もありません。

LDAPはDNSのかわりにならない

DNSはドメイン名を扱うのに最適化されています。そもそもLDAP自身もサーバに接続する時などにDNSを見ています。

LDAPでできること

それではLDAPでできることは何でしょうか? LDAPはコンピュータシステムにおける様々なディレクトリサービスを統一した方法で提供することができます。そのため様々なアプリケーションからLDAPという共通のインターフェースを使ってネットワークユーザやリソースの位置を特定したり、それらを管理したり、認証したりすることができます。LDAPの提供するディレクトリを使って誰が何にアクセスしていいかを許可したり拒否したりすることができるわけです。LDAPは認証のためのデータベースとして使うことができるのです。様々なリソース、アプリケーション、サービスに対するアクセスを制御するのにLDAPを使うことができます。 LDAPは汎用のディレクトリシステムなので、公開鍵暗号インフラストラクチャー(PKI)においてもLDAPが使われています。