openLDAPのPerl Backendをいじってハマった話

話の発端としてはtagomorisさんのページを見た某社の方より、こんな感じのものを作って欲しいんだがというご相談を頂きまして着手しましたところ、非常にドハマりしましたので後に続くかもしれない方々にメモメモ。

オンラインドキュメントも相変わらず"LATER"のままです。どこかに更新されたドキュメントがあるんじゃないかと期待して探し回ってみましたがダメな感じです。もう忘れ去られた感がアリアリしております。何かしらの参考資料を探してみても、これと言って見当たらず、”LISM”というPerl Backendを利用したOSSの統合認証のソフトウェアがあり、良くぞ作ったなあという感もありまして参考にさせてもらいました。ただAdminツールにディスコン気味のEthnaが必要とかで、このままではインストールも困難だったりする。

openLDAP関連の書籍も、すでに書店では事実上2冊しかない。入門LDAP/OpenLDAP―ディレクトリサービス導入・運用ガイドLDAP -設定・管理・プログラミング-だ。前者はまだ何とか使えるものの、後者は発行が2003年だ。また、どちらもopenLDAPそのもののインストール、設定がメインで、バックエンドの作成にはちっとも触れられていない。洋書も何冊かチェックしてみたが、これといって参考になりそうなものもなく。

「man 5 slapd-perl すると、ちょっと詳しく書いてある。興味がある人は読んでみよう、というか、読まないと何もできない。またOpenLDAPの tarball を展開した中の servers/slapd/back-perl/SampleLDAP.pm がサンプルなので、読んでみるとなんとなく雰囲気がわかる。(雰囲気しかわからない。)」の状況からは一歩も進んでいない状況です。

とにかく試して、動きを見るのが一番という事で、SampleLDAP.pm を動かしてみることに。

ソースからビルドする場合には –enable-perl をつければOK。ディストリビューションの配布パッケージによっては、これが有効になっていたり、なっていなかったりするので、お使いの環境のパッケージを調べてみてください。(ちょっと脱線するが、id2entry.dbが無いというバグに私もハマった。お気を付けください。あとディストリビューションによっては、make dependしたときにPerlのモジュール不足で止まる事があります。結構、心が折れそうになりますがガンバ!)

で、slapd.conf には、次のように書く。

############## perl backend #############
database        perl
suffix          "dc=example,dc=com"
rootdn          "cn=Manager,dc=example,dc=com"
rootpw          xxxxxxx
perlModulePath  /path/to/handler/module/dir
perlModule      SampleLDAP

この場合、 /path/to/handler/module/dir に SampleLDAP.pm ファイルをコピーする。後は普通のopenLDAPの操作と同じで ldapaddでLDIF情報追加し、ldapsearchで検索する事が出来る。おそらくはここまでは問題なく進むと思うのだが、時々slapdが落ちる現象が確認される。ldapsearchを叩いていると時々反応が無くなる瞬間があるのだが、slapdのプロセスを見ると見事に落ちている。

いろいろ調べてみた結果、SampleLDAP.pmにはbind()の記述が無く、slapdがこのリクエストを受けると落ちるという事が分かる。取りあえず、SampleLDAP.pm の一番最後にでも次のようにダミーでもbind()を入れておくと落ちなくなることが分かる。

bind(){
     return 0;
}

SampleLDAP.pm の動きについてはコードを見てもらえればわかるが、持っている情報をどっと吐き出す感じの動きになっている。ただ、検索のフィルター条件にちょっと込み入った文字列を指定してもslapdが落ちたりするので、結構シビア。うーん・・・
(この後もコードをいじっていると、「なぜこれで?!」といった、結構、理不尽に落ちることが多かったので、こまめに動作チェックをされることをお勧め。謎のプロセス停止が頻発する場合には、configureする際に –with-threads=no をつけると安定するかもしれない。)

私の場合には、後続のデータソースから認証情報を引っ張ってきて、これを使って認証させるわけです。スキーマーがposixAccount位なら、LDIFに入れるべき情報を全部データソースの中に突っ込んで、リクエストがあるたびにそれを参照して応答を作るか、パフォーマンスの問題が出てきそうならキャッシュの仕組みを作るとかで対応できると思う。search(), bind()のなかで認証情報を確認して、それぞれLDIF形式で応答内容を作ればOK。

全体にわたって、Perl-backendだからといって、何か便利ライブラリとかあるわけでもなく、ほとんど素でslapdからデータが引き渡されるので各LDAPコマンドごとに処理ロジックを実装していく必要があります。特に面倒なのはsearch()のFilterStringの部分の処理で、あの癖のある形式での条件指定をひも解かないといけないのですが、これといったツールもなく面倒です。slapdからの応答を作成するのに関しては Net::LDAP::LDIFが役に立つでしょう。きっと。

(さらにsambaをサポートしようとすると、Perl-Backendだけで解決しようとすると、かなりヒイヒイいう事になります。私は諸般の事情で諦めざるを得ず、裏にPerl-Backendではないslapdを併用してリクエスト/応答をPerl-Backendで中継する方法を取りました。)

認証というと最近はActiveDirectoryの方が断然利用されていて、openLDAPも影が薄くなりつつありますが、何かの事情で使う事があればご参考になればいいなと。

技術・開発openLDAP

Posted by tomi