でびるまんのための えるだっぷ はうつー $Id: ukai.txt,v 1.4 2000/05/30 02:33:48 ukai Exp $ 前回の創刊準備号では「Debianでふりかえる Open Source Project あれこれ」 と題して、とりとめのないことをだらだら書いたわけですが、その中で CVSが重要であるとプッシュしてきたわけです。CVSに関しては、武藤さめの 多大な活躍により「Open Source Development with CVS」の日本語版監訳を でびあんぐるでおこなうことができました。CVSもオープンソース界において かなり一般的になってきましたし、この日本語訳によってさらに基本ツールの 一つとして広まっていくことを期待していたりもするわけです。 で、最近CVSの次に「まいぶーむ」なのが「LDAP(えるだっぷ)」です。今回は このLDAPについて、でびるまん向けにだらだらと書いてみようかと思う次第です:) ■えるだっぷってなに? LDAPとは Lightweight かるめの Directory ディレクトリに Access アクセスするための Protocol プロトコル です。 そもそも X.500なんとかで DAP とかいうディレクトリにアクセスするための プロトコルがあったわけですが、これがいろいろありすぎてもー大変やってらんね という感じで TCP/IPに特化して簡単にしちゃったのが LDAP といっていいでせう。 LDAPv2 が次のRFCに書かれています。 RFC1777: Lightweight Directory Access Protocol RFC1778: The String Representation of Standard Attribute Syntaxes RFC1779: A String Representation of Distinguished Names RFC1959: An LDAP URL Format RFC1960: A String Representation of LDAP Search Filters で、LDAPv3が次のRFCに書かれています。 RFC2251: Lightweight Directory Access Protocol (v3) RFC2252: LDAPv3: Attribute Syntax Definitions RFC2253: LDAPv3: UTF-8 String Representation of Distinguished Names RFC2254: The String Representation of LDAP Search Filters RFC2255: The LDAP URL Format RFC2256: A Summary of the X.500(96) User Schema for use with LDAPv3 Debianでは OpenLDAP (http://www.openldap.org/) が Ben Colins (BenC)により パッケージ化されています。BenC は Debianのいろんな情報を LDAPにつっこもうと がんばってる人です。 ○そもそもディレクトリって? ディレクトリというのは 名簿みたいなものですね。名前からその人の住所とか 電話番号とかいろんな情報がひけるようになっているものはディレクトリと いえばいいでしょう。ファイルシステムにおけるディレクトリも、名前と ファイルの実体(inode)とを関連づけている名簿だと考えればいいでしょう。 UNIXにおいて、ディレクトリはいろいろあります。/etc/passwd もディレクトリと いえばディレクトリです。NISもそうですね。DNSも hostnameとIP address なんかを対応ずけているディレクトリサービスです。LDAPはこういった情報を もっと一般的にアクセスできるようにすることをたくらんでいるプロトコルです。 ○データベースとはなにがちゃうの? データベースとディレクトリは似てますが、データベースは一貫性をたもちつつ データを挿入していくことも重要視されているのに対して、ディレクトリは 主に参照をすばやくやることが重要視されてる点が違うといわれています。 LDAPは、データベースに対するアクセスプロトコルとしてとらえることもできますし データベースをLDAPのバックエンドとして使うこともできます。OpenLDAPでは 1.2 では基本的に ldbm とかをバックエンドのデータベースとして使っていますが 2.0 では SQL的なのもつかえるようになるみたいです。 ■ Debianではどう使う? 既に説明した通り、openldap関係のツールは debianizeされてます。というわけで Debianで インストールして使うには apt-get です。どんなものがあるか調べてみま しょう。こういう時は apt-cache search にかぎりますね! % apt-cache search ldap libroxen-ldapmod - LDAP module for the Roxen Challenger web server python-ldap - An LDAP module for Python. courier-imap - IMAP daemon with PAM and Maildir support libopenldap1 - OpenLDAP libraries. openldap-gateways - OpenLDAP Gateways nscd - GNU C Library: Name Service Cache Daemon libtcl-ldap - Library that enables writing Tcl scripts using the LDAP API reportbug - Reports bugs in the Debian distribution. gq - GTK-enabled LDAP client umich-ldap-utils - LDAP utilities. umich-libldap-dev - static LDAP libraries. php4-ldap - LDAP module for php4 libnss-ldap - NSS module for using LDAP as a naming service ldap-rfc - LDAP Related RFC's from OpenLDAP package openldap-guide - OpenLDAP Admin Guide libnet-ldap-perl - A Client interface to LDAP servers libopenldap-runtime - OpenLDAP runtime files for libopenldap libopenldap-dev - OpenLDAP development libraries. openldap-utils - OpenLDAP utilities. php3-cgi-ldap - LDAP module for PHP3 (cgi) umich-libldap - LDAP libraries. eudc - Emacs Unified Directory Client umich-ldapd - LDAP server. libpam-ldap - Pluggable Authentication Module allowing LDAP interfaces php3-ldap - LDAP module for PHP3 (apache) openldapd - OpenLDAP server (slapd). umich-ldap-docs - Documentation for the LDAP server and utilities. まだあんまり多くないですね。とりあえず ldap を使うにはまず openldap-utils をいれればいいでしょう。apt-get yeah! # apt-get install openldap-utils このパッケージの中には以下のユーティリティが含まれてます。 ldapsearch - LDAPで検索するためのフロントエンド ldapadd - LDAPで情報を追加するためのフロントエンド ldapmodify - LDAPで情報を変更するためのフロントエンド ldapmodrdn - LDAPで名前を変更するためのフロントエンド ldapdelete - LDAPで情報を削除するためのフロントエンド ldappasswd - LDAPでパスワード ud-openldap - LDAPのためのシェルみたいなもの ○LDAPの基礎の基礎 LDAPではディレクトリの要素は次のようになっています。 dn: uid=ukai,ou=users,dc=debian,dc=org <----- 名前 uid: ukai -------+ objectclass: account | objectclass: posixAccount | objectclass: shadowAccount | objectclass: debiandeveloper | gecos: Fumitoshi Ukai,,,, | homedirectory: /debian/home/ukai | cn: Fumitoshi | sn: Ukai +- 中身 loginshell: /usr/bin/zsh | ircnick: ukai | creatorsname: uid=admin,ou=users,dc=debian,dc=org | createtimestamp: 19990621035826Z | modifytimestamp: 20000529124944Z | modifiersname: uid=admin,ou=users,dc=debian,dc=org | keyfingerprint: 9F27C9B37C630789289CABE47BED658A ---+ この最初の「dn: uid=ukai,ou=users,dc=debian,dc=org」がこのディレクトリ エントリの名前で残りがこのディレクトリエントリの情報です。LDAPでは エントリの名前のことを dn (Distinguished Name)といいます。 dn がファイル名、それ以下がそのファイルの中身だと思ってもいいでしょう。 「dn: uid=ukai,ou=users,dc=debian,dc=org」は dn(Distinguished Name)が uid=ukai, ou=users, dc=debian, dc=org であることを意味しています。このように dn では「ふに=ほげ」をカンマで 区切ったものを並べたものになっています。また LDAPでは DNSと同じように ルートからツリーを形成するディレクトリをつくっており、rootに近い方が 後ろにくるようになってます。つまり上のエントリは | dc=org | dc=debian +-------------+----------------+ | | ou=users ou=hosts | | | uid=ukai uid=foo host=master のようなかんじになってるわけです。 DNSとは違うところはこのような各ステップにおいて、どのタイプの要素かを 指定できる点です。また、それぞれの段階でどの要素を使うかは LDAPでは 決められていません。LDAPを運用してる人が決めます。 上のをわかりやすくかくと | dc(domain component)がorg | dc(domain component)がdebian | ou(organizational unit)がusers | uid(user id)がukai となってるのです。ちなみに dn はDNSのドメイン名と同じように 大文字小文字を区別しません。この最後の uid=ukai に上で示したような uid: ukai objectclass: account objectclass: posixAccount objectclass: shadowAccount objectclass: debiandeveloper gecos: Fumitoshi Ukai,,,, homedirectory: /debian/home/ukai cn: Fumitoshi sn: Ukai loginshell: /usr/bin/zsh ircnick: ukai creatorsname: uid=admin,ou=users,dc=debian,dc=org createtimestamp: 19990621035826Z modifytimestamp: 20000529124944Z modifiersname: uid=admin,ou=users,dc=debian,dc=org keyfingerprint: 9F27C9B37C630789289CABE47BED658A : がはいっています。ここでは「ふに: ほげ」というかたちで情報(アトリビュート)が 示されます。普通 uid=ukai というエントリには uid: ukai という 情報がはいってます。また objectclass というのはこのエントリの内容 (object)がどのようなクラスか、つまりどのような情報を持っているべきか 持つことができるかを示しています。アトリビュートの名前(objectclass とかhomedirectoryとか)は大文字小文字の区別がありません。そのため objectClass とか homeDirectory などのように表記することもよくあります。 それぞれのアトリビュートはそれがもっている情報がどのようなタイプなのかが 決められています。名前系(cn (common name; 一般名)や sn (sur name: 姓)) などでは大文字小文字を区別しない文字列を含むことになっています。 上の例では creatorsname なんかは dn と同じ形式 (ふに=ほげ を カンマで区切って並べたもの)をもちます。createtimestamp はタイムスタンプです。 keyringerprint みたいなものは、大文字小文字を区別する文字列です。 ここにはありませんが、電話番号的なものもあります。 さて、アトリビュートとしてどういうものを持つかを決めてるのが objectclass です。objectclass で指定されたものそれぞれについて 持たないといけないアトリビュート、持つことのできるアトリビュートが 決まっています。データベースのスキーマですね。 ここまで示してきたのを ldif フォーマットといいます。 ○検索してみよー とりあえずものは試し、検索してみましょう。Debian Project では db.debian.org というマシンで LDAP が動いています。こいつを使って 検索してみましょう。検索には ldapsearch を使います。 % ldapsearch -L -h db.debian.org -b 'dc=debian, dc=org' 'uid=ukai' これでババソと検索できます。オプションを簡単に解説すると -L ldif 形式で出力 -h db.debian.org db.debian.org の ldap serverに接続 -b 'dc=debian, dc=org' directoryのどこから検索するか(base dnという) を指定。db.debian.org では「dc=debian, dc=org」 以下の情報をもっているのでこれを指定する で引数として検索パターンを指定します。ここで指定しているのは 「uid=ukai」です。さらにオプショナルな引数を指定するとその情報だけを とりだせます。例えば % ldapsearch -L -h db.debian.org -b 'dc=debian, dc=org' 'uid=ukai' ircnick dn: uid=ukai,ou=users,dc=debian,dc=org ircnick: ukai こんなかんじ。ldapsearch で検索してるのは dn じゃありません。例えば こんな検索も可能です。 % ldapsearch -L -h db.debian.org -b 'dc=debian, dc=org' 'ircnick=ukai' uid dn: uid=ukai,ou=users,dc=debian,dc=org uid: ukai このように ircnick は dn には現れてきませんが、それで検索ができます。 検索パターンには「*」とかも使えます。 % ldapsearch -L -h db.debian.org -b 'dc=debian, dc=org' 'uid=u*' uid これで uid が u ではじまるものの uid を全て検索できます。 = 以外に ~= もつかえます。これは「似てる文字列」を検索してくれる(はずです) 例えば % ldapsearch -L -h db.debian.org -b 'dc=debian, dc=org' 'ircnick~=uki' のように uki でも ircnick=ukai にマッチします。 (http://db.debian.org/ の fuzzy searchはこれっす) 比較演算子は >= と <= があります。< とか > はないので気をつけましょう。 & や | はこのように書きます。 % ldapsearch -L -h db.debian.org -b 'dc=debian, dc=org' '(&(uid=u*)(c=JP))' このように Lisp風(?)に & や | のオペレータを前に書くことになってます。 この場合は Perl風(?)にあえて書くと ($attr{'uid'} ~= /^u.*/) && ($attr{c} eq 'JP') みたいなかんじでしょうか。 否定も ! を使って (!(uid=ukai)) のようにします。 ちなみに、これらの検索文字列に関しては RFC2254なんかを読みましょう。 さて、ここで「dc=debian, dc=org」を basedn にして「uid=ukai」を指定するだけで ou=users 以下を勝手に探してきてくれるのにきづいてるでしょうか? LDAPでは、このように basedn 以下を再帰的に探してくれます。 もちろん「ou=users, dc=debian, dc=org」を basedn にしてもこの場合は、同じ結果 になります。 では「dc=debian, dc=org」以下にはなにがあるんでしょう? そういうことを 調べたい場合は % ldapsearch -L -s one -h db.debian.org -b 'dc=debian, dc=org' 'objectclass=*' dn: ou=users,dc=debian,dc=org ou: users objectclass: top objectclass: organizationalUnit creatorsname: uid=admin,ou=users,dc=debian,dc=org createtimestamp: 19990621035217Z dn: ou=hosts,dc=debian,dc=org creatorsname: uid=jgg,ou=users,dc=debian,dc=org createtimestamp: 19990929040639Z modifytimestamp: 19991202052145Z modifiersname: uid=jgg,ou=users,dc=debian,dc=org ou: hosts objectclass: top objectclass: organizationalUnit このように objectclass=* で検索するといいのです。というのもobjectclassと いうのは必ず存在することになっているので objectclass=* で全部マッチするから です。また、このようなことをする場合は「-s one」オプションを指定しておく 方がいいでしょう。これにより 一レベルだけの検索となります。これがないと 再帰的に全部調べることになってしまうので膨大な結果がかえってくることに なります。 ○実例 ◇ potato のマシンってどれやねん? % ldapsearch -h db.debian.org -b 'ou=hosts, dc=debian, dc=org' \ 'distribution=*potato*' host ◇ そのうちalphaなのはどれじゃ? % ldapsearch -h db.debian.org -b 'ou=hosts, dc=debian, dc=org' \ '(&(distribution=*potato*)(architecture=alpha))' host ◇ wiggy って誰よ? % ldapsearch -h db.debian.org -b 'ou=users, dc=debian, dc=org' 'ircnick=wiggy' gecos ircnick ◇ 日本のでびるまん? % ldapsearch -h db.debian.org -b 'ou=users, dc=debian, dc=org' 'c=JP' uid ■まぁ でもWebインターフェースがあったり(ワラ 実は直接 ldapsearch を使わなくても、これを使った web interface が http://db.debian.org (https://db.debian.org/) があるわけです。 普通はこっちを使えばいいでしょう。(というかこれでしか見られない アトリビュートもあったり) ■ userdir-ldap というのがあって ちなみに この db.debian.org の ldap情報は userdir-ldap という 仕組みで debian.org のアカウント情報をできるだけ一元管理しようと しています。LDAPでアカウント管理というと PAMとかがすぐに思いついたり する人もいるかもしれませんが、PAMだとネットワークがアレになったり した時にいろいろ困るので、userdir-ldap では LDAPの情報を元に db ファイルを作成し、それを rsync で配布しています(ようです) つまり /etc/nsswitch.conf で passwd: compat db group: db compat shadow: compat db のようにしておいて /var/lib/misc (glibc-2.1/potatoの場合; glibc-2.0/slinkなんかでは /var/db にある)あたりに passwd.db とか group.db とか shadow.db を置いてます。こうしておくと libc が passwd: /etc/passwd になければ /var/lib/misc/passwd.db group: /var/lib/misc/group.db になければ /etc/group shadow: /etc/shadow になければ /var/lib/misc/shadow.db のようにさがしてくれます。 この dbファイルの作りかたは /var/lib/misc/Makefile (potatoの場合; slinkだと /var/db/Makefile)を見るとわかるでしょう。 ■ Bug Tracking System の LDAPわ? BenC あたりが中心となって(?) Bug Tracking System も LDAP に格納されて たりするようです。reportbug が、その LDAP を参照しています。 これは /usr/lib/site-pytyon/reportbug.py とかを見るとわかりますが 'ldap' : ('bugs.debian.org', 35567, 'ou=Bugs,o=Debian Project,c=US') となっています。 ldap serverが bugs.debian.org ldap portが 35567 base dnが ou=Bugs,o=Debian Project,c=US という意味です。調べてみるとわかるんですが、この LDAPでは objectClass がないんで、objectclass=* ではうまく調べることが できないようです。ちなみに次のようになっているようです。 dn: bugID=バグナンバ,OU=BUGS,O=DEBIAN PROJECT,C=US bugid: バグナンバ originater: レポートした人 date: レポートされた日 subject: サブジェクト messageid: メッセージID package: パッケージ名 severity: 重要度 done: クローズした人(クローズしてれば) mergedwith: マージの情報(あれば) forwarded: forward先(あれば) 例えばw3mパッケージのバグを調べたい場合は % ldapsearch -h bugs.debian.org -p 35567 -b 'ou=Bugs,o=Debian Project,c=US' \ 'package=w3m' で調べられますし、Bug#XXXXX のバグを調べたい場合は % ldapsearch -h bugs.debian.org -p 35567 -b 'ou=Bugs,o=Debian Project,c=US' \ 'bugID=XXXXX' でわかります。 しかしながら、どうもこの LDAP serverはまがいものっぽく、複雑な検索パターンは うまく扱えないようなかんじです。使えるのは上の2パターンだと思っておいた 方が無難かもしれません(上のは reportbug でも利用している) ■ これでLDAPで検索もばっちり かどうかは、わかんないですがとりあえず今回はこれで終わりです。 Debianでは今後 package pool などでも LDAPをバソバソ活用していく かんじなので、でびるまんは LDAP をマスターしましょー。 つづく(?) 参考文献 * openldap-guide: apt-get しましょう * ldap-rfc: apt-get しましょう * `Understanding and Deploying LDAP directory services' - MacMillan Network Architecture and Development Series' by Timothy A. Howes, Ph.D., Mark C. Smith, and Gordon S. Good ISBN 1-57580-070-1 LDAPをどう運用していけばいいか、LDAPにもっていくにはどうすれば いいかについていろいろ書いてある本。ぶあつくて重い。 日本語版はでないのか? * `LDAP: インターネットディレクトリアプリケーションプログラミング' by Tim Howes, Ph. D., Mark Smith ISBN 4-89471-008-0 `LDAP: Programming Directory-Enabled Applications with Lightweight Directory Access Protocol' の日本語版 LDAPを理解した人が「じゃあ LDAPを使ったアプリケーションはどうやって 書けばいいの?」という時に読む本。LDAPの基礎知識(ldifとか)がないと 読んでもわからないかんじ…