OpenLDAP監控

OpenLDAP 是一款開源的輕型目錄訪問協議(Lightweight Directory Access Protocol,LDAP)服務器軟件。提供了一個可定製、可擴展的目錄服務,用於存儲和管理各種類型的信息,如用戶賬戶、組織結構、配置信息等,這些信息以樹形結構進行組織和存儲,方便快速查詢和檢索。 許多企業將 OpenLDAP 用於集中管理用戶賬戶和權限,用戶在訪問公司的各種系統和資源時,可以通過 OpenLDAP 進行統一的身份認證和授權,如登錄企業郵箱、VPN、Gitlab、Jenkins等。 當然也可以家用,比如說現在過年人多,你可以弄個Linux虛擬機跑OpenLDAP,讓NAS接入,好像也有點用。

本文不講OpenLDAP本身的部署維護,因爲相關資料很多了,內容主要爲如何接入OpenLDAP監控。

事情的背景時這樣的,我年中的時候入職了個初創公司,前陣子突然看到技術羣裏面有人反饋,OpenLDAP無法登錄,會影響業務。情況緊急相關同事快速重啓OpenLDAP容器服務解決了問題。這種狀況在小公司很常見,可能原來沒什麼服務接入,或者維護這個的人員早就提桶跑路了,或者沒什麼外部影響,重啓還真的可能是最快速有效的解決方式😂。

當天早上盲猜問題就是FD默認配置1024不夠了,維護的服務夠多的話,這種情況還是有不少的,歷史原因導致,無可非議,也許當場只有5個人使用,公司只打算開2年關門呢?

人和程序有一個能跑就行,恰巧你到的時候,不能跑又想高枕無憂,怎麼辦呢?接入監控吧。Google裏面輸入OpenLDAP監控,中文有效資料少得可憐,又到了填補空白的時候了。

監控系統現在選Prometheus很常見,功能易用,社區活躍,個人覺得比好多年前省事多了。

直白點,方案選用的Prometheus + openldap_exporter[https://github.com/tomcz/openldap_exporter]。可惜的是這個倉庫作者也歸檔不維護了,不過能用,有能力的Fork自己玩吧。

由於原來的OpenlLDAP是採用容器化方式部署的,接入監控有點麻煩,也是難點所在。容器倉庫爲:https://github.com/osixia/docker-openldap

1. 如何接入監控

建議自己線找個測試環境測試,進入容器後。

  • 載入監控模塊模塊
 1	root@xxxxxxx:/# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=module{0},cn=config"
 2	SASL/EXTERNAL authentication started
 3	SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 4	SASL SSF: 0
 5	# extended LDIF
 6	#
 7	# LDAPv3
 8	# base <cn=module{0},cn=config> with scope subtree
 9	# filter: (objectclass=*)
10	# requesting: ALL
11	#
12
13	# module{0}, config
14	dn: cn=module{0},cn=config
15	objectClass: olcModuleList
16	cn: module{0}
17	olcModulePath: /usr/lib/ldap
18	olcModuleLoad: {0}back_mdb
19	olcModuleLoad: {1}memberof
20	olcModuleLoad: {2}refint
21
22	# search result
23	search: 2
24	result: 0 Success
25
26	# numResponses: 2
27	# numEntries: 1
28	root@9e93cb7f031d:/# ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
29	> dn: cn=module{0},cn=config
30	> changetype: modify
31	> add: olcModuleLoad
32	> olcModuleLoad: back_monitor
33	> EOF
34	SASL/EXTERNAL authentication started
35	SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
36	SASL SSF: 0
37	modifying entry "cn=module{0},cn=config"
38
39	root@9e93cb7f031d:/# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=module{0},cn=config"
40	SASL/EXTERNAL authentication started
41	SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
42	SASL SSF: 0
43	# extended LDIF
44	#
45	# LDAPv3
46	# base <cn=module{0},cn=config> with scope subtree
47	# filter: (objectclass=*)
48	# requesting: ALL
49	#
50
51	# module{0}, config
52	dn: cn=module{0},cn=config
53	objectClass: olcModuleList
54	cn: module{0}
55	olcModulePath: /usr/lib/ldap
56	olcModuleLoad: {0}back_mdb
57	olcModuleLoad: {1}memberof
58	olcModuleLoad: {2}refint
59	olcModuleLoad: {3}back_monitor
60
61	# search result
62	search: 2
63	result: 0 Success
64
65	# numResponses: 2
66	# numEntries: 1

上面操作過程輸出確認,監控模塊已載入

  • 添加監控用戶

密碼部分我用xxx代替了,操作示例:

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

第一次顯示沒有權限,-w admin意爲使用管理原權限寫入

 1	root@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
 9	SASL/EXTERNAL authentication started
10	SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
11	SASL SSF: 0
12	adding new entry "cn=monitor,dc=example,dc=org"
13	ldap_add: Insufficient access (50)
14	        additional info: no write access to parent
15
16	root@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	adding new entry "cn=monitor,dc=example,dc=org"
  • 驗證新添加用戶讀取信息是否正常
1	root@9e93cb7f031d:/# ldapwhoami -x -D "cn=monitor,dc=example,dc=org" -w "your_password"
2	dn: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}to dn.subtree="cn=Monitor" by dn.base="cn=monitor,dc=example,dc=org" read by * none
6EOF
 1	root@9e93cb7f031d:/# ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
 2	dn: olcDatabase=Monitor,cn=config
 3	changetype: modify
 4	replace: olcAccess
 5	olcAccess: {0}to dn.subtree="cn=Monitor" by dn.base="cn=monitor,dc=example,dc=org" read by * none
 6	EOF
 7	SASL/EXTERNAL authentication started
 8	SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 9	SASL SSF: 0
10	modifying entry "olcDatabase=Monitor,cn=config"
11	ldap_modify: No such object (32)
12	        matched DN: cn=config

上面顯示不存在數據庫時的報錯,沒有數據庫直接修改肯定不行啦(存在:ldapmodify,不存在:ldapadd,合理沒毛病)

看起來很簡單是不是,倘若第一次接觸理解,上面的語句什麼意思都要理解半天,我就是看了很久官方文檔 + AI輔助 + 動手實踐。

2. 部署監控組件openldap_exporter

上述不是有個監控模塊嗎?怎麼這裏又有個監控組件。不一樣,上面的是服務端,這個是客戶端,用來讀取上面監控模塊的信息,再吐給Prometheus的,大概是這樣的鏈路:

Prometheus <--- openldap_exporter監控組件 <--- OpenLDAP server的監控模塊

這部分很簡單沒什麼好說的。看操作:

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

 如果監控組件 沒有正確顯示指標,就要耐心慢慢排查,先確認服務端沒有問題,再查看服務端日誌,甚至要讀監控組件的源碼,別問,我就是這樣過來的。讀者比我幸運,沒有中文用戶在我之前寫這些,反正沒搜到。

3. 接入Prometheus

簡單示例如下:

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

懶得截圖了。

4. 接入Grafana

監控面板還是很有用的,領導上級都很喜歡,你應該懂的。

很遺憾,目前社區沒什麼製作好的面板,我自己動手製作了一個。要的話,可以關注我微信公衆號,我發給你,真關注真發。

示例圖片見下面的壓測。

5. 壓測

上文提到初步判斷的是FD數目沒配置導致的問題,需要壓測驗證。

壓測程序放出來:

 1
 2import ldap
 3import time
 4
 5def main():
 6    connections = []
 7    target_connection_count = 1023
 8    try:
 9        while len(connections) < target_connection_count:
10            try:
11                # 嘗試連接到 localhost:389 上的 openldap 服務
12                conn = ldap.initialize("ldap://localhost:389")
13                conn.simple_bind_s("cn=admin,dc=example,dc=org", "admin")  # 請使用有效的管理員 DN 和密碼
14                connections.append(conn)
15                result = conn.search_s("dc=example,dc=org", ldap.SCOPE_SUBTREE)
16                print(result)
17                time.sleep(0.5)
18            except ldap.LDAPError as e:
19                print(f"LDAP error occurred: {e}")
20                break
21        while True:
22            # 保持程序運行,以保持佔用文件描述符
23            pass
24    except Exception as e:
25        print(f"An error occurred: {e}")
26    finally:
27        # 關閉所有創建的 LDAP 連接
28        for conn in connections:
29            try:
30                conn.unbind()
31            except ldap.LDAPError:
32                pass
33
34
35if __name__ == "__main__":
36    main()

sleep 控制連接建立的速度,可調整,或者去掉。注意,ldap包有幾個系統依賴的,不然安裝不上。

壓測結果圖:

openldap

最后修改于: Tuesday, February 4, 2025
欢迎关注微信公众号,留言交流。

相关文章: