OpenLDAP モニタリング

OpenLDAPは、オープンソースの軽量ディレクトリアクセスプロトコル(LDAP)サーバーソフトウェアです。ユーザーアカウント、組織構造、設定情報など、さまざまな情報を保存・管理するための、カスタマイズ可能で拡張可能なディレクトリサービスを提供します。これらの情報はツリー構造で整理・保存されるため、高速なクエリと取得が可能です。 多くの企業が、ユーザーアカウントと権限の集中管理にOpenLDAPを使用しています。ユーザーは、社内メール、VPN、GitLab、Jenkinsへのログインなど、さまざまな社内システムやリソースにアクセスする際に、OpenLDAPを使用して統一された認証と認可を行うことができます。 もちろん、自宅でも利用できます。例えば、春節(旧正月)の休暇中など、多くの人が集まる時期には、OpenLDAP を実行する Linux 仮想マシンをセットアップして NAS に接続すれば、非常に便利に使えるでしょう。

OpenLDAP 自体の導入とメンテナンスについては、既に豊富な情報が存在するため、この記事では扱いません。OpenLDAP に接続して監視を行う方法に焦点を当てます。

背景は次のとおりです。私は年内にスタートアップ企業に入社しました。少し前に、技術グループの誰かから、OpenLDAP のログイン問題が業務に影響していると報告を受けました。緊急時には、関係する同僚がすぐに OpenLDAP コンテナ サービスを再起動して問題を解決しました。このような状況は小規模企業では非常によく見られます。おそらく、接続されているサービスが少なかったか、メンテナーがずっと前に退職していたか、あるいは外部への影響がなかったのでしょう。再起動こそが、実際には最も迅速かつ効果的な解決策かもしれません。😂

その朝の私の勝手な推測は、デフォルトの FD 設定である 1024 では不十分だったのではないかというものでした。サービスの数が多いと、この状況は続く可能性が高いでしょう。これは歴史的な問題であり、当然のことです。当時は5人しか使っていなかったのかもしれませんし、会社側も2年後に閉鎖する予定だったのかもしれません。

誰か一人でもプログラムが動いている限りは問題ありません。もし到着して動作しないという状況に陥り、それでも安心したい場合はどうすればいいでしょうか?監視機能を追加しましょう。Googleで「OpenLDAP 監視」を検索してみましたが、中国語の情報は驚くほど少なかったです。そこで、空白を埋める必要がありました。

Prometheusは、近年非常に一般的な監視システムです。使いやすく、活発なコミュニティがあり、個人的には数年前よりもずっと手間がかからなくなったと感じています。

正直なところ、私が選んだ解決策はPrometheus + openldap_exporter [https://github.com/tomcz/openldap_exporter] でした。残念ながら、作者はこのリポジトリをアーカイブしてしまい、メンテナンスも終了していますが、まだ利用可能です。スキルがあれば、フォークして自分で試してみるのも良いでしょう。

オリジナルの OpenLDAP はコンテナ化されたアプローチでデプロイされていたため、監視システムへの接続は少し面倒で困難でした。コンテナリポジトリは次のとおりです: https://github.com/osixia/docker-openldap

1. 監視システムへの接続方法

テスト環境を見つけてからコンテナに入ることをお勧めします。

  • 負荷監視モジュール module
 1root@xxxxxxx:/# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=module{0},cn=config"
 2SASL/EXTERNAL認証を開始しました
 3SASLユーザー名: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 4SASL SSF: 0
 5# 拡張LDIF
 6#
 7#LDAPv3
 8# ベース <cn=module{0},cn=config> スコープサブツリー付き
 9# フィルター: (objectclass=*)
10# 要求: ALL
11#
12
13# module{0}, config
14dn: cn=module{0},cn=config
15objectClass: olcModuleList
16cn: module{0}
17olcModulePath: /usr/lib/ldap
18olcModuleLoad: {0}back_mdb
19olcModuleLoad: {1}memberof olcModuleLoad: {2}refint
20
21検索結果 #
22search: 2
23結果: 0 成功
24
25レスポンス数 #numResponses: 2
26エントリ数 #numEntries: 1
27root@9e93cb7f031d:/# ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
28> dn: cn=module{0},cn=config
29> changetype: modify
30> add: olcModuleLoad
31> olcModuleLoad: back_monitor
32> EOF
33SASL/EXTERNAL認証を開始しました
34SASLユーザー名: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
35SASL SSF: 0
36エントリ「cn=module{0},cn=config」を変更しています
37
38root@9e93cb7f031d:/# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=module{0},cn=config"
39SASL/EXTERNAL認証を開始しました
40SASLユーザー名: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
41SASL SSF: 0
42# 拡張LDIF
43#
44#LDAPv3
45# スコープサブツリーを含むベース <cn=module{0},cn=config>
46# フィルター: (objectclass=*)
47# 要求: ALL
48#
49# module{0}, config
50dn: cn=module{0},cn=config
51objectClass: olcModuleList
52cn: module{0}
53olcModulePath: /usr/lib/ldap
54olcModuleLoad: {0}back_mdb
55olcModuleLoad: {1}memberof
56olcModuleLoad: {2}refint
57olcModuleLoad: {3}back_monitor
58
59検索結果
60search: 2
61Result: 0 Success
62
63レスポンス数: 2
64エントリ数: 1

上記の操作の出力から、監視モジュールがロードされたことがわかります。

  • 監視ユーザーの追加

パスワードをxxxに置き換えました。操作例:

 1root@4433d2af4a1d:/# slappasswd -s your_password
 2{SSHA}xxx
 3
 4ldapadd -Y EXTERNAL -H ldapi:/// <<EOF
 5dn: cn=monitor,dc=example,dc=org
 6objectClass: simpleSecurityObject
 7objectClass: organizationalRole
 8cn: monitor
 9description: LDAP monitor
10userPassword: {SSHA}xxx
11EOF

最初の表示には権限がありません。-w admin は管理者権限での書き込みを意味します。

 1root@9e93cb7f031d:/# ldapadd -Y EXTERNAL -H ldapi:/// <<EOF
 2> dn: cn=monitor,dc=example,dc=org
 3> objectClass: simpleSecurityObject
 4> objectClass: organizationalRole
 5> cn: monitor
 6> description: LDAP monitor
 7> userPassword: {SSHA}3W8Q0HWiBVRyy2qX47qPVZQxQvZ3/R9+
 8> EOF
 9SASL/EXTERNAL認証を開始しました
10SASLユーザー名: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
11SASL SSF: 0
12新しいエントリ「cn=monitor,dc=example,dc=org」を追加しています
13ldap_add: アクセス権限が不十分です (50)
14追加情報: 親への書き込み権限がありません
15
16root@9e93cb7f031d:/# ldapadd -x -D cn=admin,dc=example,dc=org -w 'admin' <<EOF
17> dn: cn=monitor,dc=example,dc=org
18> objectClass: simpleSecurityObject
19> objectClass: organizationalRole
20> cn: monitor
21> description: LDAP monitor
22> userPassword: {SSHA}xxx
23> EOF
24新しいエントリ "cn=monitor,dc=example,dc=org" を追加しています
  • 新しく追加したユーザーが情報を正常に読み取れることを確認します
1root@9e93cb7f031d:/# ldapwhoami -x -D "cn=monitor,dc=example,dc=org" -w "your_password"
2dn:cn=monitor,dc=example,dc=org

上記のように、クエリ結果はユーザー情報が正しいことを示しています。上記で設定したパスワードを入力してください。

  • 監視データベースを追加します
1ldapadd -Y EXTERNAL -H ldapi:/// <<EOF
2dn: olcDatabase={2}Monitor,cn=config
3objectClass: olcDatabaseConfig
4objectClass: olcMonitorConfig
5olcDatabase: {2}Monitor
6olcAccess: {0} to dn.subtree="cn=Monitor" by dn.base="cn=monitor,dc=example,dc=org" read by * none
7EOF

データベースが存在する場合:

1ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
2dn: olcDatabase={2}Monitor,cn=config
3changetype: modify
4replace:olcAccess
5olcAccess: {0} を dn.subtree="cn=Monitor" に変更しました。dn.base="cn=monitor,dc=example,dc=org" によって * なしによって読み取り
6EOF
 1root@9e93cb7f031d:/# ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
 2dn: olcDatabase=Monitor,cn=config
 3changetype: modify
 4replace:olcAccess
 5olcAccess: {0} を dn.subtree="cn=Monitor" に変更しました。dn.base="cn=monitor,dc=example,dc=org" によって * なしによって読み取り
 6EOF
 7SASL/EXTERNAL 認証を開始しました
 8SASL ユーザー名: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 9SASL SSF: エントリ "olcDatabase=Monitor,cn=config" を変更しています
10ldap_modify: そのようなオブジェクトはありません (32)
11一致するDN: cn=config

上記は、データベースが存在しない場合のエラーメッセージです。データベースが存在しない場合、直接変更することは絶対に不可能です(存在する場合:ldapmodify、存在しない場合:ldapadd であり、これは妥当かつ正しい方法です)。

とてもシンプルに見えますね。初めて理解する方は、上記の文の意味を理解するのにかなり時間がかかるでしょう。私は公式ドキュメントを読み、AI支援を受け、実践練習をかなり時間をかけて行いました。

2. 監視コンポーネント openldap_exporter をデプロイする

上に監視モジュールがありませんか?なぜここに別の監視コンポーネントがあるのでしょうか?それは違います。上記はサーバー、そしてこちらはクライアントです。クライアントは上記の監視モジュールの情報を読み取ってPrometheusに出力します。リンクは次のようになります。

Prometheus <--- openldap_exporter 監視コンポーネント <--- OpenLDAP サーバー監視モジュール

この部分は非常にシンプルで、特に説明することはありません。操作を参照してください:

 1xxx@xxx: cat /etc/systemd/system/openldap_exporter.service
 2[Unit]
 3説明=OpenLDAP Exporter
 4After=network.target
 5
 6[Service]
 7タイプ=simple
 8ExecStart=/opt/openldap_exporter/openldap_exporter --promAddr ":8080" --interval "10s" --config /opt/openldap_exporter/config.yml
 9Restart=on-failure
10
11[Install]
12WantedBy=multi-user.target
13
14xxx@xxx:~$ cat /opt/openldap_exporter/config.yml
15---
16ldapUser: "cn=monitor,dc=example,dc=org"
17ldapPass: "your_password"

If monitoringコンポーネント メトリクスが正しく表示されない場合は、根気強くトラブルシューティングを行う必要があります。まず、サーバーに問題がないことを確認し、次にサーバーログを確認し、監視コンポーネントのソースコードも読んでみてください。聞かないでください。私自身もそうできました。あなたは私より幸運です。私より前にこれを書いた中国語ユーザーはいませんし、そもそも見つけることもできませんでした。

3. Prometheus への接続

簡単な例を以下に示します。

1- job_name: "openldap"
2static_configs:
3- targets: ["10.10.20.98:8080"]

スクリーンショットを撮るのが面倒です。

4. Grafana への接続

ご存知のとおり、監視ダッシュボードは非常に便利で、リーダーや上司に大変好評です。

残念ながら、コミュニティには既製のダッシュボードがあまりないので、自分で作成しました。もしご希望でしたら、私のWeChat公式アカウントをフォローしていただければお送りします。本当にフォローしていただければ、お送りします。

下記のストレステストのサンプル画像をご覧ください。

5. ストレステスト

前述の通り、初期診断では、問題はFDの数の設定ミスが原因であると考えられます。これを検証するには、ストレステストを実施する必要があります。

ストレステストプログラムが公開されました:

 1
 2import ldap
 3import time
 4
 5def main():
 6connections = []
 7target_connection_count = 1023
 8try:
 9while len(connections) < target_connection_count:
10try:
11# localhost:389 の openldap サービスへの接続を試みます
12conn = ldap.initialize("ldap://localhost:389")
13conn.simple_bind_s("cn=admin,dc=example,dc=org", "admin") # 有効な管理者 DN とパスワードを使用してください
14connections.append(conn)
15result = conn.search_s("dc=example,dc=org", ldap.SCOPE_SUBTREE)
16print(result)
17time.sleep(0.5)
18except ldap.LDAPError as e:
19print(f"LDAP エラーが発生しました: {e}")
20break
21while True:
22# ファイル記述子を維持するためにプログラムを実行したままにします。
23pass
24except Exception as e:
25print(f"エラーが発生しました: {e}")
26finally:
27# 確立済みのすべてのLDAP接続を閉じます。
28for conn in connections:
29try:
30conn.unbind()
31except ldap.LDAPError:
32pass
33
34if __name__ == "__main__":
35main()

sleep は接続確立の速度を制御し、調整または削除できます。ldap パッケージにはいくつかのシステム依存関係があることに注意してください。依存関係がない場合、インストールされません。

ストレステスト結果:

openldap

最終更新日: Wednesday, August 13, 2025

このシリーズの投稿:

翻訳: