[Login Pod] SSSD + LDAP 密碼登入除錯教學 === ###### tags: `SlinkyProject` ###### tags: `Kubernetes`, `k8s`, `app`, `slurm`, `SlinkyProject`, `Login Pod`, `SSSD`, `LDAP` <br> [TOC] <br> ## 適用情境 * `ldapwhoami` 以使用者 DN 可成功(LDAP 可驗證)。 * 但 `id <user>` / `getent passwd <user>` 一開始抓不到;後來加入 bind 後可以抓到。 * SSH 仍無法密碼登入(一直被拒),`su -` 首登出現沒有家目錄、群組名稱顯示異常等。 <br> --- ## 快速路徑(5 分鐘檢核) 1. **SSSD/NSS 基礎**:`sssd.conf` 權限 600;`libnss-sss` 在位;`nsswitch.conf` 有 `sss`。 2. **LDAP 查詢權限**:匿名查詢被拒 → 在 SSSD 加唯讀 bind。 3. **POSIX 欄位**:user 具 `uidNumber/gidNumber/homeDirectory/loginShell`。 4. **Primary group 存在**:建立對應 `posixGroup(gidNumber)`。 5. **PAM/SSH**:`libpam-sss` 在位;`/etc/pam.d/common-*` 包含 `pam_sss.so`;`pam_mkhomedir`。 6. **傳輸安全**:SSSD 不接受明文密碼 → 先臨時放行驗證,再改 **STARTTLS/LDAPS**。 7. **只讀 sshd_config**:以 `sshd -T` 查實際生效;需改就從上游(ConfigMap/Helm)調整。 <br> --- ## Step-by-Step 除錯流程 ### Step 0. 基本準備 ```bash # 檢查 sssd.conf 權限 ls -l /etc/sssd/sssd.conf # 期望:-rw------- 1 root root ... sssd.conf ``` **異常修正** ```bash chown root:root /etc/sssd/sssd.conf && chmod 600 /etc/sssd/sssd.conf ``` **建議**:容器基底用 **Debian/Ubuntu(glibc)**,避免 Alpine(無法跑 sssd)。 <br> --- ### Step 1. 解析與連線 ```bash getent hosts openldap.openldap || nslookup openldap.openldap ``` **預期**:能解析到 ClusterIP(你的是 `10.107.x.x`)。 <br> --- ### Step 2. 套件就緒 ```bash dpkg -l | egrep 'sssd|libnss-sss|sssd-ldap|libpam-sss' || echo "缺套件" ldconfig -p | grep nss_sss || echo "找不到 libnss_sss" ``` **異常修正** ```bash apt-get update && apt-get install -y sssd sssd-ldap libnss-sss libpam-sss ldap-utils ``` **建議**:另裝 `sssd-tools` 方便清快取、檢測(`sss_cache` / `sssctl`)。 <br> --- ### Step 3. NSS 走 SSSD ```bash grep -E '^(passwd|group|shadow):' /etc/nsswitch.conf # 期望: # passwd: files sss (systemd 可有可無) # group: files sss (systemd 可有可無) # shadow: files ``` **異常修正** ```bash sed -i 's/^passwd:.*/passwd: files sss/' /etc/nsswitch.conf sed -i 's/^group:.*/group: files sss/' /etc/nsswitch.conf ``` <br> --- ### Step 4. 目錄拒匿名 → 在 SSSD 設唯讀 bind 你的匿名 `ldapsearch` 回 `48 Inappropriate authentication`。在 `[domain/DEFAULT]` 加: ```ini ldap_default_bind_dn = cn=admin,dc=www,dc=asus,dc=com # 先用 admin 測通 ldap_default_authtok = YourSecurePassword ``` 存檔(600 權限)→ 讓 pod 正常重啟一次(你 kill sssd 會觸發重啟,OK)。 **驗證** ```bash getent passwd tj_tsai id tj_tsai ``` **預期**:能看到 UID/GID 與 shell/home。 **建議**:改用「唯讀」專用帳號(例如 `cn=readonly,ou=svc,...`),別長期放 admin 密碼。 <br> --- ### Step 5. 使用者 POSIX 欄位檢查 ```bash ldapsearch -x -H ldap://openldap.openldap \ -D "cn=admin,dc=www,dc=asus,dc=com" -w 'YourSecurePassword' \ -b "dc=www,dc=asus,dc=com" "(uid=tj_tsai)" \ uidNumber gidNumber homeDirectory loginShell objectClass -LLL ``` **預期**:有 `posixAccount` 與四大欄位。 <br> --- ### Step 6. 建立 primary group(posixGroup) 你最後變成 `gid=10001(gid10001)`,代表群組已存在但名稱不美觀;範例如下: ```ldif dn: cn=tn,ou=groups,ou=ocis,dc=www,dc=asus,dc=com objectClass: top objectClass: posixGroup cn: tn gidNumber: 10001 memberUid: tj_tsai ``` ```bash ldapadd -x -H ldap://openldap.openldap \ -D "cn=admin,dc=www,dc=asus,dc=com" -w 'YourSecurePassword' -f group_tn.ldif getent group 10001 id tj_tsai ``` **建議**:若你要把 `gid10001` 改成更易讀的 `tn`,須「新建正名的群組 → 調整使用者 gidNumber/次要群組 → 刪舊群組」。 <br> --- ### Step 7. PAM 串接 SSSD 與家目錄 確認 PAM 有 `pam_sss.so`: ```bash grep -nH 'pam_sss.so' /etc/pam.d/* /etc/pam.d/common-* # 你的輸出已包含 pam_sss.so(OK) ``` 自動建立家目錄(你已加): ```text # /etc/pam.d/common-session session optional pam_mkhomedir.so ``` **驗證**:`su - tj_tsai` 首次會印 `Creating directory '/home/tj_tsai'.` **建議**:可加 `skel` 與 `umask`: ``` session optional pam_mkhomedir.so skel=/etc/skel/ umask=0077 ``` <br> --- ### Step 8. SSHD 設定與唯讀檔案系統 查實際生效設定: ```bash sshd -T | egrep 'usepam|passwordauthentication' # 預期:usepam yes / passwordauthentication yes ``` 你無法改 `/etc/ssh/sshd_config`(唯讀)。 **建議**:到 Helm/ConfigMap 上游改,或用 drop-in:`/etc/ssh/sshd_config.d/xxx.conf`(若掛載允許)。 也檢查: ```bash ls -l /etc/nologin || echo "沒有 /etc/nologin(OK)" ``` <br> --- ### Step 9. SSSD 預設拒明文密碼 → 先驗證再上 TLS 先**臨時**允許(確認卡點用): ```ini # /etc/sssd/sssd.conf [domain/DEFAULT] ldap_auth_disable_tls_never_use_plaintext = True ``` 重啟 pod 後測: ```bash ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no \ -p <port> tj_tsai@127.0.0.1 ``` 若此時能登入 → 問題確立:**需上 TLS**。 正式化其一: * **STARTTLS** ```ini ldap_id_use_start_tls = True ldap_tls_reqcert = allow # 測試;正式請配 CA 後改 demand # ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt ``` * **LDAPS** ```ini ldap_uri = ldaps://openldap.openldap ldap_tls_reqcert = demand ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt ``` TLS 正式化後,**移除**臨時放行那一行。 <br> --- ### Step 10. 清快取&終驗 ```bash apt-get update && apt-get install -y sssd-tools # 若尚未安裝 sss_cache -E getent passwd tj_tsai id tj_tsai ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no \ -p <port> tj_tsai@127.0.0.1 ``` <br> --- ## 常見錯誤對照表 | 現象 / 訊息 | 判斷 | 修正 | |------------|-----|-----| | `ldap_bind: Inappropriate authentication (48)` | 目錄拒匿名查詢 | 在 SSSD 設 `ldap_default_bind_dn/_authtok`(用唯讀帳號) | | `id: ‘user’: no such user` / `getent 找不到` | NSS/SSSD 沒接上或沒權查 | 檢 `nsswitch.conf`、`libnss-sss`、`sssd.conf` 權限與 bind | | `groups: cannot find name for group ID 10001` | 缺對應 `posixGroup` | 在 LDAP 建 `posixGroup(gidNumber)`,必要時加 `memberUid` | | `su - user: No such file or directory` | 家目錄未建立 | `common-session` 加 `pam_mkhomedir.so` 或手動建目錄 | | SSH 一直被拒(會跳密碼) | 多半是 SSSD 禁明文密碼 | 臨時 `ldap_auth_disable_tls_never_use_plaintext=True` 驗證 → 上 STARTTLS/LDAPS | | 無法改 `sshd_config` | 檔案系統唯讀/被掛載 | 從 Helm/ConfigMap 調整;或用 `sshd_config.d/*.conf` 落實 | <br> --- ## 建議(彙整) * **安全**:建立「唯讀」Bind 帳號與最小 ACL;不要長期用 admin。 * **TLS**:正式環境務必用 **STARTTLS/LDAPS**,並配置 CA;撤掉臨時明文放行。 * **群組命名**:用有意義的 `cn`(例如 `tn`),避免 `gid10001` 這類機器生成名。 * **K8s 規劃**:把 `sssd.conf` 與 `sshd` 設定來源化(ConfigMap/Secret),避免進 Pod 手改。 * **工具**:安裝 `sssd-tools`,善用 `sss_cache -E` 與 `sssctl user-checks -s sshd -a pam_auth <user>`。 <br> --- ## 延伸探討(較艱澀,但值得一看) ### 1) NSS vs PAM 的分工 * **NSS**:解「這個帳號是誰」(`getent/id`)。 * **PAM**:驗「這個帳號的密碼對不對」(SSH/`su`)。 你出現的現象正是「NSS OK、PAM 擋在傳輸政策」。 ### 2) rfc2307 vs rfc2307bis * `posixGroup + memberUid`(rfc2307)最直覺。 * 若用 `groupOfNames + member`,請在 SSSD 設: ```ini ldap_schema = rfc2307bis # 必要時指定成員屬性: # ldap_group_member = member ``` ### 3) SSSD 與明文密碼政策 * 預設禁止在非加密通道送密碼。 * 僅用 `ldap_auth_disable_tls_never_use_plaintext=True` 作**排錯**,最後要回到 TLS。 ### 4) K8s 上的服務管理 * Pod 內通常沒有 systemd,`sssd -i` 前景除錯會被 liveness 掉;你可改「寫入設定 → 讓 Pod 自動重啟」。 * sshd 設定若唯讀,代表來自掛載;需修改 chart/ConfigMap 才能持久。 <br> --- ## 最終驗證清單(交付前自檢) * [ ] `getent passwd <user>` 與 `id <user>` 正常 * [ ] `getent group <gid>` 顯示命名良好的群組(如 `tn`) * [ ] `su - <user>` 會建立/使用 `/home/<user>` * [ ] `sshd -T` 顯示 `usepam yes`、(若需要)`passwordauthentication yes` * [ ] `sssd.conf` 裡 **沒有** 臨時的 `ldap_auth_disable_tls_never_use_plaintext` * [ ] 已改用 **STARTTLS/LDAPS** 並配置 CA * [ ] 唯讀 bind 帳密來自 **K8s Secret** 掛載,`sssd.conf` 權限 600 做到以上,Login Pod 的 LDAP 密碼登入就會穩定且安全地運作。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}