# NASA HW8 ldap
* 41173058h
* 鍾詠傑
## ref
## people
41047033S
b12202064
郭浩雲學長
### hw_ref
https://www.digitalocean.com/community/tutorials/understanding-the-ldap-protocol-data-hierarchy-and-entry-components
https://wiki.archlinux.org/title/OpenLDAP#The_server
https://wiki.archlinux.org/title/LDAP_authentication#Create_home_folders_at_login
https://man.archlinux.org/man/sssd.conf.5
https://www.openldap.org/doc/
https://www.openldap.org/
https://stackoverflow.com/questions/65435945/how-do-i-fix-certificate-verify-failed-self-signed-certificate-when-trying-to
https://www.python-ldap.org/en/python-ldap-3.4.3/index.html
https://stackoverflow.com/questions/27242453/enable-active-directory-user-account-using-ldap-python
<div style="page-break-after:always;"></div>
## ldap_ref
https://access.redhat.com/solutions/978713
https://www.digitalocean.com/community/tutorials/how-to-encrypt-openldap-connections-using-starttls
https://www.digitalocean.com/community/tutorials/how-to-encrypt-openldap-connections-using-starttls
https://docs.oracle.com/cd/E19253-01/816-1435/rpcproto-9/index.html
https://ubuntu.com/server/docs/ldap-and-transport-layer-security-tls
https://www.sudo.ws/docs/man/1.8.17/sudoers.ldap.man/
<div style="page-break-after:always;"></div>
## 1. Server Setup

```
# suffix.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=nasa,dc=csie,dc=ntu
```
```
ldapmodify -Y EXTERNAL -H ldapi:/// -f rootdn.ldif
```
```
# rootdn.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=admin,dc=nasa,dc=csie,dc=ntu
```
加入mypasswd
```
# rootpw.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: mypasswd
```
```
# base.ldif
dn: dc=nasa,dc=csie,dc=ntu
dc: nasa
objectClass: top
objectClass: domain
dn: cn=admin,dc=nasa,dc=csie,dc=ntu
cn: admin
objectClass: organizationalRole
description: admin account
dn: ou=people,dc=nasa,dc=csie,dc=ntu
ou: people
objectClass: organizationalUnit
dn: ou=group,dc=nasa,dc=csie,dc=ntu
ou: group
objectClass: organizationalUnit
```

<div style="page-break-after:always;"></div>
### b
安裝必要套件
```
sudo apt install gnutls-bin ssl-cert
```
建⽴⾃簽憑證所需的私鑰
```
$ sudo certtool --generate-privkey \
--bits 4096 --outfile mycakey.pem
```
定義 CA 憑證的模板(相關檔案: ca.tmpl )
```ca.tmpl
cn = Example Company
ca
cert_signing_key
expiration_days = 3650
```
```
$ sudo certtool --generate-self-signed \
--load-privkey mycakey.pem \
--template ca.tmpl \
--outfile /usr/local/share/ca-certificates/mycacert.crt
```
```
sudo update-ca-certificates
```
產⽣伺服器私鑰
```
sudo certtool --generate-privkey \
--bits 2048 \
--outfile /etc/ldap/server_key.pem
```
定義憑證模板(相關檔案: server_key.tmpl )
```server_key.tmpl
organization = "Example Inc"
cn = nasa.csie.ntu
tls_www_server
encryption_key
signing_key
expiration_days = 3652
```
建⽴憑證
```
$ sudo certtool --generate-certificate \
--load-privkey /etc/ldap/server_key.pem \
--load-ca-certificate \
/etc/ssl/certs/mycacert.pem \
--load-ca-privkey mycakey.pem \
--template server_key.tmpl \
--outfile /etc/ldap/server_cert.pem
```
調整私鑰的檔案權限
```
$ sudo chgrp openldap /etc/ldap/server_key.pem
$ sudo chmod 0640 /etc/ldap/server_key.pem
```
修改 /etc/default/slapd
加入 `ldaps:///`
```
SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
```
重啟 slapd
```
$ sudo systemctl restart slapd
```
[LDAP with TLS/SSL](https://ubuntu.com/server/docs/service-ldap-with-tls)

<div style="page-break-after:always;"></div>
## 2. Client Setup
### a
```
pacman -Syu openldap
```

<div style="page-break-after:always;"></div>
### b
[How do I use TLS/SSL?](https://www.openldap.org/faq/data/cache/185.html)
將伺服器的 CA 憑證複製到⼯作站上
```
$ scp /etc/ssl/certs/mycacert.pem root@ldap:/us
r/local/share/ca-certificates/
```
更新簽證
```
# update-ca-trust
```
強制啟用
[how 2 forceTLS](https://www.digitalocean.com/community/tutorials/how-to-encrypt-openldap-connections-using-starttls)
在 Server 上套⽤設定檔(相關檔案: ldap/ssl/forceTLS.ldif )
sudo ldapmodify -H ldapi:// -Y EXTERNAL -f forceTLS.l
dif

<div style="page-break-after:always;"></div>
### c
請參考 arch wiki
全部照做即可
https://wiki.archlinux.org/title/LDAP_authentication#Password_management
<div style="page-break-after:always;"></div>
### d
```
# groups.ldif
dn: cn=ta,ou=group,dc=nasa,dc=csie,dc=ntu
objectClass: posixGroup
cn: ta
gidNumber: 1001
dn: cn=student,ou=group,dc=nasa,dc=csie,dc=ntu
objectClass: posixGroup
cn: student
gidNumber: 1002
```
## 伺服器設定
建⽴群組及使⽤者帳號
```
$ ldapadd -x -D cn=admin,dc=nasa,dc=csie,dc=ntu -W -H
ldaps:// -f groups.ldif
$ ldapadd -x -D cn=admin,dc=nasa,dc=csie,dc=ntu -W -H
ldaps:// -f users.ldif
```
接著將使⽤者加⼊各⾃的群組
```
$ ldapmodify -x -D cn=admin,dc=nasa,dc=csie,dc=ntu -W
-H ldaps:// -f adduser.ldif
```
## 客戶端設定
安裝必要套件
```
# pacman -S nss-pam-ldap sssd openssh
編輯 sudoers 檔案
# EDITOR=micro visudo
```
將反⽩那⾏取消註解
HW4 28
允許 SSH 連線
啟⽤ sshd 服務
$ sudo systemctl enable sshd
$ sudo systemctl start sshd
編輯 /etc/sssd/sssd.conf ,加⼊以下內容:
HW4 29
將該檔案的權限設為 0600
NSCD 組態
編輯 /etc/nscd.conf ,修改 cache policy:
```
# Begin /etc/nscd.conf
[...]
enable-cache passwd no
[...]
enable-cache group no
[...]
enable-cache hosts yes
[...]
enable-cache netgroup no
[...]
# End /etc/nscd.conf
```
NSS 組態
HW4 30
編輯 /etc/nsswitch.conf ,加⼊粗紅字部分
```
# Name Service Switch configuration file.
# See nsswitch.conf(5) for details.
passwd: files systemd sss
group: files [SUCCESS=merge] systemd sss
shadow: files systemd sss
gshadow: files systemd sss
publickey: files
hosts: mymachines resolve [!UNAVAIL=return] files myh
ostname dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
netgroup: files
```
PAM 基本配置
編輯 /etc/pam.d/system-auth ,加⼊粗紅字部分
```
#%PAM-1.0
auth sufficient
pam_sss.so forward_pass
auth required pam_faillock.s
o preauth
# Optionally use requisite above if you do not want t
o prompt for the password
# on locked accounts.
-auth [success=2 default=ignore] pam_systemd_ho
me.so
auth [success=1 default=bad] pam_unix.so
HW4 31
try_first_pass nullok
auth [default=die] pam_faillock.s
o authfail
auth optional pam_permit.so
auth required pam_env.so
auth required pam_faillock.s
o authsucc
# If you drop the above call to pam_faillock.so the l
ock will be done also
# on non-consecutive authentication failures.
account [default=bad success=ok user_unknown=ignore a
uthinfo_unavail=ignore] pam_sss.so
-account [success=1 default=ignore] pam_systemd_ho
me.so
account required pam_unix.so
account optional pam_permit.so
account required pam_time.so
password sufficient pam_sss.so use_authtok
-password [success=1 default=ignore] pam_systemd_ho
me.so
password required pam_unix.so
try_first_pass nullok shadow sha512
password optional pam_permit.so
session required pam_mkhomedir.
so skel=/etc/skel/ umask=0077
-session optional pam_systemd_ho
me.so
session required pam_limits.so
session required pam_unix.so
session optional pam_sss.so
session optional pam_permit.so
```
其中 pam_mkhomedir.so 那⾏就是設定登⼊時⾃動建⽴家⽬錄的部分
編輯 /etc/pam.d/passwd ,加⼊粗紅字部分:
```
HW4 32
#%PAM-1.0
password sufficient pam_sss.so
password required pam_unix.so sha512 shadow nul
lok
```
5. 參考資料:
How to Integrate Sudoers with OpenLDAP Server
Sudoers LDAP Manual
⽤ LDAP Server 管理 SSH Key login – 設定篇
LDAP authentication - ArchWiki
README.LDAP
Configuring SSSD to Work with System Services
伺服器設定
### 下載 sudo 的 LDAP schema sudo.ldif
(其他 Linux 發⾏版的 sudo 似乎會在安裝時附
帶 schema 於 /usr/share/doc/sudo ,但 Debian 沒有)
```
$ sudo wget "https://raw.githubusercontent.com/Lullab
ot/openldap-schema/master/sudo.ldif" -O /etc/ldap/sch
ema/sudo.ldif
加⼊ LDAP schema
$ sudo ldapadd -x -D cn=admin,dc=nasa,dc=csie,dc=ntu
-W -f /etc/ldap/schema/sudo.ldif -H ldaps://
加⼊ sudoer.ldif 及 sudoconf.ldif
$ ldapadd -x -D cn=admin,dc=nasa,dc=csie,dc=ntu -W -f
sudoers.ldif -H ldaps://
$ ldapadd -x -D cn=admin,dc=nasa,dc=csie,dc=ntu -W -f
sudoconf.ldif -H ldaps://
```
建⽴ ta 群組的 sudoRole 物件
```
$ ldapadd -x -D cn=admin,dc=nasa,dc=csie,dc=ntu -W -f
sudo_group.ldif -H ldaps://
```
客戶端設定
安裝 sudo 套件
```
# pacman -S sudo
```
NSS組態 編輯 /etc/nsswitch.conf ,加⼊粗紅字部分
```
# Name Service Switch configuration file.
# See nsswitch.conf(5) for details.
passwd: files systemd sss
group: files [SUCCESS=merge] systemd sss
shadow: files systemd sss
gshadow: files systemd sss
sudoers: files sss
publickey: files
hosts: mymachines resolve [!UNAVAIL=return] files myh
ostname dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
netgroup: files
```
編輯 /etc/pam.d/sudo ,加⼊粗紅字部分
```
#%PAM-1.0
auth sufficient pam_sss.so
auth include system-auth
account include system-auth
session include system-auth
```
接著在 /etc/sssd/sssd.conf 中加⼊粗紅字部分
```
[sssd]
config_file_version = 2
services = nss, pam, sudo
domains = LDAP
[domain/LDAP]
cache_credentials = true
enumerate = true
id_provider = ldap
auth_provider = ldap
ldap_uri = ldaps://ldap.nasa.csie.ntu
ldap_search_base = dc=nasa,dc=csie,dc=ntu
ldap_id_use_start_tls = true
ldap_tls_reqcert = allow
ldap_tls_cacert = /etc/ssl/certs/mycacert.pem
chpass_provider = ldap
ldap_chpass_uri = ldaps://ldap.nasa.csie.ntu
entry_cache_timeout = 600
ldap_network_timeout = 2
sudoers_base ou=sudo,dc=nasa,dc=csie,dc=ntu
sudo_provider = ldap
# OpenLDAP supports posixGroup, uncomment the followi
ng two lines
# to get group membership support (and comment the ot
her conflicting parameters)
#ldap_schema = rfc2307
#ldap_group_member = memberUid
# Other LDAP servers may support this instead
ldap_schema = rfc2307bis
ldap_group_member = uniqueMember
[nss]
filter_users = root, user # 排除掉已經存在的帳號,以⽅便操作
```
### d
1. 新增群组 `ta` 和 `student`:
```
# group, nasa.csie.ntu
dn: cn=ta,ou=group,dc=nasa,dc=csie,dc=ntu
cn: ta
objectClass: posixGroup
dn: cn=student,ou=group,dc=nasa,dc=csie,dc=ntu
cn: student
objectClass: posixGroup
```
2. 為 `ta` 群組的使用者設定 `sudo` 權限,我們需要使用 `sudoRole` 物件類別來建立一個 sudo 角色,並為該角色指定適當的 `sudoUser` 和 `sudoHost` 屬性。
```
dn: cn=ta_sudo,ou=group,dc=nasa,dc=csie,dc=ntu
objectClass: top
objectClass: sudoRole
cn: ta_sudo
sudoUser: %ta
sudoHost: ALL
sudoCommand: ALL
```
這個設定表示,屬於 `ta` 群組的使用者在任何主機上都可以執行任何指令,並且擁有 `sudo` 權限。
完成以上步驟後, LDAP 資料庫應該包含了兩個新的群組 `ta` 和 `student`,以及為 `ta` 群組建立的 `sudo` 角色。現在,屬於 `ta` 群組的使用者將擁有 `sudo` 權限,而屬於 `student` 群組的使用者則沒有這個權限。
<div style="page-break-after:always;"></div>
### 截圖
從 LDAP Server SSH 連線到⼯作站上的 student 帳號,⾸次登⼊⾃動建⽴家⽬錄
從 LDAP Server SSH 連線到⼯作站上的 ta 帳號,⾸次登⼊⾃動建⽴家⽬錄

在這之中
ta 群組的帳號可以 sudo
⽽ student 群組的帳號則不能 sudo
<div style="page-break-after:always;"></div>
## 3 Access Control Lists
在LDAP伺服器上設置這些存取控制權限,我們需要使用存取控制清單(ACL)來定義規則。讓我們逐步完成這些要求:
1. 使用者不可以修改其他使用者的資料,如其他使用者的 userPassword。
這個規則可以通過設置ACL來限制使用者只能修改自己的entry而不是其他使用者的entry,並排除掉`userPassword`屬性的修改權限。
```
access to attrs=userPassword
by self write
by * none
```
2. 使用者只可以更改除了家目錄、UID、GID 以外的資訊,如 loginShell。
我們可以通過ACL限制使用者對於特定屬性的寫入權限。例如,假設homeDirectory、uid和gid屬性對應的LDAP屬性名稱分別為`homeDirectory`、`uidNumber`和`gidNumber`,
設置ACL如下:
```
access to attrs=homeDirectory,uidNumber,gidNumber
by * none
```
這將防止所有使用者對這些屬性的寫入權限。
3. 使用者(包含 anonymous)可以存取其他使用者除了密碼以外的資訊。
這個規則需要為所有使用者(包括anonymous)授予讀取其他使用者除了密碼以外資訊的權限。例如:
```
access to *
by self write
by * read
```
這將允許所有使用者讀取其他使用者的資訊,但只有自己可以進行寫入操作。
完成以上步驟後,你的LDAP伺服器應該根據這些ACL規則來控制使用者的存取權限,確保了數據的安全性和完整性。記得在實施之前,確保了解你的LDAP伺服器的配置和ACL設置方法。
<div style="page-break-after:always;"></div>
# 4. Scripts (30 points)
好的,讓我們分別用 Python 和 Shell 腳本編寫 add_user 和 del_user 腳本來實現所需功能。
首先是 add_user 腳本,我們將使用 Python 編寫:
```python
#!/usr/bin/env python3
import sys
import ldap
def add_user():
ldap_server = "ldaps://ldap"
ldap_base_dn = "dc=nasa,dc=csie,dc=ntu"
ldap_admin_dn = "cn=admin,dc=nasa,dc=csie,dc=ntu"
ldap_admin_password = "your_ldap_admin_password"
username = input("Enter username: ")
password = input("Enter password: ")
# Check if username and password meet requirements
if not (username.isalnum() and len(username) <= 10 and password.isalnum() and len(password) <= 10):
print("Username and password must be alphanumeric and have length <= 10.")
return
# Connect to LDAP server
try:
conn = ldap.initialize(ldap_server)
conn.simple_bind_s(ldap_admin_dn, ldap_admin_password)
except ldap.LDAPError as e:
print(f"LDAP connection error: {e}")
return
# Add user to LDAP
try:
add_dn = f"uid={username},ou=people,{ldap_base_dn}"
attrs = [
("objectClass", [b"inetOrgPerson", b"posixAccount"]),
("uid", [bytes(username, 'utf-8')]),
("userPassword", [bytes(password, 'utf-8')]),
# Add other required attributes like home directory, uidNumber, gidNumber, etc.
]
conn.add_s(add_dn, attrs)
print("User added successfully.")
except ldap.LDAPError as e:
print(f"LDAP add user error: {e}")
conn.unbind()
if __name__ == "__main__":
add_user()
```
<div style="page-break-after:always;"></div>
接下來是 del_user 腳本,同樣使用 Python 編寫:
```python
#!/usr/bin/env python3
import sys
import ldap
def del_user():
ldap_server = "ldaps://ldap"
ldap_base_dn = "dc=nasa,dc=csie,dc=ntu"
ldap_admin_dn = "cn=admin,dc=nasa,dc=csie,dc=ntu"
ldap_admin_password = "your_ldap_admin_password"
username = input("Enter username to delete: ")
# Connect to LDAP server
try:
conn = ldap.initialize(ldap_server)
conn.simple_bind_s(ldap_admin_dn, ldap_admin_password)
except ldap.LDAPError as e:
print(f"LDAP connection error: {e}")
return
# Delete user from LDAP
try:
del_dn = f"uid={username},ou=people,{ldap_base_dn}"
conn.delete_s(del_dn)
print("User deleted successfully.")
except ldap.LDAPError as e:
print(f"LDAP delete user error: {e}")
conn.unbind()
if __name__ == "__main__":
del_user()
```
你需要根據你的實際情況修改腳本中的LDAP伺服器地址、基礎DN、管理員DN和密碼等資訊。
這兩個腳本將使管理員能夠通過輸入用戶名和密碼來添加用戶,並且能夠輸入用戶名來刪除用戶。
<div style="page-break-after:always;"></div>