LDAP 相關術語 === ###### tags: `LDAP` ###### tags: `LDAP`, `術語`, `DN`, `CN`, `Base DN`, `Bind DN` <br> [TOC] <br> ## 相關術語 | 術語 | en | 臺灣繁體中文 | 備註 | |-----|----|------------|-----| | **DN** | **Distinguished Name** | 辨別名稱(完整地址) | | RDN | Relative Distinguished Name | 相對辨別名稱(門牌號) | | OU | Organizational Unit | 組織單位 | | DC | Domain Component | 網域元件 | | **CN** | **Common Name** | 通用名稱(顯示名稱) | | uid | User Identifier | 使用者帳號 | | sn | Surname | 姓氏 | | givenName | Given Name | 名 | | mail | Email | 電子郵件 | | telephoneNumber | Telephone Number | 電話號碼 | | uidNumber | User ID Number | 使用者數值 ID | | gidNumber | Group ID Number | 群組數值 ID | | homeDirectory | Home Directory | 家目錄 | | loginShell | Login Shell | 登入 Shell | | objectClass | Object Class | 物件類別 | | attribute | Attribute | 屬性 | | entry | Entry | 條目(資料項) | | DIT | Directory Information Tree | 目錄資訊樹 | | **Base DN** | **Base Distinguished Name** | 基底 DN(搜尋起點) | | Bind | Bind (authenticate) | 綁定(登入驗證) | | **Bind DN** | **Bind Distinguished Name** | 綁定 DN(登入用辨別名稱) | | Search | Search | 搜尋 | | Filter | Filter | 篩選條件 | | LDIF | LDAP Data Interchange Format | 目錄資料交換格式 | | Schema | Schema | 綱要(結構定義) | | TLS | Transport Layer Security | 傳輸層安全性 | | StartTLS | StartTLS | 升級為 TLS 的機制 | | LDAPS | LDAP over SSL/TLS | 輕量級目錄存取協定(LDAP) 的安全版本 | 它使用 SSL/TLS 加密保護LDAP 通訊,確保傳輸過程中資料的機密性和完整性。 | inetOrgPerson | inetOrgPerson | 網際網路組織人員(物件類別) | | posixAccount | posixAccount | POSIX 帳號(物件類別) | | posixGroup | posixGroup | POSIX 群組(物件類別) | | groupOfNames | groupOfNames | 名稱群組(物件類別) | | person | person | 人員(物件類別) | | organizationalPerson | organizationalPerson | 組織人員(物件類別) | | organizationalUnit | organizationalUnit | 組織單位(物件類別) | | organization | organization | 組織(物件類別) | | dcObject | dcObject | 網域元件物件(物件類別) | | top | top | 最上層/基礎(物件類別) | | memberUid | Member UID | 成員帳號(屬性) | | **olc** | **O**pen**L**DAP **C**onfiguration | **OpenLDAP 動態設定**(`cn=config`) | `olc-` 是一組屬性的前綴,專屬於動態設定(back-config)。 | | **olcDatabase** | (olc) **database identifier / type** | **OpenLDAP 動態設定中的資料庫識別/類型屬性** | 不是「一座資料庫」本身,而是資料庫**節點的屬性/RDN**,用來標識該資料庫的**後端類型**與**序號**。 | <br> ### olc & olcDatabase - `olc` 確實可視為 *OpenLDAP Configuration* 的縮寫,用在 `cn=config` 架構裡的屬性名稱前綴(如 `olcSuffix`, `olcRootDN`, `olcAccess` 等)。 - `olcDatabase` 並不是正式英文長名的「縮寫」;它是 **屬性名稱**,語意是「(olc 的)Database」。作用是**辨識/宣告**一個資料庫設定節點使用的**後端**(例如 `mdb`, `hdb`, `monitor`, `config`, `frontend`)。 - ### 範例說明 ```ldif dn: olcDatabase={2}mdb,cn=config objectClass: olcDatabaseConfig olcDatabase: mdb olcSuffix: dc=example,dc=org olcRootDN: cn=admin,dc=example,dc=org ``` * `dn` 中的 `olcDatabase={2}mdb`:`{2}` 是此資料庫設定條目的索引;`mdb` 是後端類型。 * `olcDatabase: mdb`:同樣指明該資料庫使用 **mdb** 後端。 * 常見特殊資料庫:`{-1}frontend`、`{0}config`、`{1}monitor` …… > 你原表的意思是對的;只要把「OpenLDAP 動態設定**資料庫**」微調為「**動態設定中的資料庫識別/類型屬性**」就更精準。 <br> ## 討論 ### 簡單解釋 LDAP術語 - ### Question LDAP 提到很多術語: - dn - ou - dc - cn - ... 用最簡單、小學生能懂的方式解釋? - ### gpt-5 (2025/09/01) 當 LDAP 在講話時,可以把它想像成「一棟超大的檔案圖書館」📚 每一張卡片=一個人/一個群組/一台機器(叫做 *entry*),卡片上有很多欄位(*attributes*),而「卡片放在架上的位置」就是它的地址(*DN*)。 下面用「地址」的比喻,超白話帶你一次懂最常見的術語: ### 最常用的幾個 * **DN (Distinguished Name)**:**完整地址**。告訴你「這張卡片」在大樓哪一層、哪一櫃、哪一格。 例:`uid=tj,ou=people,dc=example,dc=org` * **RDN (Relative DN)**:**門牌號**。就是 DN 的最前面那段,描述卡片自己的名稱。 例:`uid=tj`、或有時是 `cn=Tony` * **OU (Organizational Unit)**:**樓層/部門**。用來分區分類。 例:`ou=people`、`ou=groups` * **DC (Domain Component)**:**網站網域拆開的每一段**。 例1:`example.org` 會寫成 `dc=example,dc=org` 例2:`www.google.com` 會寫成 `dc=www,dc=google,dc=com` (額外補充) * **CN (Common Name)**:**看得懂的人名/顯示名稱**。 例:`cn=Tony Jiang`(和登入帳號不同喔) ### 會常看到的欄位(放在卡片上的資訊) * **uid**:**登入帳號**(像 `tj`)。 * **sn / givenName**:**姓 / 名**(sn=surname 姓、givenName=名)。 * **mail**:**電子郵件**。 * **telephoneNumber**:**電話**。 * **uidNumber / gidNumber**:**數字版的使用者ID/群組ID**(作業系統用的,像 1001、100)。 * **homeDirectory / loginShell**:**家目錄 / 預設 Shell**(整合 Linux 帳號時會用到)。 ### 卡片的種類與規矩 * **objectClass**:**卡片樣板(規格)**。決定這張卡片「必須/可以有」哪些欄位。 例:`inetOrgPerson`(一般人員)、`posixAccount`(Linux 帳號)、`groupOfNames`(群組)。 * **attribute**:**欄位**(像 `mail`、`uidNumber` 都是 attribute)。 * **entry**:**卡片本體**(一筆資料)。 ### 資料怎麼擺、怎麼找 * **DIT (Directory Information Tree)**:**整棵檔案樹**。大樓的樓層/櫃位結構。 * **Base DN**:**你要開始找的「起點樓層」**。 例:`dc=example,dc=org` * **Bind**:**登入**(先表明你是誰,像管理員或一般用戶)。 * **Bind DN**:登入時使用的**帳號地址**(通常是一串 DN)。 * **Search / Filter**:**搜尋 / 篩選條件**。 例:在 `ou=people,dc=example,dc=org` 裡找 `uid=tj` 或 `mail=*@example.org` ### 檔案與安全 * **LDIF**:**純文字交換格式**,用來匯入/匯出 LDAP 卡片。 例: ``` dn: uid=tj,ou=people,dc=example,dc=org objectClass: inetOrgPerson objectClass: posixAccount uid: tj cn: Tsung-Jung Tsai sn: Tsai givenName: Tsung-Jung uidNumber: 1001 gidNumber: 100 homeDirectory: /home/tj loginShell: /bin/bash mail: tj@example.org ``` * **Schema**:**校規**。定義有哪些 objectClass、每個欄位怎麼用。 * **TLS/StartTLS**:**加密通道**(讓登入與查詢不被偷聽)。 --- ### 一眼看懂 DN:拆解範例 ``` uid=tj,ou=people,dc=lab,dc=example,dc=com │ │ └────────────── 網域 lab.example.com → dc=lab,dc=example,dc=com │ └──────────────────────── 部門/樓層:people └────────────────────────────── 門牌號(這張卡片):uid=tj ``` --- ### 小抄:名稱 → 記法 * **人名**:`cn=Tsung-Jung Tsai`(顯示用) * **帳號**:`uid=tj`(登入用) * **部門**:`ou=people`、`ou=groups` * **公司網域**:`dc=example,dc=org` * **完整地址(DN)**:`uid=tj,ou=people,dc=example,dc=org` --- ### 10 秒自我測驗 看懂這串了嗎? `cn=Alice Chen,ou=groups,dc=school,dc=tw` * 門牌號:`cn=Alice Chen` * 樓層:`ou=groups` * 網域:`school.tw` → `dc=school,dc=tw` * 這是誰?一張叫「Alice Chen」的卡片,放在 groups 這層下面。 --- ### 和你要做的事有關(整合 Linux/Slurm 常見) * 人員:`objectClass: inetOrgPerson, posixAccount` * 必備欄位:`uid`、`uidNumber`、`gidNumber`、`homeDirectory`、`loginShell` * 群組:`objectClass: posixGroup`,欄位:`cn`(群組名)、`gidNumber`、`memberUid`(成員帳號) --- 想不想我幫你把「你們的 LDAP 樹」用你要的部門/群組/使用者,直接畫成範本(含 Base DN、OU 規劃、範例 DN 與 LDIF)?你只要告訴我預計的網域(例如 `dc=yourlab,dc=org`)就行。 <br> ### 建立 slurm 的 LDAP 範本 - ### Question 根據底下資訊: - 5glab (IP: 50.111.105.78) - partition: tn - user: tj_tsai - uid=20001 - Name: Tsung-Jung Tsai 建立 slurm 的 LDAP 範本 - ### gpt-5 (2025/09/01) 太好了!我用你給的資訊做一份「能直接用的 LDAP 範本 + Slurm 對應」。 (以下先用 `dc=5glab,dc=local` 當作你的 LDAP 根;若你有正式網域,改成 `dc=example,dc=org` 之類即可。) ### 一、DIT 規劃(像大樓樓層) * Base DN:`dc=5glab,dc=local` * OU: * `ou=people`(人員/帳號) * `ou=groups`(群組) * (可選)`ou=service`、`ou=policies` 以後要再加也行 ### 二、命名與 ID 建議 * 使用者: * `uid=tj_tsai`(你提供) * `uidNumber=20001`(你提供) * 群組(對應 Slurm partition: `tn`): * 群組名:`cn=tn` * `gidNumber=30001`(我幫你挑一個不跟系統衝突的數字;可改) --- ### 三、一次建立的 LDIF(base + OU + 群組 + 使用者) 把下面內容存成 `5glab-init.ldif`(把 `{SSHA}...` 換成你實際的密碼雜湊;做法在下個段落)。 ```ldif # 1) Base dn: dc=5glab,dc=local objectClass: top objectClass: dcObject objectClass: organization o: 5glab dc: 5glab # 2) OUs dn: ou=people,dc=5glab,dc=local objectClass: top objectClass: organizationalUnit ou: people dn: ou=groups,dc=5glab,dc=local objectClass: top objectClass: organizationalUnit ou: groups # 3) Group: tn (對應 Slurm partition: tn) dn: cn=tn,ou=groups,dc=5glab,dc=local objectClass: top objectClass: posixGroup cn: tn gidNumber: 30001 memberUid: tj_tsai # 4) User: tj_tsai dn: uid=tj_tsai,ou=people,dc=5glab,dc=local objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount cn: Tsung-Jung Tsai sn: Tsai givenName: Tsung-Jung uid: tj_tsai uidNumber: 20001 gidNumber: 30001 homeDirectory: /home/tj_tsai loginShell: /bin/bash mail: tj_tsai@5glab.local # 將下一行替換成你用 slappasswd 產生的密碼雜湊 userPassword: {SSHA}REPLACE_ME ``` #### 產生密碼雜湊(選一種) ```bash # Ubuntu/Debian 常見 slappasswd -h {SSHA} -s '你的密碼' # 輸出形如:{SSHA}nknh2... 把整串貼到 LDIF 的 userPassword ``` #### 匯入(假設 LDAP 在 50.111.105.78) ```bash ldapadd -H ldap://50.111.105.78 \ -D "cn=admin,dc=5glab,dc=local" -W \ -f 5glab-init.ldif ``` #### 快速檢查 ```bash ldapsearch -x -H ldap://50.111.105.78 -b "dc=5glab,dc=local" uid=tj_tsai ldapsearch -x -H ldap://50.111.105.78 -b "dc=5glab,dc=local" cn=tn ``` --- ### 四、Linux 節點(含 Slurm login/compute)連到 LDAP(SSSD) > 目標:`id tj_tsai` 能看到 `uid=20001 gid=30001 groups=30001(tn)` 1. #### 安裝(Ubuntu) ```bash sudo apt update sudo apt install -y sssd sssd-ldap libnss-sss libpam-sss ``` 2. #### 建立 `/etc/sssd/sssd.conf`(權限 600) ```ini [sssd] services = nss, pam domains = 5glab [domain/5glab] id_provider = ldap auth_provider = ldap chpass_provider = ldap ldap_uri = ldap://50.111.105.78 ldap_search_base = dc=5glab,dc=local # 建議啟用加密(若你有 TLS/CA) # ldap_id_use_start_tls = true # ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt cache_credentials = true enumerate = false ``` ```bash sudo chmod 600 /etc/sssd/sssd.conf sudo systemctl enable --now sssd ``` 3. #### `/etc/nsswitch.conf` 加上 `sss` ``` # diff -passwd: files systemd -group: files systemd +passwd: files sss systemd +group: files sss systemd ``` 4. #### 測試 ```bash getent passwd tj_tsai id tj_tsai ``` 若正常,會顯示 `uid=20001 gid=30001(tn)`。 --- ### 五、Slurm 對應(把群組 tn 綁到 partition=tn) 在你的 `slurm.conf` 的 `PartitionName=tn` 區塊加入: ```conf PartitionName=tn Nodes=<你的節點> Default=NO MaxTime=INFINITE State=UP AllowGroups=tn ``` 套用: ```bash scontrol reconfigure ``` > 重點:Slurm 會用 **作業系統的群組** 來判斷允許誰進入某個 partition,所以 LDAP 必須先讓所有節點能解析 `group tn` 與使用者成員。 --- ### 六、以後要「動態新增人員」怎麼做? #### 新增使用者 `alice`(範本) ```ldif dn: uid=alice,ou=people,dc=5glab,dc=local objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount cn: Alice Chen sn: Chen givenName: Alice uid: alice uidNumber: 20002 gidNumber: 30001 homeDirectory: /home/alice loginShell: /bin/bash mail: alice@5glab.local userPassword: {SSHA}REPLACE_ME ``` 匯入: ```bash ldapadd -H ldap://50.111.105.78 -D "cn=admin,dc=5glab,dc=local" -W -f add-alice.ldif ``` (因為 `gidNumber=30001`,她自動就屬於 `tn` 群組。如果你用 `memberUid` 維護群組成員,也可以用 `ldapmodify` 往 `cn=tn` 加一行 `memberUid: alice`。) --- ### 七、把名詞再白話對照一次 * **DN**:完整地址(例:`uid=tj_tsai,ou=people,dc=5glab,dc=local`) * **OU**:樓層/分類(people、groups) * **DC**:網域每一段(5glab.local → `dc=5glab,dc=local`) * **CN**:顯示名稱(例:`cn=Tsung-Jung Tsai`) * **uid/gidNumber**:數字版使用者/群組 ID(OS 用) * **posixAccount/posixGroup**:Linux 會認得的帳號/群組規格 --- 需要我把上面檔案分成好幾個 `.ldif` 小檔,或幫你產生 `sssd.conf` 成品,直接拷上去就能測嗎?你也可以告訴我是否要把 Base DN 改成你的正式網域,我幫你一次換好。 <br> --- ### 為何一個 entry 會有多個 LDAP 物件類別? - ### Question ```ldif dn: uid=alice,ou=people,dc=5glab,dc=local objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount ... ``` 中間為何有多個 objectClass? - ### gpt-5 (2025/09/01) 超可以理解你卡關的點!那串 `objectClass` 為什麼要一次放好幾個?關鍵在於:**每個 objectClass 就像是一塊功能積木**,疊起來後,這張 LDAP「卡片」(entry)就同時具備多種欄位與能力。下面把原理拆得很白話,再對照你那段範例逐一解釋。 --- ### 為什麼一個 entry 會有多個 objectClass? 把 LDAP 想成「貼有許可證的表單」: * **objectClass = 這張表單拿到的許可證** 每張許可證都**規定**: * 必填哪些欄位(**MUST**) * 可選哪些欄位(**MAY**) 一張 entry 可以**同時拿多張許可證**,因此你會看到很多個 `objectClass`。這樣做的好處是: * 你可以同時擁有「人員聯絡資訊」的欄位(如 `mail`、`givenName`), * 又能擁有「Linux 登入帳號」需要的欄位(如 `uidNumber`、`gidNumber`、`homeDirectory`、`loginShell`)。 --- ### 三種 objectClass 型別(觀念一定要有) 1. **Abstract(抽象)**:最基礎的祖先,像骨架。典型是 `top`。 2. **Structural(結構)**:決定「這張卡片是什麼類型」。**每個 entry 只有一條“最專門”的結構類別血統**(會沿著繼承鏈包含祖先)。 3. **Auxiliary(附加)**:加功能的外掛,補上額外欄位(例如讓條目同時變成可登入的 Unix 帳號)。 > 重點:**一張 entry 最終只有一個「最專門的 Structural 類別」**(例如 `inetOrgPerson`), > 其他再用 **Auxiliary** 類別(例如 `posixAccount`)加功能。`top` 與各層祖先類別常會一併列出(有的伺服器會自動補,寫出來更相容、也好讀)。 --- ### 逐一解釋你範例中的每個 objectClass 你貼的使用者條目: ``` objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount ``` * **top(Abstract)** * 全部類別的老祖宗;幾乎所有條目都會繼承它。 * **person(Structural,繼承 top)** * 規定你至少要有:`cn`(名字/顯示名)、`sn`(姓氏)。 * 常見可選:`telephoneNumber`、`userPassword`…等。 * **organizationalPerson(Structural,繼承 person)** * 加上一些組織內的人員欄位(如 `title`、`ou`、地址…),讓「人」更像在公司裡的職員。 * **inetOrgPerson(Structural,繼承 organizationalPerson)** ← **最專門的結構類別** * 企業最常用的人員類別;支援 `mail`、`givenName`、`displayName` 等現代通訊欄位。 * 也要求有 `sn`、`cn`(它的祖先已經要求了)。 * **posixAccount(通常是 Auxiliary,在常見的 OpenLDAP/RFC2307bis 佈署裡)** * 給條目附加「Linux/Unix 帳號」能力: * 常見 **MUST**:`uidNumber`、`gidNumber`、`homeDirectory`、(不少實務也要求 `uid`) * 常見 **MAY**:`loginShell`、`gecos`、`userPassword`… * 有了它,`id tj_tsai` 這類系統指令才知道該用哪個數字 UID/GID、家目錄在哪、預設 shell 是什麼。 > 小結:**`inetOrgPerson` 讓他像「公司的人」;`posixAccount` 讓他能「登入 Linux」**。兩個一起用,就同時滿足通訊錄與作業系統的需求。 --- ### 為什麼同時寫 `person`、`organizationalPerson`、`inetOrgPerson`? 因為 `inetOrgPerson → organizationalPerson → person → top` 是**繼承鏈**。 有些伺服器會自動把祖先類別也加進條目;有些則要求你**明確列出**整條鏈。 **把它們都寫出來**有幾個好處: * 相容性較佳(不同 LDAP 伺服器/工具都不會誤會) * 人類一眼就能看懂這條目的定位與能力來源 --- ### 迷你對照表(記一下就通了) | 類別 | 型別 | 作用重點 | 常見 MUST(至少要有) | 常見 MAY(可選) | | -------------------- | ------------- | ------------- | ---------------------------------------------------- | ------------------------------------------ | | top | Abstract | 祖先骨架 | — | — | | person | Structural | 基本人員 | `cn`、`sn` | `telephoneNumber`、`userPassword`… | | organizationalPerson | Structural | 公司人員欄位 | (承襲 `person` 的 MUST) | `title`、`ou`、地址相關… | | inetOrgPerson | Structural | 現代人員/聯絡資料 | (仍需 `sn`、`cn`) | `givenName`、`displayName`、`mail`、`mobile`… | | posixAccount | Auxiliary(常見) | Linux/Unix 帳號 | `uidNumber`、`gidNumber`、`homeDirectory`(多半也需要 `uid`) | `loginShell`、`gecos`、`userPassword`… | > 注意:`posixAccount` 在不同 schema 版本可能被定義成 **AUXILIARY** 或 **STRUCTURAL**。 > 在常見的 OpenLDAP + RFC2307bis 佈署裡是 **AUXILIARY**,因此能與 `inetOrgPerson`(STRUCTURAL)自然共存。 > 若你的環境把 `posixAccount` 當 STRUCTURAL,就**不能**和 `inetOrgPerson` 同時當結構類別;解法是改用 RFC2307bis(把 `posixAccount` 規劃為 AUXILIARY)或改走 `account` 分支。你目前這種寫法通常表示你用的是 AUX 版本,正確 👍。 --- ### 「最小可行」與「完整明白」兩種寫法 #### A. 最小可行(伺服器會自動補祖先) ```ldif dn: uid=tj_tsai,ou=people,dc=5glab,dc=local objectClass: inetOrgPerson objectClass: posixAccount cn: Tsung-Jung Tsai sn: Tsai uid: tj_tsai uidNumber: 20001 gidNumber: 30001 homeDirectory: /home/tj_tsai loginShell: /bin/bash mail: tj_tsai@5glab.local userPassword: {SSHA}... ``` #### B. 完整明白(把繼承鏈寫全,最不易踩雷) ```ldif dn: uid=tj_tsai,ou=people,dc=5glab,dc=local objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson # ← 唯一“最專門”的 Structural objectClass: posixAccount # ← Auxiliary 外掛 cn: Tsung-Jung Tsai sn: Tsai uid: tj_tsai uidNumber: 20001 gidNumber: 30001 homeDirectory: /home/tj_tsai loginShell: /bin/bash mail: tj_tsai@5glab.local userPassword: {SSHA}... ``` --- ### 常見錯誤&如何自救 * **`object class violation`(65)** 代表你漏了某個類別的 **MUST** 欄位,或加了不屬於任何已宣告類別的欄位。 → 對照上面表格,把 MUST 補齊;或加上對應的 Auxiliary 類別。 * **`invalid structural class` / 不能混兩個 Structural** 比如(在你的 schema 裡)`inetOrgPerson` 和 `posixAccount` 同為 Structural,就衝突了。 → 換用 RFC2307bis(讓 `posixAccount` 為 AUXILIARY),或選擇 `account` 分支而非 `inetOrgPerson`。 --- ### 想查「到底 MUST/MAY 是什麼」? 你可以直接問伺服器的 schema(以 OpenLDAP 為例): ```bash ldapsearch -LLL -x -H ldap://50.111.105.78 -b "cn=subschema" \ "(objectClass=*)" objectClasses | less ``` 找到 `NAME 'inetOrgPerson'`、`NAME 'posixAccount'` 等段落,就能看到它們的 MUST/MAY 定義。 --- 如果你願意,我可以用你現在的伺服器實測一下 schema(你貼回 `ldapsearch` 的 schema 片段),我就能**精準**標出你環境裡各類別的 MUST/MAY 與型別(Structural/Auxiliary),再把你的 LDIF 調到 100% 合規、最不會踩雷的版本。 <br> --- ### LDAP 物件類別解釋:inetOrgPerson & posixAccount - ### Question inetOrgPerson: internet organization person 網際網路組織人員? posixAccount: ? - ### gpt-5 (2025/09/01) 下面用最實用、工程師看得懂的方式說明兩個 LDAP 物件類別(objectClass): | 術語 | en | 臺灣繁體中文(建議用語) | 是哪種類別 | |-----|-----|---------------------|----------| | inetOrgPerson | Internet Organizational Person(RFC 2798) | 「通訊錄人員」/「組織成員(含聯絡資訊)」 | **Structural** | | posixAccount | POSIX Account(RFC 2307)| 「可登入 UNIX 的帳號屬性」 | **Auxiliary** | ### 怎麼理解? * **inetOrgPerson**:用來描述「人」這個實體的聯絡與身分資訊(例如 `cn`, `sn`, `mail`, `givenName`, `displayName`, `telephoneNumber`, `uid` 等)。常見於企業通訊錄或身分目錄。 * **MUST**:`sn`, `cn` * sn=surname:姓 * cn=common name:常用名/顯示名稱(多半是全名),意思是「大家用來稱呼的名稱」。可以是全名、暱稱或帶職稱的展示字串,但務必穩定、可辨識。 * **MAY(常用)**:`mail`, `givenName`, `displayName`, `telephoneNumber`, `uid`, `userPassword`, `jpegPhoto` …(依實作而異) * **posixAccount**:在「人」的基礎上,加上能讓 UNIX/Linux 系統辨識並允許登入的欄位(相當於 `/etc/passwd` 的那些欄位)。通常**疊加在** `inetOrgPerson` 上。 * **MUST**:`cn`, `uid`, `uidNumber`, `gidNumber`, `homeDirectory` * **MAY(常用)**:`loginShell`, `gecos`, `userPassword`, `description` ### 為什麼一個條目會有多個 objectClass? * LDAP 讓你把「**身分/通訊錄**」(`inetOrgPerson`,**Structural**)與「**UNIX 登入**」(`posixAccount`,**Auxiliary**)合在同一筆條目。 * 一個條目**實務上會有一個 Structural**(例如 `inetOrgPerson`,上面還會列出它的父類 `organizationalPerson`、`person`、`top`),再加上**零到多個 Auxiliary**(例如 `posixAccount`、`shadowAccount`)。 * 好處:同一筆人員資料,同時能當聯絡人、也能被機器當作可登入帳號使用。 ### 最常見的欄位對照(posixAccount ↔ `/etc/passwd`) * `uid` → 登入名稱(login name) * `uidNumber` → UID * `gidNumber` → GID * `gecos` → 備註/全名欄(GECOS) * `homeDirectory` → 家目錄 * `loginShell` → 登入 Shell * `userPassword` → 密碼雜湊(如 `{SSHA}`, `{CRYPT}`…) ### 範例 LDIF(把兩者一起用) ```ldif dn: uid=tj,ou=People,dc=example,dc=com objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount cn: Tsung-Jung Tsai sn: Tsai uid: tj mail: tj@example.com uidNumber: 20001 gidNumber: 100 homeDirectory: /home/tj loginShell: /bin/bash userPassword: {SSHA}xxxx... # 範例,實務請放安全雜湊 ``` > 小結: > > * **inetOrgPerson**:把人當作「通訊錄成員」。 > * **posixAccount**:把同一個人加上「可以登入 UNIX 的欄位」。 > * 兩者一起用,就能同時管聯絡資訊與系統登入權限。 <br> ### 設定裡有 {0},{1},{2},是什麼意思? - ### gpt-5 (2025/09/12) 簡單說:**`{0},{1},{2}` 是在 `cn=config` 下給「同一層兄弟節點」編的**「順序索引」。 它沒有特別語義,只是用來**確保 DN 唯一、固定排序**,也方便你之後新增 `{3}`、`{4}`⋯而不撞名。 ### 在 OpenLDAP 裡常見的幾個例子 * `olcDatabase={0}config,cn=config` → 管理整個 slapd 設定的「配置資料庫」(suffix 是 `cn=config`)。 * `olcDatabase={1}monitor,cn=config`(有些發行版在 {1}) → 監控資料庫(suffix `cn=Monitor`)。 * `olcDatabase={2}mdb,cn=config` → 你的第一個實際「資料庫」(例如 `dc=esc4000,dc=ocis,dc=asus,dc=com`)。 若再新增一顆,就會是 `{3}mdb`、`{4}mdb`⋯ * 在某一顆資料庫底下,**overlays** 也會有自己的編號,例如 `dn: olcOverlay={0}memberof,olcDatabase={2}mdb,cn=config` > 重點:數字「只表示建立順序」,不代表權限高低或功能差異;**不要任意改號或改 DN**,除非你非常確定。 ### 為什麼需要這些數字? 因為在 `cn=config` 下,同一層有很多條目都叫 `olcDatabase=mdb` 或 `olcOverlay=memberof`,若不加編號 DN 會重複。用 `{N}` 讓每個 DN 唯一,順序也穩定。 ### 我怎麼知道現在有哪些編號可用? 用 root 在主機上查: ```bash # 列出所有資料庫(看現有 {N}) ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config '(olcDatabase=*)' olcDatabase olcSuffix # 只列 mdb 類型 ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config '(&(objectClass=olcMdbConfig)(olcSuffix=*))' olcDatabase olcSuffix olcDbDirectory ``` 看見已有 `{0},{1},{2}`,下一個就用 **`{3}`**;中間有缺號也沒關係(例如刪掉過 `{1}` 產生空洞)。 ### 補充小提醒 * `frontend` 與 `config` 是特殊資料庫,常見會看到 `olcDatabase={-1}frontend`、`{0}config`(不同發行版顯示略有差異)。 * 跟「選哪顆資料庫處理請求」相關的主要規則是 **最長 suffix 匹配**,不是 `{N}` 大小。 * 對 `cn=config` 動手要用 **SASL/EXTERNAL + ldapi:///**(或事先設定 `cn=config` 的 rootDN/rootPW)。 若你要新增一顆 `dc=asus,dc=com`,只要挑一個**沒用過的 `{N}`**(例如 `{3}`)來建立 `olcDatabase={3}mdb,cn=config` 就行了。 <br> --- ### 連線埠:`389/tcp`(LDAP,支援 StartTLS 升級) vs `636/tcp`(LDAPS) - ### gpt-5 (2025/09/19) 以下重點版,超好記: * **389/tcp = LDAP(可升級加密)** 連線一開始是一般 LDAP;**用 `StartTLS` 指令升級成 TLS**。若**沒執行 StartTLS**,就是明文(不安全)。 * **636/tcp = LDAPS(預設就加密)** 一連上就進入 **TLS**(俗稱「LDAP over SSL/TLS」),**不需要再下 StartTLS**。 ### 差異總表 | 項目 | 389 (LDAP + StartTLS) | 636 (LDAPS) | | --- | ---------------------- | ------------ | | 加密啟動方式 | 先明文握手,再發 **StartTLS** 升級 | 一連上就在 **TLS** 通道 | | 需要額外指令 | 需要(例如 `-ZZ`)| 不需要 | | 風險 | 客戶端忘了升級→可能變明文 | 一律加密,無遺漏 | | 防火牆與埠口 | 用**同一個埠**服務明文與加密(管理較單純)| 需要**額外開 636** | | 標準與相容性 | IETF 偏好;現代實務常見 | 歷史悠久、相容性也很普遍 | | 伺服器端管控 | 可**強制要求 StartTLS**、拒絕明文綁定 | 天生強制加密 | ### 指令怎麼下 * **用 389 並啟用加密(StartTLS)** ```bash ldapsearch -x -H ldap://server.example.com:389 -ZZ -b "dc=example,dc=com" "(objectClass=*)" ``` * `-ZZ` = 要求 StartTLS。沒有 `-ZZ` 就是明文,請避免。 * **用 636(LDAPS)** ```bash ldapsearch -x -H ldaps://server.example.com:636 -b "dc=example,dc=com" "(objectClass=*)" ``` ### 什麼時候用哪個? * **新部署或能控制用戶端行為**:多數人會選 **389 + 強制 StartTLS**(標準、單埠管理)。 前提是你在伺服器上**禁止未加密的 simple bind**,確保客戶端一定要升級。 * **環境複雜或有舊客戶端/代理設備破壞 StartTLS**:選 **636**,省掉「是否升級」的顧慮。 ### 小叮嚀(實務安全) 1. **不要在 389 做明文 simple bind**(除非是測試網段而且確定無敏感資料)。 2. 無論 389/636,都要準備**正確的伺服器憑證**與**可信任 CA**;客戶端要能驗證憑證鏈。 3. 若是 Active Directory,也建議**啟用 LDAP 簽章與通道繫結(channel binding)**,能避免中間人攻擊(進階加固)。 一句話總結: **389 要記得用 `StartTLS`(或在伺服器強制它);636 一律加密、較直覺。兩者都安全,關鍵在你的政策與管控。** <br> --- ### X.500 模型是什麼? - ### gpt-5 (2025/09/19) 下面用**速懂版 → 對照版 → 範例**帶你掌握 X.500 模型。 ### 速懂版 **X.500** 是一組(ITU-T/ISO)標準,定義「目錄服務」的**資料怎麼長、怎麼命名、能做哪些操作、怎麼保護安全**。它把目錄分成四個互補模型: 1. **資訊模型**:目錄裡有 **entry(條目)**,每個 entry 由多個 **attribute(屬性)** 組成,且符合一或多個 **objectClass(物件類別)**(由 **schema** 規範)。 2. **命名模型**:用樹狀的 **DIT(Directory Information Tree)** 來組織資料;每個節點用 **RDN** 命名,整條路徑叫 **DN**。 3. **功能模型**:定義能做的操作,如 **bind、search、add、delete、modify、modifyDN、compa##re**。 4. **安全模型**:認證、授權(ACL)、完整性與機密性(簽章/加密)等。 配角與角色: * **DUA(Directory User Agent)**:用戶端/應用程式(如 `ldapsearch`、SSSD、你的程式碼)。 * **DSA(Directory System Agent)**:目錄伺服器(如 **OpenLDAP**、**389 DS**、**Active Directory**)。 * **DAP vs LDAP**:X.500 原生協定是 **DAP**(走 OSI 協定疊),後來出現更輕量、跑 TCP/IP 的 **LDAP**;語意幾乎對應,但 LDAP 更實用、普及。 --- ### 與 LDAP 的對照(實務觀點) | X.500 概念 | 與 LDAP 的對應/你在現場怎麼看 | | ---------| --------------------------- | | 資訊模型(entry/attribute/objectClass/schema) | 就是你在 OpenLDAP/AD 看到的 **條目**、**屬性**、**物件類別**(`person`、`inetOrgPerson`…)與 **schema**(`cosine.schema`、`inetorgperson.schema`…)。 | | 命名模型(DIT、RDN、DN) | 你設定的 **樹根與分支**(例如 `dc=example,dc=com`),每個 entry 有唯一 **DN**,父節點下 **RDN** 唯一。 | | 功能模型(search, add…) | LDAP 的 CRUD 與查詢操作(`ldapsearch/ldapadd/ldapmodify` 等)就是對應的實作。 | | 安全模型 | LDAP 以 **SASL / TLS(389+StartTLS 或 636)**、**ACL** 來落實;AD 還會配 **Kerberos、簽章與通道繫結**。 | | DUA | 你的客戶端:`ldapsearch`、PAM/SSSD、應用程式的 LDAP 驅動。 | | DSA | 你的伺服器:`slapd`(OpenLDAP)、389 DS、AD DS。 | | DAP | 幾乎不會在現代環境用;改用 **LDAP**。 | --- ### 小範例(把四大模型串起來) #### 1) 命名與資訊 * **樹根(naming context / suffix)**:`dc=example,dc=com` * **一個人員條目 DN**: `uid=tj,ou=users,dc=example,dc=com` * **RDN** 是 `uid=tj`,其餘是父路徑。 * **objectClass** 可能是:`inetOrgPerson`, `posixAccount`, `shadowAccount` * **屬性**(節選): ``` cn: Tsung-Jung Tsai sn: Tsai uid: tj uidNumber: 20001 gidNumber: 10001 mail: tj@example.com homeDirectory: /home/tj ``` #### 2) 功能操作(LDAP 命令對應) * 查詢(功能模型 → LDAP `search`) ```bash ldapsearch -x -H ldap://ldap.example.com -b "dc=example,dc=com" \ "(uid=tj)" cn uidNumber gidNumber ``` * 新增(功能模型 → LDAP `add`) ```ldif dn: uid=tj,ou=users,dc=example,dc=com objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount cn: Tsung-Jung Tsai sn: Tsai uid: tj uidNumber: 20001 gidNumber: 10001 homeDirectory: /home/tj loginShell: /bin/bash userPassword: {SSHA}... # 實務請用雜湊 ``` * 重新命名/搬家(功能模型 → LDAP `modifyDN`):變更 RDN 或把使用者搬到另一個 OU。 #### 3) 安全 * **389 + StartTLS** 或 **636(LDAPS)**,並設定伺服器憑證與 **ACL**(誰可讀/寫哪些屬性)。 * 在 AD,建議開啟 **LDAP 簽章**與**通道繫結**;在 OpenLDAP/389 DS,善用 **access control** 與 **強制 TLS**。 --- ### 分散式與委派(為何目錄能「長很大」) 多個 **DSA** 可共同承載同一顆邏輯 DIT: 某一段子樹(如 `ou=people,dc=example,dc=com`)可由另一台 DSA 管,主 DSA 收到查詢會轉介(referral)或連鎖(chaining)過去。這正是 X.500 設計的**分散式目錄**概念。 ``` [DUA] ---> [DSA A: dc=example,dc=com] |--(referral)--> [DSA B: ou=people,...] ``` --- ### 簡要結論 **X.500 模型 = 目錄服務的「通用藍圖」**: * 用 **資訊/命名** 規定資料長相與定位, * 用 **功能** 定義能做什麼操作, * 用 **安全** 保證存取控制與通訊防護。 **LDAP** 則是把這個藍圖用 TCP/IP 的方式「輕量化實作」出來,你日常在 OpenLDAP/AD 看到的一切,幾乎都能在 X.500 模型中找到對應。 <br> --- ### LDAP vs 目錄伺服器 vs 資料庫 - ### Queestion 我想要做投影片: - **LDAP:Lightweight Directory Access Protocol,輕型目錄存取協定** - LDAP 是「協定」不是「服務」 - **LDAP 是一種開放標準的目錄服務協定,用於存取和管理目錄資訊。** - LDAP 被用來做集中式帳號管理,扮演身分資料庫 這邊很困惑,LDAP 是「協定」不是「服務」,既然不是服務,又為何是資料庫? - ### gpt-5 (2025/09/19) 超精準版結論:**LDAP 是「通訊協定」;提供目錄的叫「目錄伺服器(服務)」;而「資料庫」是伺服器裡的儲存層**。 你聽到「LDAP 是資料庫」多半是口語偷懶,正確應說「**LDAP 目錄伺服器的資料庫**」。 ### 一張圖搞懂(放投影片) ``` [ 用戶端 / 應用程式 / SSSD ] │ (LDAP 協定:389+StartTLS 或 636) ▼ [ 目錄伺服器 / 服務:OpenLDAP、Active Directory、389 DS ] │ (儲存引擎) ▼ [ 目錄資料庫:LMDB/HDB(Berkeley DB)/ESE(JET Blue) … ] ``` ### 正確分工(投影片可直接貼) * **LDAP(協定)**:定義 client 如何「查詢/新增/修改/刪除」目錄資料,與如何 bind 驗證。 * **目錄伺服器(服務)**:實作協定並**對外提供服務**(例如 **OpenLDAP 的 slapd**、**Windows AD DS**、**389 Directory Server**)。 * **目錄資料庫(儲存層)**:伺服器用來存放條目(entry)的**專用資料庫**(如 **LMDB**、**ESE** 等),不是通用關聯式資料庫。 ### 為什麼大家說「LDAP 做集中式帳號管理」? 因為**應用程式透過 LDAP 協定**去**查詢/驗證帳號資料**(實際資料放在目錄伺服器的資料庫裡)。 → 應說:「**用 LDAP 介面存取目錄伺服器的帳號資料**」,而不是「LDAP 本身是資料庫/服務」。 ### 投影片用語修正版 * ✅ 「**LDAP 是用來存取目錄資料的網路協定**」 * ✅ 「**目錄伺服器(如 OpenLDAP/AD)提供目錄服務**,內部使用**目錄資料庫**儲存條目」 * ⚠️ 避免:「LDAP 服務」「LDAP 資料庫」(除非完整說成「LDAP 目錄伺服器的資料庫」) ### 類比(放備用投影片) * **HTTP : Web 伺服器 : 網站檔案/DB** * **SQL : 資料庫伺服器 : 資料檔** * **LDAP : 目錄伺服器 : 目錄資料庫** - **表格** | 界面 | 伺服器 | 資料 | | --- | ----- | ---- | | SQL 語言 | 資料庫伺服器(RDBMS)| 資料庫(tables/indexes;實體為 .ibd、.sqlite…) | | LDAP 協定 | 目錄伺服器(Directory Server,如 OpenLDAP/AD/389 DS) | **DIB/DIT**(entries/attributes/objectClass 的樹;實體為後端檔,如 OpenLDAP LMDB 的 `data.mdb`、AD 的 `ntds.dit`) | * **DIT**(Directory Information Tree):邏輯上的樹狀結構(DN/RDN、OU、人員等)。 * **DIB**(Directory Information Base):整體目錄資料集合(包含那棵樹)。 * **實體檔**:由目錄伺服器的後端引擎保存(OpenLDAP 常用 **LMDB**→`data.mdb`;AD 用 **ESE**→`ntds.dit`)。 一句話版:**LDAP 是協定;目錄伺服器提供服務;資料以 DIB/DIT 形式存在,實際落在後端資料庫檔上。** ### 加值備註 * SSO/授權通常要搭配 **Kerberos / SAML / OIDC**;**LDAP 多扮演「身分資料庫介面」** 與簡單密碼驗證(bind)。 * 連線埠:**389(搭配 StartTLS)**、**636(LDAPS)**。 * 目錄資料是**樹狀(DIT)**,由 **objectClass/schema** 規範欄位。 一句話記:**LDAP 是語言;說這種語言的伺服器在提供服務;伺服器把資料存進自己的專用資料庫。** <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}