# 帳號管理

# 登入失敗後鎖定帳號

#### RedHat 8

NOTE:

- RH8 新增一個 faillock 設定檔在 /etc/security/faillock.conf。  
    如果在 system-auth 內有指定參數，會忽略 faillock.conf 相同參數的設定。
- unlock\_time - 帳號鎖定後，經過多久時間會自動解鎖。
- deny - 密碼錯誤次數。

新增目錄 faillock (optional)

> TIP: 如果不指定目錄，預設目錄是 /var/run/faillock。

```
mkdir /var/log/faillock
```

Edit /etc/pam.d/system-auth , /etc/pam.d/password-auth

```
# for auth<br></br># faillock, add the below line BEFORE pam_unix.so<br></br>auth required pam_faillock.so preauth dir=/var/log/faillock silent audit deny=3 fail_interval=900 unlock_time=600<br></br>auth required pam_faillock.so authfail dir=/var/log/faillock unlock_time=600<br></br>#<br></br><br></br>auth        sufficient    pam_unix.so try_first_pass nullok<br></br><br></br># faillock, add the below line AFTER pam_unix.so<br></br>auth        [default=die] pam_faillock.so authfail deny=3 fail_interval=900 unlock_time=600<br></br>#<br></br><br></br># for account<br></br># faillock, add the below line BEFORE pam_unix.so<br></br>account required pam_faillock.so<br></br>#<br></br><br></br>account     required      pam_unix.so<br></br>
```

#### RedHat 6

Edit /etc/pam.d/system-auth , /etc/pam.d/password-auth

```
# for auth<br></br># add the below line BEFORE pam_unix.so<br></br>auth required pam_faillock.so preauth silent audit deny=3 unlock_time=600  # insert this<br></br><br></br>auth        sufficient    pam_unix.so nullok try_first_pass<br></br><br></br># add the below line AFTER pam_unix.so<br></br>auth [default=die] pam_faillock.so authfail audit deny=3 unlock_time=600  # insert this<br></br><br></br># for account<br></br># add the below line BEFORE pam_unix.so<br></br>account required pam_faillock.so  # insert this<br></br><br></br>account     required      pam_unix.so
```

預設不會套用在 root；如果需要限制 root，下面這一行加上 `even_deny_root` ：

```
auth    required    pam_faillock.so preauth silent audit deny=3 even_deny_root unlock_time=1200 root_unlock_time=600
```

如果要排除特定 user，在第一個 `pam_faillock.so` 之前加上這行:

```
auth [success=1 default=ignore] pam_succeed_if.so user in user1:user2:user3
```

如何手動解鎖與檢查被鎖定的帳戶

```
# display the authentication failure for all users <br></br>faillock<br></br><br></br># display the authentication failure for the specified user<br></br>faillock --user mytest<br></br><br></br># unlock the user<br></br>faillock --user mytest --reset
```

> Tip:
> 
> 要確認設定是否有作用，可以監看 log 檔 /var/log/secure，登入錯誤次數達到設定值時，應該要出現下面的訊息。
> 
> Mar 8 15:26:08 centos7 sshd\[26995\]: pam\_faillock(sshd:auth): Consecutive login failures for user i04181 account temporarily locked

#### VSFTPD

如果 vsftpd 使用系統帳號做認證時，也適用帳號鎖定的規則。

#### 參考教學

- \[RH\] [What is pam\_faillock and how to use it in Red Hat Enterprise Linux?](https://access.redhat.com/solutions/62949)
- \[RH\] [Lock account after 3 failed attempts.](https://access.redhat.com/discussions/1404353)
- [Linux 封鎖、解鎖登入失敗次數過多的帳號 pam\_faillock 教學與範例](https://officeguide.cc/linux-pam-tally2-lock-user-accounts-after-failed-login-attempts-tutorial-examples/)

# 進階管理技巧

##### 建立系統用帳號

CentOS/RedHat)

```shell
groupadd -r asterisk
useradd -r -g asterisk -d /var/lib/asterisk -M asterisk
```

Ubuntu/Debian)

```shell
addgroup --system asterisk
adduser --system --ingroup asterisk --home /var/lib/asterisk --no-create-home --shell /bin/bash asterisk
```

##### 移除帳號

```bash
# RedHat
userdel -r <username>

# Debian
deluser <username> --remove-home
```

##### 變更帳號為管理者權限

```shell
# Debian/Ubuntu
# Add the user into the group sudo
sudo usermod -aG sudo <user-name>
# Verify the user's groups
groups <user-name>
```

##### 強制修改密碼

強迫使用者在第一次登入後，修改他們的登入密碼

```shell
# 先將帳號鎖定
usermod -L <username>

# 強制第一次登入必須修改密碼
# 套用後，原密碼會立即過期，直到完成密碼變更。
chage -d 0 <username>

# 解除帳號鎖定
usermod -U <username>

# 檢查帳號的期限
chage -l <user-name>
```

##### 帳號使用期限

```shell
# 檢查帳號期限
chage -l <user-name>

# 設定有效期限 
chage -M 10 <user-name>             # 10 天後密碼即失效
chage -E "2017-02-20" <user-name>   # 2017-02-20 以後帳號即鎖定
chage -I 10 <user-name>             # 如有設定密碼期限時，當密碼失效起 10 日後自動鎖定帳號 

# 解除期限
chage -E -1 <user-name>       ; 數字 -1 解除期限設定 
```

##### 帳號鎖定與解鎖

```shell
# 鎖定帳號
usermod -L <user-name>
passwd -l <user-name>
chage -E 0 <user-name>

# 解鎖帳號
usermod -U <user-name>
passwd -u <user-name>
chage -E <user-name>

# 檢查帳號鎖定狀態
grep <user-name> /etc/shadow

dbtest:!$6$hFCW6eI1$kI9J9QrxCjnpvzFPJnxSpNvQ...  密碼欄有 ! 符號表示鎖定

# List the locked and passwordless accounts
getent shadow | awk '/^.*:[!\*].*/' | cut -d: -f1
```

> 注意：Passwd 雖然可以鎖定帳號，但仍可以用 SSH-Key 登入。

> 注意：帳號鎖定與帳號到期後的鎖定，後者會影響 CronJob 運作。

登入失敗的自動鎖定：

RHEL 7

```bash
# To enable the faillock
# unlock_time: seconds
authconfig --enablefaillock --faillockargs="deny=5 unlock_time=1200" --update

# To disable the faillock
authconfig --disablefaillock --update

# Validate the configuration
authconfig --test

# Check the login attempts failed
faillock

# Unlock the user locked immediately
faillock --user test01 --reset
```

##### 修改既有帳號的設定

```shell
# 修改註解
usermod -c "John" john
# 修改 shell
usermod -s "/sbin/nologin" alang
# 修改帳號名稱
usermod -l newuser currentuser
```

##### 限制某帳號不可遠端登入

但可以由其他允許帳號從遠端登入後，執行 su 切換到該帳號

情境：限制 devrpt 可以從遠端登入，但其他帳號在登入後可以 su 到 devrpt。

方法一: 修改 sshd\_config

```
# Added by Alang
# prevent certain users from using ssh for login
# while retaining the option to 'su username'
#
DenyUsers istdc
```

方法二: 最快速且容易設定但不適用需要有密碼的帳號

```shell
# 刪除 devrpt 的密碼
passwd -d devrpt
```

方法三: 比較嚴謹的做法

以 CentOS 為例：

1\. 編輯 /etc/security/access.conf，加上這幾行

```
# The line 'cron crond' is required
+:devrpt:cron crond tty1 tty2 tty3 tty4 tty5 tty6
-:devrpt:ALL
```

> TIPs：  
> 內容格式為 permission : username: origins
> 
> permission + 允許 或 - 拒絕  
> username 帳號  
> origins 來源，這可以是 tty 名稱'、主機/網域名稱、IP 。 注意：在此例，必須加上 cron crond 這一行，否則該帳號的 crontab 會無法工作。

2\. 對於不同的登入服務，需要修改相應的安全設定檔

- telnet : /etc/pam.d/remote (修改後立即生效)
- SSH : /etc/pam.d/sshd (修改後需重新載入 SSHD)
- Local 本機登入 : /etc/pam.d/login

視需要將以下內容加入其中一項或多項檔案內

```
# Limited users for remote login via telnet
# Check the file /etc/security/access.conf
account    required     pam_access.so
```

##### 重建帳號的家目錄

```
mkhomedir_helper <username>
```

##### 限制登入後的行為

情境: 帳號執行遠端登入後，只能變更密碼與幾個受限制的指令權限

RedHat-KB: [https://access.redhat.com/solutions/65822](https://access.redhat.com/solutions/65822)

```shell
# Create the restricted shell
cp /bin/bash /bin/rbash

# Create a directory that is used as the HOME of the user
mkdir /home/dbuser/
mkdir /home/dbuser/bin

# Modify the target user 'siview' for the shell as restricted shell
usermod -d /home/dbuser -s /bin/rbash siview
# or for new user
useradd -d /home/dbuser -s /bin/rbash siview
```

If a user uses **rbash**, the user can not do the following after login:

- Changing directories with the |cd| built in.
- Setting or unsetting the values of the |SHELL|, |PATH|, |ENV|, or |BASH\_ENV| variables.
- Specifying command names containing slashes.
- Specifying a filename containing a slash as an argument to the |.| built in command.
- Importing function definitions from the shell environment at startup.
- Parsing the value of |SHELLOPTS| from the shell environment at startup.
- Redirecting output using the `|&gt;|', `|&gt;||', `|&lt;&gt;|', `|&gt;&amp;|', `|&amp;&gt;|', and `|&gt;&gt;|' redirection operators.
- Using the |exec| built in to replace the shell with another command.
- Adding or deleting built in commands with the `|-f|' and `|-d|' options to the |enable| built in.
- Specifying the `|-p|' option to the |command| built in.
- Turning off restricted mode with `|set +r|' or `|set +o restricted|'.

```shell
# Create specific profile for the user
vi /home/dbuser/.bash_profile
```

.bash\_profile:

```shell
# cat /home/localuser/.bash_profile  
# .bash_profile  

# Get the aliases and functions  
if [ -f ~/.bashrc ]; then  
. ~/.bashrc  
fi  
# User specific environment and startup programs  
PATH=$HOME/bin  
export PATH
```

```shell
# Create the softlinks of commands which are required for the user
ln -s /bin/date /home/dbuser/bin/
ln -s /bin/ls /home/dbuser/bin/
ln -s /usr/bin/passwd /home/dbuser/bin/
```

##### 密碼強度

- RH-KB: [https://access.redhat.com/solutions/66322](https://access.redhat.com/solutions/66322) (RHEL6)
- RH-KB: [Set a password policy in Red Hat Enterprise Linux 7](https://access.redhat.com/solutions/2808101) (RHEL7)
- [How to Set password policy in CentOS or RHEL system](http://cjcheema.com/2019/05/how-to-set-password-policy-in-centos-or-rhel-system/)
- RedHat/CentOS: `/usr/share/doc/pam-<version>/txts/README.pam_cracklib`
- \[中文\] [https://www.lijyyh.com/2012/07/pam-managing-account-security-with-pam.html](https://www.lijyyh.com/2012/07/pam-managing-account-security-with-pam.html)

預設強度:

- difok=N , 預設字元數 5 位數
- minlen=N, 最少字元位數，預設是 9。
- dcredit=-1, 數字至少 1 位數
- ucredit=-1, 大寫字母至少 1 位數
- lcredit=-1, 小寫字母至少 1 位數

Edit `/etc/pam.d/system-auth` , `/etc/pam.d/password-auth`

CentOS 5/6)

> NOTE: CentOS 5 沒有 `/etc/pam.d/password-auth` , 所以只需要設定 `/etc/pam.d/system-auth`

```
# Set password strength
#password    requisite     pam_cracklib.so try_first_pass retry=3 type=
password    requisite     pam_cracklib.so minlen=8 dcredit=-1 ucredit=-1 lcredit=-1
```

CentOS 7/8)

Edit `/etc/security/pwquality.conf`

```
# Set password strength
minlen = 8
dcredit = -1
ucredit = -1
lcredit = -1
```

預設 root 不會套用密碼強度規則，如果要做限制，編輯 `/etc/pam.d/system-auth` 與 `/etc/pam.d/password-auth` ，在 password 這一行加上 `enforce_for_root`。

```
# Enforce root for password strength
password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= enforce_for_root
```

記住幾代密碼

Edit `/etc/pam.d/system-auth` , `/etc/pam.d/password-auth`  
CentOS 5/6)

```
# Keep history of passwords used
# Add remember=N
# The last n passwords for each user are saved in /etc/security/opasswd in order to force password change history 
# and keep the user from alternating between the same password too frequently.
#password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    sufficient    pam_unix.so sha512 remember=8 shadow nullok try_first_pass use_authtok
```

CentOS 7/8)

```
# Keep history of passwords used, insert the below line after pam_pwquality.so line
password    requisite     pam_pwhistory.so remember=8 use_authtok
```

> TIP: 歷史密碼會被儲存在 `/etc/security/opasswd` .

##### 密碼算法

檢查目前系統帳號的密碼演算法

```bash
# 方法 1
grep ENCRYPT_METHOD /etc/login.defs

# 方法 2
grep pam_unix.so /etc/pam.d/password-auth

# 方法 3
passwd -S <user-name>
```

列出有支援的密碼算法

```bash
authconfig --help | grep passalgo
```

變更密碼算法

> The below command modifies /etc/pam.d/system-auth, /etc/login.defs, /etc/libuser.conf, and /etc/sysconfig/authconfig and thus will have no effect (good or bad) on the password hashes already stored in /etc/passwd or /etc/shadow; instead, only future executions of passwd will use the new algo

```bash
authconfig --passalgo=sha512 --update
```

Optional: 重設 non-root 所有帳號的密碼為 &lt;user-name&gt;

```bash
for u in $(awk -F: '{if ( $1 != "root" && $2 ~ /^!?[[:alnum:]\.\/\$]/ ) print $1}' /etc/shadow); do passwd --stdin $u <<<$u; done
```

如果要強制第一次登入時需要變更密碼，繼續執行下個指令

```bash
for u in $(awk -F: '{if ( $1 != "root" && $2 ~ /^!?[[:alnum:]\.\/\$]/ ) print $1}' /etc/shadow); do chage -d0 $u; done
```

##### 群組管理

```shell
# Create a new group
groupadd <group-name>
addgroup <group-name>

# add a group into an account
usermod -aG mygroup user1
useradd -aG family,friends james

# To change the primary group of the user tom to family
usermod -g family tom

# remove user from a group
gpasswd -d user1 mygroup

# list all users in a group
lid -g mygroup

# list groups for current user
groups

# List groups for specified user
groups username
```

##### 指令 passwd

```shell
# displays the status of user account password settings
# [Username] [Status] [Date Last Changed] [Min. Age] [Max. Age] [Warn. Period] [ Inactivity Period]
# Status: 
#  - P: Usable password
#  - NP: No password
#  - L: Locked password
# Age: 
#  - 99999: Never expires
#  - 0: Can be changed at anytime
#  - -1: Disabled
passwd -S evans
 evans PS 2020-09-07 0 99999 7 -1 (Password set, SHA512 crypt.)

# lock the password of a specified account
passwd -l user1

# unlock the password
passwd -u user2

# delete a password for an account
passwd -d user1

# expire a password for an account
# This will force user to change the password at next login.
passwd -e user2

# This sets the number of days before a password can be changed. 
# By default, a value of zero is set, which indicates that the user may change 
# their password at any time.
# This means user2 cannot change its own password until 10 days have passed.
passwd -n 10 user2

# To confirm the password setting made with the -n option above, run the following command:
# The value of 10 after the date indicates the minimum number of days 
# until the password can be changed.
passwd -S user1
user1 PS 2020-12-04 10 99999 7 -1 (Password set, SHA512 crypt.)

# This means after 90 days, the password is required to be changed.
passwd -x 90 user2

# This means the user will receive warnings that the password will expire 7 days 
# before the expiration.
passwd -w 7 user2

# This means after a user account has had an expired password for 5 days, 
# the user may no longer sign on to the account.
passwd -i 5 user2

# This command will read from the echo command and pass it to the passwd command. 
# So this will set the user1 password to userpasswd1.
echo "userpasswd1"|passwd --stdin user1
```

##### 指令 getent

```bash
# List all user
getent passwd
getent passwd | awk -F: '{print $1}'

# List a specified user
getent passwd <username>

# List the locked and no-login accounts
getent shadow | awk '/^.*:[!\*].*/' | cut -d: -f1

# List the users with uid between 1000 ~ 1500
getent passwd {1000..1500}

```

##### 批次建立多個帳號

```shell
# Step 1 – Create an encrypted password
## perl one liner ##
#perl -e 'print crypt("Your-Clear-Text-Password-Here", "salt"),"\n"'

password="1YelloDog@"
pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
echo "$pass"
```

```shell
# Step 2 – Shell script to add a user and password on Linux
#!/bin/bash
# Purpose - Script to add a user to Linux system including passsword
# Author - Vivek Gite <www.cyberciti.biz> under GPL v2.0+
# ------------------------------------------------------------------
# Am i Root user?
if [ $(id -u) -eq 0 ]; then
	read -p "Enter username : " username
	read -s -p "Enter password : " password
	egrep "^$username" /etc/passwd >/dev/null
	if [ $? -eq 0 ]; then
		echo "$username exists!"
		exit 1
	else
		pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
		useradd -m -p "$pass" "$username"
		[ $? -eq 0 ] && echo "User has been added to system!" || echo "Failed to add a user!"
	fi
else
	echo "Only root may add a user to the system."
	exit 2
fi
```

```shell
# Step 3 – Change existing Linux user’s password in one CLI
echo "vivek:password" | chpasswd

# Verify that password has been changed
chage -l vivek
```

```shell
# Step 4 – Create Users and change passwords with passwd on a CentOS/RHEL
echo "YourPassword" | passwd --stdin UserName
```

##### 系統帳號與密碼遷移

在來源主機執行

```bash
# 範例一: 遷移 uid=500 以上的所有帳號
ID_minimum=500
for f in /etc/{passwd,group}; do awk -F: -vID=$ID_minimum '$3>=ID && $1!="nfsnobody"' $f |sort -nt: -k3 > ${f#/etc/}.bak; done
while read line; do grep -w "^${line%%:*}" /etc/shadow; done <passwd.bak >shadow.bak
while read line; do grep -w "^${line%%:*}" /etc/gshadow; done <group.bak >gshadow.bak

# 範例二: 遷移 uid=501 以上的所有帳號
export UGIDLIMIT=501
awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534)' /etc/passwd | sed '/nfsnobody/d' > passwd.move
awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534)' /etc/group | sed '/nfsnobody/d' > group.move
awk -v LIMIT=$UGIDLIMIT -F: '($3>=LIMIT) && ($3!=65534) {print $1}' /etc/passwd | egrep -wf - /etc/shadow | sed '/nfsnobody/d' > shadow.move

# 範例三: 遷移 uid=501 ~ 600 的帳號
export UGID_DOWN=501
export UGID_UP=600
awk -v LIMIT_DOWN=$UGID_DOWN -v LIMIT_UP=$UGID_UP -F: '($3>=LIMIT_DOWN) && ($3<=LIMIT_UP) && ($3!=65534)' /etc/passwd | sed '/nfsnobody/d' > passwd.move
awk -v LIMIT_DOWN=$UGID_DOWN -v LIMIT_UP=$UGID_UP -F: '($3>=LIMIT_DOWN) && ($3<=LIMIT_UP) && ($3!=65534)' /etc/group | sed '/nfsnobody/d' > group.move
awk -v LIMIT_DOWN=$UGID_DOWN -v LIMIT_UP=$UGID_UP -F: '($3>=LIMIT_DOWN) && ($3<=LIMIT_UP) && ($3!=65534) {print $1}' /etc/passwd | egrep -wf - /etc/shadow | sed '/nfsnobody/d' > shadow.move

# 範例四: uid= 501 ~ 699 and 1000+
export UGIDLIMIT_LOW=501
export UGIDLIMIT_HIGH=699
export UGIDS_RHEL7=1000

awk -v RHEL7=$UGIDS_RHEL7 -v LIMIT_LOW=$UGIDLIMIT_LOW -v LIMIT_HIGH=$UGIDLIMIT_HIGH -F: '($3>=RHEL7) || (($3>=LIMIT_LOW) && ($3<=LIMIT_HIGH) && ($3!=65534))' /etc/passwd | sed '/nfsnobody/d' > passwd.move

awk -v RHEL7=$UGIDS_RHEL7 -v LIMIT_LOW=$UGIDLIMIT_LOW -v LIMIT_HIGH=$UGIDLIMIT_HIGH -F: '($3>=RHEL7) || (($3>=LIMIT_LOW) && ($3<=LIMIT_HIGH) && ($3!=65534))' /etc/group | sed '/nfsnobody/d' > group.move

awk -v RHEL7=$UGIDS_RHEL7 -v LIMIT_LOW=$UGIDLIMIT_LOW -v LIMIT_HIGH=$UGIDLIMIT_HIGH -F: '($3>=RHEL7) || (($3>=LIMIT_LOW) && ($3<=LIMIT_HIGH) && ($3!=65534)) {print $1}' /etc/passwd | egrep -f - /etc/shadow | sed '/nfsnobody/d' > shadow.move
```

> NOTE: 如果系統有設定群組密碼，還要加上檔案 `/etc/gshadow` 的遷移。

將以上的檔案 \*.move 複製到目的主機，然後執行

```bash
cat passwd.move >> /etc/passwd
cat shadow.move >> /etc/shadow
cat group.move >> /etc/group

pwconv
grpconv

# 帳號如果需要建立 home 目錄，可以執行
mkhomedir_helper <user-name>
```

Optional: 清除之前匯入的帳密

> NOTE: 清除帳密時，只需要編輯 `/etc/passwd` 與 `/etc/group`，然後執行 `pwconv` 與 `grpconv`，就可以自動更新 `/etc/shadow` 與 `/etc/gshadow`。這方法不適用在匯入帳密時。

```bash
# 清除之前匯入的帳密
## 修改 /etc/passwd
vipw

## 修改 /etc/group
vigr

## 更新 /etc/shadow, /etc/gshadow
pwconv
grpconv
```

Optional: 批次建立 Home 目錄

```bash
for uidgid in $(cut -d: -f3,4 passwd.move); do
    dir=$(awk -F: /$uidgid/{print\$6} passwd.move)
    mkdir -vm700 "$dir"; cp -r /etc/skel/.[[:alpha:]]* "$dir"
    chown -R $uidgid "$dir"; ls -ld "$dir"
done
```

##### 帳號活動監控 psacct  


```bash
yum install psacct
```

- [How to Monitor Linux Users Activity with psacct or acct Tools](https://www.tecmint.com/monitor-linux-user-activity-psacct-acct/)
- Display total statistics of connect time in hours
- Print All Linux Commands Executed by Users
- Print Linux User Information
- Print Number of Linux Processes
- Print and Sort Usage by Percentage
- Search Logs for Commands

##### 遠端連線自動登出 (TMOUT)

Linux: `/etc/profile.d/timeout.sh`

```bash
#!/bin/bash
# Set the TMOUT 600 for specified group
grpname="sshusers"
#if [[ "`id -Gn`" =~ .*"$grpname".* ]]; then
if grep -q "$grpname" <<< "`id -Gn`"; then
    export TMOUT=600
fi

```

Multi groups

```bash
#!/bin/bash
# Set the TMOUT 600 for specified groups
#grpnames="(group1|group2|group3)"
grpnames="(sshusers)"
if echo "`id -Gn`" | grep -wEq "$grpnames"; then
    export TMOUT=600
fi
```

AIX: `/etc/profile`

```bash
# Set the TMOUT 600 for specified groups
#grpnames="(group1|group2|group3)"
grpnames="(sshusers)"
if echo "`id -Gn`" | grep -wEq "$grpnames"; then
    export TMOUT=600
fi
```

##### Learning

- [How to Lock User Accounts After Failed Login Attempts](https://www.tecmint.com/lock-user-accounts-after-failed-login-attempts-in-linux/)
- [Restrict SSH User Access to Certain Directory Using Chrooted Jail](https://www.tecmint.com/restrict-ssh-user-to-directory-using-chrooted-jail/)
- [How can I restrict the normal user to run only limited set of commands in RHEL?](https://access.redhat.com/solutions/65822)
- [How To Limit User’s Access To The Linux System](https://www.ostechnix.com/how-to-limit-users-access-to-the-linux-system/)
- [Set a password policy in Red Hat Enterprise Linux](https://access.redhat.com/solutions/66322)
- \[RedHat\] [How to enhance Linux user security with Pluggable Authentication Module settings](https://www.redhat.com/sysadmin/linux-security-pam)
- [Linux PAM for Compliance](https://cromwell-intl.com/open-source/linux-pam-compliance/)
- [12 Ways to Find User Account Info and Login Details in Linux](https://www.tecmint.com/check-user-in-linux/)

# Windows AD 認證

登入 RedHat 系統時，可使用 Windows AD 帳號。

#### RedHat 7/8 (不加入網域)

<p class="callout info">這個方式需要先建立相同名稱的本機帳號，通常這個會違反資安規範。</p>

- [Chapter 7. Configuring a RHEL host to use AD as an authentication provider Red Hat Enterprise Linux 8 | Red Hat Customer Portal](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_authentication_and_authorization_in_rhel/configuring-a-rhel-host-to-use-ad-as-an-authentication-provider_configuring-authentication-and-authorization-in-rhel)

安裝需要的套件

```bash
yum install sssd sssd-tools krb5-workstation krb5-libs
```

新增本地帳號與 AD 帳號同名

```bash
useradd AD_user
```

編輯 `/etc/nsswitch.conf`

```
# Add 'sss' for AD authentication
passwd:     files sss systemd
shadow:     files sss
group:      files sss systemd
```

編輯 `/etc/krb5.conf`

```
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
# Change this as required
 default_realm = EXAMPLE.COM
 default_ccache_name = KEYRING:persistent:%{uid}

[realms]
# Change this as required
EXAMPLE.COM = {
    kdc = ad.example.com
    dmin_server = ad.example.com
}

[domain_realm]
# Change this as required
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
```

新增 `/etc/sssd/sssd.conf`

```
[sssd]
    services = nss, pam
    domains = EXAMPLE.COM

[domain/EXAMPLE.COM]
    id_provider = files
    auth_provider = krb5
    krb5_realm = EXAMPLE.COM
    krb5_server = ad.example.com
```

設定檔權限

```bash
chmod 0600 /etc/sssd/sssd.conf
```

啟動 sssd 服務

```bash
systemctl start sssd
systemctl enable sssd
```

編輯 `/etc/pam.d/system-auth`

```
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        required      pam_faildelay.so delay=2000000
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
# AD Authentication
auth        sufficient    pam_sss.so forward_pass

auth        required      pam_deny.so


account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
# AD Authentication
account     [default=bad success=ok user_unknown=ignore] pam_sss.so

account     required      pam_permit.so


password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type$
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
# AD Authentication
password    sufficient    pam_sss.so use_authtok

password    required      pam_deny.so


session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
# AD Authentication
session     optional      pam_sss.so
```

編輯 `/etc/pam.d/password-auth` ，內容與上述的一樣。

##### 驗證AD登入

本機驗證

```
#> kinit AD_user
Password for AD_user@EXAMPLE.COM:

#> klist
Ticket cache: KEYRING:persistent:0:0
Default principal: AD_user@EXAMPLE.COM

Valid starting     Expires            Service principal
11/02/20 04:16:38  11/02/20 14:16:38  krbtgt/EXAMPLE.COM@EXAMPLE.COM
	renew until 18/02/20 04:16:34
```

遠端 SSH 驗證

遠端使用 AD\_user ( 不需加 `@example.com` )登入 SSH。

#### 其他指令

Displaying user authorization details

```bash
sssctl user-checks -a acct -s sshd AD_user
```

Display a list of available domains

```bash
sssctl domain-list
```

#### RedHat 7/8 (加入網域)

- [How to join a Linux system to an Active Directory domain | Enable Sysadmin (redhat.com)](https://www.redhat.com/sysadmin/linux-active-directory)
- [Windows Integration Guide Red Hat Enterprise Linux 7 | Red Hat Customer Portal](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html-single/windows_integration_guide/index)
- [How to join a Linux system to an Active Directory domain](https://www.redhat.com/en/blog/linux-active-directory)

安裝需要套件

```bash
yum install sssd realmd oddjob oddjob-mkhomedir adcli \
  samba-common samba-common-tools krb5-workstation \
  openldap-clients policycoreutils-python
```

使用 realmd 將 Linux 主機加入 AD 網域

> NOTE: 建議先將 /etc/krb5.conf 恢復成初始值，如果曾經修改過。還有將 /etc/sssd/sssd.conf 移除。
> 
> 加入 AD 網域時，需要有 AD 管理員或有足夠權限的 AD 帳號 例如 adm1。
> 
> 一旦加入網域成功，系統會自動修改或建立這兩個檔案。

```bash
realm discover ad.example.com

realm join ad.example.com -U adm1

realm list
```

自動生成 `/etc/sssd/sssd.conf`, `/etc/krb5.conf`

```
[sssd]
domains = example.com
config_file_version = 2
services = nss, pam

[domain/example.com]
ad_server = ad.example.com
ad_domain = example.com
krb5_realm = EXAMPLE.COM
realmd_tags = manages-system joined-with-adcli
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_id_mapping = True
use_fully_qualified_names = True
fallback_homedir = /home/%u@%d
access_provider = ad
```

```
[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
 default_ccache_name = KEYRING:persistent:%{uid}

 default_realm = EXAMPLE.COM
[realms]
 EXAMPLE.COM = {
 }

[domain_realm]
 example.com = EXAMPLE.COM
 .example.com = EXAMPLE.COM
```

Optional: 主機退出 AD 網域

```bash
# 預設需要 AD 的 Administrator 密碼
realm leave ad.example.com

# 或者使用指定的帳密
realm leave ad.example.com -U 'EXAMPLE.COM\user'
```

登入存取控制

<p class="callout info">預設，網域所有帳號都可以登入主機；要限制可以存取主機的 AD 帳號或 AD 群組，需要修改 /etc/sssd/sssd.conf。</p>

編輯 /etc/sssd/sssd.conf

```
# ACL for AD Login
#access_provider = ad
access_provider = simple
#simple_allow_users = ad-user1, ad-user2
simple_allow_groups = ad-group
```

重啟 sssd 服務

```bash
systemctl restart sssd
realm list
```

##### 帳號管理

加入 ad-user 至本機群組

```bash
usermod -aG local-group aduser@ad.domain.com
getent group local-group
groups aduser@ad.domain.com
```

##### 更多指令

列出 AD 帳號的 uid

```bash
id ADDOMAIN\\aduser@ad.domain.com

getent passwd aduser@ad.domain.com
```