毎回テーマがコロコロと変わる本連載ですが、今回はOpenLDAPを運用する上で必須となるログの知識についてお話しします。トラブルシューティング時にログと格闘するのは管理者の必要最低限の行動です……よね。
OpenLDAPとログの設定
OpenLDAPのログはsyslogを経由して出力されます。ログの設定はいつものslapd.conf中のloglevelというパラメータで設定します。
loglevelで指定可能な値は表1のように定義されています。
表1 loglevelの値とログの収集データの関係
値 | ログ収集データ |
1 |
trace function calls |
2 |
debug packet handling |
4 |
heavy trace debugging |
8 |
connection management |
16 |
print out packets sent and received |
32 |
search filter processing |
64 |
configuration file processing |
128 |
access control list processing |
256 |
stats log connections/operations/results |
512 |
stats log entries sent |
1024 |
print communication with shell backends |
2048 |
entry parsing |
以上のいずれかを設定することにより、slapdからsyslogデーモンにログが送出されるのですが、当然のことながらsyslogデーモン側でも適切に設定を行っておく必要があります。slapdからのログはlocal4というファシリティで出力されるため、/etc/syslog.confにリスト2のような設定を追記し、syslogdを再起動しておいてください。
syslog-ngなどのその他のsyslogデーモンを使用している場合にも、local4というファシリティのログを適切に出力できるよう設定を行ってデーモンを再起動しておく必要があります。
ログの出力例
syslogデーモンの設定を適切に行った場合、loglevelの値を変更しつつldapaddやldapsearchコマンドを実行すると、リスト3~7のようなログが出力されます。
これらのサンプルからわかるように、loglevelは適切に設定しておく必要があります。さもなければ、トラブルが起きても全くログが吐かれていなかった、ということにもなりかねません。基本的にはloglevel 256などを設定しておくのが良いでしょう。
ログを読む
HTTPの世界で、正常にページ表示できれば200、ファイルが存在しなければ404といったステータスコードが返るのと同様、LDAPでも各種コードや操作識別のための手段が用意されています。たとえば、エントリ追加時のログを見てみましょう(リスト8)。すべての操作はログからわかるようになっています。
まずこれらのログで一致しているのは、conn=0となっている部分です。つまり、これらのオペレーションは複数のTCP接続ではなく、1度のTCP接続(ldap_open)で行われたことを意味しています。たとえば、もしldapaddコマンドを発行した後にldapsearchコマンドを実行した場合、それらは別々のプロセス、つまり接続として取り扱われますので、ログ中にはconn=0とconn=1が記録されることとなります。
次に着目すべきはop(オペレーション)です。このログが意味するところは、文字通り接続時の操作ですので、1回のLDAP接続で3回のオペレーションが行われた、ということになります。op=0はバインドに関する部分であり、op=1はエントリの追加、op=2はアンバインドです。
以上の点を整理してみると、リスト8のログから、実際にはサーバ上で次のような操作が行われたことがわかります。
- 127.0.0.1:32785というクライアントからからLDAP接続が行われた
- その際、cn=Manager,dc=example,dc=comというDNでシンプル認証が行われ、無事認証が通った(err=0)
- cn=suzuki,ou=People,dc=example,dc=comというDNの追加が試行され成功した(err=0)
- アンバインドされた後、切断された。
トラブルシューティング
LDAPとさまざまなソフトウェアを連携させる中で、正しく設定を行っているつもりでもうまく認証できない、という場面に遭遇することがあります。
本連載では過去にOpenSSHの公開鍵をLDAPで管理する方法を紹介しました。これを例として、「OpenSSHの設定を正しく行ったつもりだが、うまく公開鍵認証ができない」という問題のトラブルシューティングを行ってみます。
まずはもっとも基本的な方法として、たとえばLDAPサーバに全くログが出力されないとします。この場合、バインドDNや検索フィルタの設定以前に、正しいサーバが指定されていなかったり、そもそもパッチがうまく当たっていないことが考えられます。LDAPサーバの389/tcpに接続が1度でも行われれば、必ずACCEPTというログが出力されるためです。
ではログの分析に入りたいと思います。
この操作を見てみると、ou=people,dc=example,dc=com
以下で
filter="(&(objectClass=posixAccount)
(objectClass=ldapPublicKey)(uid=root))"
という検索が何度か行われているにもかかわらず、サーチ後のRESULTが err=0 nentries=0
となっています。
つまり、検索自体は成功したけれどもエントリが1つも返ってこなかったことを意味しています。エントリが1件も見つからない、つまりLDAPサーバ上に公開鍵が見つからないのですから、公開鍵認証ができないことは明白です。
試しにldapsearchコマンドを利用して同等のコマンドを実行しても、当然のことながらエントリは返ってきません。
以上のことから、今回のトラブルのチェックポイントは次のようになります。
ou=people,dc=example,dc=com
の下に
"(&(objectClass=posixAccount)(objectClass=ldapPublicKey)
(uid=root))"
であるデータが登録されているか確認
- さらに、そのLDIF中にsshPublicKey属性が含まれ、値が登録されているかを確認
エラーコード
いくつかのログからLDAP操作を見てきたわけですが、エラーコードが0でない場合、つまりldapsearchコマンドやldapaddコマンドが失敗した場合のトラブルシューティングはどのように行えば良いのでしょうか?
たとえば、親エントリがない場合にldapaddした際のログは、リスト10のようになります。
同様に、すでにDNが存在する場合にそれを上書きしようとするとリスト11のようなログになります。
パスワードが間違っておりうまくバインドできなかった場合はリスト12のようなログです。
これらの操作では、エラーコードがそれぞれ32、68、49と出力されているため、追加操作に失敗したことを意味しています。また、エラーコードについては/usr/include/ldap.h(リスト13)に定義されています。これらのコードは16進数で定義されています。10進数で表される32、68、31というコードは16進ではそれぞれ0x20、0x44、0x31であるため、原因は
LDAP_NO_SUCH_OBJECT、LDAP_ALREADY_EXISTS、
LDAP_INVALID_CREDENTIALS
であることがわかります。LDAPサーバを管理していると、エラーコード49や68はよく目にしますので、そのうち皆さんも自然と数字の意味を覚えられるようになると思います(笑)。
まとめ
以上、非常に簡単でしたがOpenLDAPのログの読み方について簡単に紹介してきました。LDAPに限った話ではありませんが、困ったときにはすぐにログファイルをtail -f
するような習慣を身につけたいものです。