Linux 基礎學習訓練教材 - CentOS 7.x

第 10 堂課:使用者管理與 ACL 權限設定

針對 Linux 使用者的進階管理,同時還有處理一下重要的 ACL 這玩意兒,針對單一用戶、群組所進行的權限設計!

最近更新時間: 2017/04/02

帳號管理是一門大學問,使用者可以回想一下之前玩過的 useradd, userdel, usermod 等指令的功能,同時再回想一下之前的權限概念, 就能夠知道使用者帳號管理的行為有多重要了!這一堂課還會針對同一個檔案給予個別帳號或個別群組的權限功能,啟用的是所謂的 ACL 的概念! 都是非常重要的管理行為!

10.1:Linux 帳號管理

在管理權限時,操作者可以藉由 id 這個指令查詢使用者所加入的次要群組支援,藉以了解使用者對於某個檔案的權限。 而主要的檔案記錄其實是使用者的 UID 與 GID。

10.1.1:Linux 帳號之 UID 與 GID

系統記錄使用者 UID 與 GID 的檔案主要在:

  • 記錄 UID : /etc/passwd
  • 記錄 GID : /etc/passwd 與 /etc/group

針對 UID 的部份,在 CentOS 7.x 以後,系統管理員、系統帳號與一般帳號的 UID 範圍為:

id 範圍該 ID 使用者特性
0
(系統管理員)
當 UID 是 0 時,代表這個帳號是『系統管理員』!
1~999
(系統帳號)
保留給系統使用的 ID,其實除了 0 之外,其他的 UID 權限與特性並沒有不一樣。預設 1000 以下的數字讓給系統作為保留帳號只是一個習慣。根據系統帳號的由來,通常這類帳號又約略被區分為兩種:
  • 1~200:由 distributions 自行建立的系統帳號;
  • 201~999:若使用者有系統帳號需求時,可以使用的帳號 UID。
1000~60000
(可登入帳號)
給一般使用者用的。事實上,目前的 linux 核心 (3.10.x 版)已經可以支援到 4294967295 (2^32-1) 這麼大的 UID 號碼

Linux 的帳號資料記錄在 /etc/passwd 當中,這個檔案的內容中,以冒號 (:) 為區隔,共有七個欄位,每個欄位的意義為:

  1. 帳號名稱:就是登入的帳號名稱
  2. 密碼:已經挪到 /etc/shadow 中,因此在此都是 x
  3. UID:如上說明的 UID 資訊
  4. GID:為使用者『初始群組』的 ID
  5. 使用者資訊說明欄
  6. 家目錄所在處
  7. 預設登入時所取得的 shell 名稱

更多的說明可以參考 man 5 passwd 的內容。早期使用者加密過的密碼記錄在 /etc/passwd 第二個欄位,但這個檔案的權限是任何人均可讀取, 因此,有心人士可以查閱到加密過的密碼,再以暴力破解法就可能可以獲取所有人的密碼。因此,密碼欄位已經移動到另一個檔案去, 這就是 /etc/shadow 的由來。 /etc/shadow 以冒號 (:) 分隔成 9 欄位,各欄位功能為:

  1. 帳號名稱
  2. 密碼:目前大多使用 SHA 的加密格式來取代舊的 md5,因為密碼的長度較長,比較不容易被破解。
  3. 最近更動密碼的日期:主要以 1970/01/01 累積來的總日數
  4. 密碼不可被更動的天數:修改好密碼後,幾天內不能變更之意,0 代表沒限制
  5. 密碼需要重新變更的天數:修改好密碼後,幾天內一定要變更的意思,0 代表沒限制
  6. 密碼需要變更期限前的警告天數:第 3 與第 5 欄位相加後的幾天內,當使用者登入系統時,會警告該修改密碼了
  7. 密碼過期後的帳號寬限時間(密碼失效日):密碼有效日期為『更新日期(第3欄位)』+『重新變更日期(第5欄位)』, 過了該期限後使用者依舊沒有更新密碼,那該密碼就算過期了。(參考底下例題的說明)
  8. 帳號失效日期:亦使用 1970/01/01 累加的總日數,這個欄位表示,此帳號在此欄位規定的日期之後,將無法再使用。
  9. 系統保留尚未使用

使用者的密碼加密機制是可變的,從早期的 md5 到新的 sha512 改善了密碼的資料長度,對於暴力破解法來說, 解密的時間會比較長。至於目前系統的加密機制可使用底下的方式查閱:

[root@localhost ~]# authconfig --test | grep password
 shadow passwords are enabled
 password hashing algorithm is sha512

[root@localhost ~]# cat /etc/sysconfig/authconfig | grep -i passwd
PASSWDALGORITHM=sha512
USEPASSWDQC=no

使用者的初始群組 (原生家庭) 記載在 /etc/passwd 檔案的第四個欄位,不過該 GID 對應到人類認識的群組名稱就得到 /etc/group 當中查詢。 這個檔案的內容同樣使用冒號 (:) 分隔成四個欄位,內容為:

  1. 群組名稱
  2. 群組密碼:目前很少使用
  3. GID
  4. 加入此群組的帳號,使用逗號 (,) 分隔每個帳號

這三個檔案中心以 /etc/passwd 為主,連結到 /etc/group 與 /etc/shadow 的示意圖如下:

圖10.1.1、帳號相關檔案之間的 UID/GID 與密碼相關性示意圖
圖10.1.1、帳號相關檔案之間的 UID/GID 與密碼相關性示意圖
例題:
  1. 密碼的過期狀態分析:
    1. 建立一個名為 check 的帳號,密碼設定為 check123
    2. 請使用『 chage -d 0 check 』讓這個帳號的密碼建置日期強迫歸零,亦即強迫該帳號密碼過期。
    3. 當密碼過期後,check 這個帳號登入系統會有什麼應該要進行的任務?
  2. 查詢 find 的選項,嘗試找出系統中『不屬於任何人』的檔案檔名(不見得存在)
  3. 有一個 /etc/shadow 內的資料如下,嘗試回答下列問題:
    student:$6$3iq4VYrt$Hg62ID...RVbE/:16849:5:180:7:::
    1. 這個帳號的密碼最近一次被修改的日期為何 (查詢 date 的 example 用法)
    2. 這個帳號的密碼在那一個日期以前不可以被修改?
    3. 這個帳號的密碼在那一個日期以內最好能夠被修改?
    4. 這個帳號是否會失效?

10.1.2:帳號與群組管理

從上述資料我們可以知道,Linux 的帳號資訊大概都記錄在 /etc/passwd, /etc/shadow, /etc/group 當中,那如果我們要新建帳號時, 系統會怎麼做呢?先測試建置帳號:

[root@local ~]# useradd testuser1
[root@local ~]# passwd testuser1
Changing password for user testuser1.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

讓我們觀察一下 testuser 這個帳號的相關資料,先看一下使用者的 UID 與 GID:

[root@local ~]# id testuser1
uid=1002(testuser1) gid=1002(testuser1) groups=1002(testuser1)

[root@local ~]# grep testuser1 /etc/passwd /etc/group /etc/shadow
/etc/passwd:testuser1:x:1002:1002::/home/testuser1:/bin/bash
/etc/group:testuser1:x:1002:
/etc/shadow:testuser1:$6$bgAJnRxx$lvgO10GAMg1aoHSzm/cR.GcW..:16924:0:99999:7:::

上述 shadow 的資料可以簡易的使用如下的指令來查詢:

[root@localhost ~]# chage -l testuser1
Last password change                               : May 03, 2016
Password expires                                   : never
Password inactive                                  : never
Account expires                                    : never
Minimum number of days between password change     : 0
Maximum number of days between password change     : 99999
Number of days of warning before password expires  : 7

一般來說,新建帳號時,系統會:

  • 『拿既有的最大的 UID + 1 作為新的 UID』提供給新用戶
  • 在 /home 建立與帳號同名的目錄作為使用者家目錄
  • 給予 bash 這個 shell
  • 然後 CentOS 也會建立一個與帳號同名的群組給該帳號
  • 建立密碼時,會依據預設值給予該帳號一些限制資料

至於新建使用者時,上述的動作參考資料其實是參考 /etc/default/useradd 檔案而來,該檔案內容如下:

[root@localhost ~]# cat /etc/default/useradd
# useradd defaults file
GROUP=100               <==若為公開群組,使用 GID 100 的群組名稱
HOME=/home              <==預設使用者家目錄位置
INACTIVE=-1             <==密碼是否失效,預設不會失效!
EXPIRE=                 <==帳號是否需要失效 (shadow 第 8 欄位)
SHELL=/bin/bash         <==預設使用的 shell
SKEL=/etc/skel          <==預設使用者家目錄的參考依據
CREATE_MAIL_SPOOL=yes   <==是否要建立使用者郵件信箱

除了 /etc/default/useradd 之外,其他像是密碼欄位的預設值,則寫入在 /etc/login.defs 這個檔案中,這個檔案的內容如下:

[root@localhost ~]# grep -v '#' /etc/login.defs | grep -v '^$'
MAIL_DIR        /var/spool/mail  <==使用者預設郵件信箱放置目錄

PASS_MAX_DAYS   99999    <==/etc/shadow 內的第 5 欄,多久需變更密碼日數
PASS_MIN_DAYS   0        <==/etc/shadow 內的第 4 欄,多久不可重新設定密碼日數
PASS_MIN_LEN    5        <==密碼最短的字元長度,已被 pam 模組取代,失去效用!
PASS_WARN_AGE   7        <==/etc/shadow 內的第 6 欄,過期前會警告的日數

UID_MIN          1000    <==使用者最小的 UID,意即小於 1000 的 UID 為系統保留
UID_MAX         60000    <==使用者能夠用的最大 UID
SYS_UID_MIN       201    <==保留給使用者自行設定的系統帳號最小值 UID
SYS_UID_MAX       999    <==保留給使用者自行設定的系統帳號最大值 UID
GID_MIN          1000    <==使用者自訂群組的最小 GID,小於 1000 為系統保留
GID_MAX         60000    <==使用者自訂群組的最大 GID
SYS_GID_MIN       201    <==保留給使用者自行設定的系統帳號最小值 GID
SYS_GID_MAX       999    <==保留給使用者自行設定的系統帳號最大值 GID

CREATE_HOME     yes      <==在不加 -M 及 -m 時,是否主動建立使用者家目錄?
UMASK           077      <==使用者家目錄建立的 umask ,因此權限會是 700
USERGROUPS_ENAB yes      <==使用 userdel 刪除時,是否會刪除初始群組
ENCRYPT_METHOD SHA512    <==密碼加密的機制使用的是 sha512 這一個機制!

一般來說,除非有特殊的需求,例如需要建立的是雲端集中帳號管理,所以需要修改上述的設定檔資料 (/etc/default/useradd, /etc/login.defs),否則盡量使用自訂的手動修改使用者相關參數,不要隨意更動上述的檔案內容。

例題:嘗試使用 passwd 這個指令完成如下的任務:
  1. 使用 passwd 這個指令觀察 testuser1 的密碼狀態
  2. 設定密碼存活時間從 99999 改為 180 天
  3. 設定警告期限從 7 天改為 14 天
  4. 暫時將這個帳號的密碼鎖定,讓這個帳號無法登入系統
例題:嘗試使用 chage 以及 usermod 完成如下任務 (不要使用 passwd 喔!)
  1. 使用 chage 這個指令觀察 testuser1 的密碼狀態
  2. 使用 chage 設定密碼存活時間從 180 改為 365 天
  3. 使用 chage 設定警告期限從 14 天改為 30 天
  4. 使用 usermod 將這個帳號的密碼放行,讓這個帳號可以登入系統

若需要刪除帳號,使用 userdel 即可。不過需要加上 -r 的選項較佳!如果忘記加上 -r 的選項時,你應該要這樣做:

[root@localhost ~]# userdel testuser1
[root@localhost ~]# ll -d /home/testuser1 /var/spool/mail/testuser1
drwx------. 3 1002 1002 74 May  3 18:26 /home/testuser1
-rw-rw----. 1 1002 mail  0 May  3 18:26 /var/spool/mail/testuser1
[root@localhost ~]# find / -nouser
/home/testuser1
/home/testuser1/.mozilla
/home/testuser1/.mozilla/extensions
/home/testuser1/.mozilla/plugins
/home/testuser1/.bash_logout
/home/testuser1/.bash_profile
/home/testuser1/.bashrc
/var/spool/mail/testuser1

如上所示,系統會有一堆暫存資料需要刪除,因此管理員可能需要使用 rm -rf /home/testuser1 /var/spool/mail/testuser1 來刪除掉這些沒主人的檔案。

10.1.3:bash shell script 的迴圈控制

我們知道 id 可以找出使用者 UID 與 GID,但是 id 只能接一個參數而已,若需要 /etc/passwd 內所有帳號的 UID 與 GID 列表呢? 除了使用管線命令的 xargs 之外,我們可以使用 shell script 的迴圈控制來處理。Bash shell script 的 for 迴圈基本語法如下:

for 變數名 in 內容1 內容2 內容3 ...
do
	執行的指令碼
done

變數名稱會在 do..done 當中被取用,然後第一次執行迴圈為『變數名=內容1』,第二次為『變數名=內容2』,以此類推! 依據上面的基本語法,我們可以透過管線命令取出 /etc/passwd 內的第 1 個欄位的帳號資料後,丟進迴圈處理。如下所示:

[root@localhost ~]# mkdir bin; cd bin
[root@localhost bin]# vim allid.sh
#!/bin/bash
# This script will show all users id
# VBird 2016/05/03
users=$( cut -d ':' -f 1 /etc/passwd)
for username in ${users}
do
        id ${username}
done

[root@localhost bin]# chmod a+x allid.sh
[root@localhost bin]# allid.sh
uid=0(root) gid=0(root) groups=0(root)
uid=1(bin) gid=1(bin) groups=1(bin)
uid=2(daemon) gid=2(daemon) groups=2(daemon)
.......

bash shell script 的迴圈控制主要是根據 for ... do ... done 來處理,所以也稱為 for 迴圈。上述的腳本中:

  1. 先使用 cut 取得系統所有帳號的資料,並帶入 users 這個變數中
  2. 之後以 for 迴圈定義出名為 username 的變數,這個變數一次取出一個 ${users} 內的帳號資料
  3. 在 do ... done 動作中間,每次使用 id ${username} 進行 id 指令的行為。
例題:使用下列的功能建置名為 account.sh 的指令來大量建置帳號
  1. 建立一個名為 users.txt 的檔案,內容填寫三行,每行一個帳號名稱 (假設帳號為 linuxuser1~linuxuser3)
  2. 在 account.sh 當中,依序處理如下的行為:
    1. 建立名為 users 的變數,這個變數的內容為取出 users.txt 的內容
    2. 建立 for 迴圈,建立名為 username 的變數,此變數取用 ${users} 的內容
    3. 在迴圈內,針對每個用戶進行 (1)建立帳號 (2)使用 passwd --stdin 建立同帳號名稱的密碼 (3)使用 chage -d 0 ${username} 強制使用者第一次登入時需要修改自己的密碼。

10.1.4:預設權限 umask

使用者在新建資料時,預設的權限會是如何規範?一般來說,依據帳號的差異而會給予這樣的設定:

  • 如果用戶為 root 時,預設目錄權限為 755 而預設檔案為 644
  • 如果用戶為一般帳號時,預設目錄權限為 775 而預設檔案為 664

這樣的權限設計是考量一般用戶可能會有同群組互相操作『同群組共享目錄』的可能之故。但其實該預設權限是可以修改的, 其主要的設定為 umask 所管理。

[student@localhost ~]$ umask
0002

[root@localhost ~]# umask
0022

分別使用 root 與 student 查閱 umask 時,其輸出的結果並不相同。最簡單的思考方向,umask 為拿掉不想要給予的預設權限。 而四組分數中,第一個為特殊權限分數,不用理會,後續三個分數 (root為022而student為002) 即為一般權限設定的三種身份權限。

例題:
嘗試說明為何 root 在新建資料時,預設權限會是 755(目錄) 與 644(檔案)?

如果 linuxuser1 在新建目錄時,希望同群組的用戶可以一同完整操作檔案,但是其他人則沒有任何權限,該如何處理 umask 呢? 簡單的處理流程為:

[root@localhost ~]# su - linuxuser1
[linuxuser1@localhost ~]$ umask 007
[linuxuser1@localhost ~]$ mkdir newdir
[linuxuser1@localhost ~]$ touch newfile
[linuxuser1@localhost ~]$ ll -d new*
drwxrwx---. 2 linuxuser1 linuxuser1 6 May  3 23:54 newdir
-rw-rw----. 1 linuxuser1 linuxuser1 0 May  3 23:54 newfil

若需要這樣的設定永遠存在,就寫入 ~/.bashrc 當中即可。

10.1.5:帳號管理實務

任務一:關於新建用戶的家目錄與 bash 操作環境設定,未來所有系統新建的用戶,在其家目錄中:

  • 必須要建立名為 bin 的子目錄
  • 在 .bashrc 之內,必須要讓 HISTSIZE 達到 10000 的記錄
  • 建立 cp, rm, mv 的 alias ,讓這三個指令預設要加上 -i 的選項

解決方案很簡單,因為只是修改未來新用戶的資料而已,因此只要修訂 /etc/skel 即可處理完畢!

[root@localhost ~]# cd /etc/skel
[root@localhost skel]# mkdir bin
[root@localhost skel]# vim .bashrc
# User specific aliases and functions
HISTSIZE=10000
HISTFILESIZE=10000
alias cp="cp -i"
alias mv="mv -i"
alias rm="rm -i"

[root@localhost skel]# useradd testuser2
[root@localhost skel]# ll /home/testuser2; tail -n 4 /home/testuser2/.bashrc
drwxr-xr-x. 2 testuser2 testuser2 6 May  3 19:56 bin
HISTFILESIZE=10000
alias cp="cp -i"
alias mv="mv -i"
alias rm="rm -i"

[root@localhost skel]# userdel -r testuser2

建置完畢後我們使用 useradd 建立一個名為 testuser2 的帳號來查看一下是否有問題,若沒有問題就可以刪除該帳號了!


任務二:建立 mailuser1 ~ mailuser5 共五個帳號,這五個帳號需求:

  • 這五個帳號為純 email 帳號,不許這五個帳號使用本機登入取得 shell,也不許透過網路取得可互動的 shell
  • 使用 openssl rand -base64 6 取得 8 位數密碼,將密碼設定給 mailuser[1-5]
  • 最終輸出 mailuserpw.txt 的檔案,內容就是這五個帳號與對應的密碼

上述第一點主要是 shell 改成不可互動的 shell 即可,預設建議使用 /sbin/nologin 較佳。 由於建置帳號的資料太多,因此建議使用 shell script 來處理較佳!

[root@localhost ~]# cd bin
[root@localhost bin]# vim mailuser.sh
#!/bin/bash
# This program will create mail users
# VBird 2016/05/03

for user in $(seq 1 5)
do
        username="mailuser${user}"
        userpass=$(openssl rand -base64 6)
        useradd -s /sbin/nologin ${username}
        echo ${userpass} | passwd --stdin ${username}
        echo "${username} ${userpass}" >> mailuserpw.txt
done

[root@localhost bin]# sh mailuser.sh
[root@localhost bin]# cat mailuserpw.txt
mailuser1 M8pk6GEt
mailuser2 HznQI88d
mailuser3 zKpg4eg/
mailuser4 aakuwjo/
mailuser5 VrJtokaT

[root@localhost bin]# grep mailuser /etc/passwd
mailuser1:x:1006:1006::/home/mailuser1:/sbin/nologin
mailuser2:x:1007:1007::/home/mailuser2:/sbin/nologin
mailuser3:x:1008:1008::/home/mailuser3:/sbin/nologin
mailuser4:x:1009:1009::/home/mailuser4:/sbin/nologin
mailuser5:x:1010:1010::/home/mailuser5:/sbin/nologin

上述即可建立好專門給 mail user 專用的帳號了!而且這些帳號還無法登入系統操作 bash,這樣系統較為安全!


任務三:由於軟體的特殊需求,我們需要建立如下的帳號:

  • UID 為 399 的名為 sysuser1 的帳號
  • 這個帳號的初始群組為 users
  • 這個帳號的密碼為 centos。

其實不難,只要兩個指令即可結束!

[root@localhost ~]# useradd -u 399 -g users sysuser1
[root@localhost ~]# echo centos | passwd --stdin sysuser1
[root@localhost ~]# id sysuser1
uid=399(sysuser1) gid=100(users) groups=100(users)

建議讀者們最終一定要自己檢查看看是否正確才好!所以上述我們使用了 id 這個指令來查詢是否正確!


任務四:同一專案人員的共享目錄資源情況:

  • 我的使用者 pro1, pro2, pro3 是同一個專案計畫的開發人員
  • 我想要讓這三個用戶在同一個目錄底下工作,但這三個用戶還是擁有自己的家目錄與基本的私有群組。
  • 假設我要讓這個專案計畫在 /srv/projecta 目錄下開發

問題不難,讀者應該會想到,之前處理權限資料時,就曾經玩過『共享目錄』的資訊,這裡即是重新複習一次!

[root@localhost ~]# groupadd project
[root@localhost ~]# useradd -G project pro1
[root@localhost ~]# useradd -G project pro2
[root@localhost ~]# useradd -G project pro3
[root@localhost ~]# echo password | passwd --stdin pro1
[root@localhost ~]# echo password | passwd --stdin pro2
[root@localhost ~]# echo password | passwd --stdin pro3
[root@localhost ~]# mkdir /srv/projecta
[root@localhost ~]# chgrp project /srv/projecta
[root@localhost ~]# chmod 2770 /srv/projecta
[root@localhost ~]# ll -d /srv/projecta
drwxrws---. 2 root project 6 May  3 21:43 /srv/projecta

最終三個用戶都加入 project 這個群組,而這個群組的用戶均可在 /srv/projecta 目錄裡進行任何工作!

10.2:多人共管系統的環境:用 sudo

由於系統的工作比較複雜,經常有不同的用戶會共同管理一部系統,這在社群的實務運作上經常發現。因為管理系統時需要管理員 (root) 的權限, 本章之前讀者可以透過 su 來切換用戶,但如此一來就得要提供所有的用戶 root 的密碼,對於系統的運作來說,可能會有些許的問題。 例如某位用戶切換成 root 密碼後,不小心改了 root 的密碼,而且自己也忘記了改回來,則未來大家都不知道如何操作系統了。

相對於 su 需要瞭解新切換的使用者密碼 (常常是需要 root 的密碼), sudo 的執行則僅需要自己的密碼即可!甚至可以設定不需要密碼即可執行 sudo ! 由於 sudo 可以讓你以其他用戶的身份執行指令 (通常是使用 root 的身份來執行指令),因此並非所有人都能夠執行 sudo , 而是僅有規範到 /etc/sudoers 內的用戶才能夠執行 sudo 這個指令。

只有信任用戶才能夠操作 sudo 這個指令,因此一開始還是需要使用 root 的權限來管理 sudo 的使用權才行。 雖然 sudo 的設定檔為 /etc/sudoers,不過建議使用 visudo 來編輯較佳,因為 visudo 可以進行設定檔的語法檢驗功能。

[root@localhost ~]# visudo
## Allow root to run any commands anywhere
root                     ALL=(ALL)           ALL
使用者帳號  登入者的來源主機=(可切換的身份) 可下達的指令

大約在 98 行附近,讀者會看到上面的 root 開頭那行。由於僅有 root 這一行,亦即一開始僅有 root 可以執行 sudo 的意思。

例題:
  1. 如何讓 student 這個帳號可以執行 sudo 來轉換身份成為 root 進行系統管理?
  2. 利用 student 身份操作 sudo ,進行 grep student /etc/shadow 的行為
  3. 讓 student 操作 su - 時,輸入的是自己的密碼而非 root 密碼

除了單一個人的設定之外,在 /etc/sudoers 若有底下這一行,亦代表加入 wheel 群組的用戶也能夠操作 sudo 之意。

[root@localhost ~]# visudo
## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

例題:
  1. 測試一下 linuxuser1 能否操作 sudo 指令達成 tail /etc/shadow 任務?
  2. 將 linuxuser1 加入 wheel 群組內
  3. 再重新測試第 1 點任務。

10.3 主機的細部權限規劃:ACL 的使用

如果 10.1 小節最後的一個練習中, /srv/projecta 需要讓 student 這個帳號登入去『查看』資料而已,不能變更現有的權限設定, 此時該如何設計呢?這時就可以考慮 ACL (Access Control List, 存取控制列表) 的使用了!

10.3.1:什麼是 ACL 與如何支援啟動 ACL

ACL 是 Access Control List 的縮寫,主要的目的是在提供傳統的 owner,group,others 的 read,write,execute 權限之外的細部權限設定。ACL 可以針對單一使用者,單一檔案或目錄來進行 r,w,x 的權限規範,對於需要特殊權限的使用狀況非常有幫助。

ACL 主要可以針對幾個項目來加以控制:

  • 使用者 (user):可以針對使用者來設定權限;
  • 群組 (group):針對群組為對象來設定其權限;
  • 預設屬性 (mask):還可以針對在該目錄下在建立新檔案/目錄時,規範新資料的預設權限;

ACL 必須要配合檔案系統的掛載啟動才能生效,一般均將 acl 參數寫入 /etc/fstab 的第四欄位中。不過由於 ACL 幾乎為目前 Linux 標準支援的檔案系統參數, 因此讀者僅須查詢核心是否啟動 ACL 即可,已無須將 acl 參數寫入掛載設定中。

[root@localhost ~]# dmesg | grep -i acl
[    0.609488] systemd[1]: systemd 219 running in system mode. (+PAM +AUDIT 
 +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS 
 +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
[    1.763620] SGI XFS with ACLs, security attributes, no debug enabled

例題:(請注意,因為 xfs 預設已經啟動 ACL,且掛載參數不支援 acl,故使用 ext4 檔案系統解釋)
  • 建立一個新的大約有 500M 容量的 ext4 檔案系統,開機後預設掛載到 /data/ext4 目錄內
  • 同時強迫這個 ext4 檔案系統加上 ACL 的參數掛載。
  • 測試完畢後,請刪除此檔案系統喔!

10.3.2:ACL 的設定技巧

ACL 針對單一用戶的設定練習中,我們以『讓 student 可以讀取 /srv/projecta 』為範本來介紹。

[root@localhost ~]# ll -d /srv/projecta
drwxrws---. 2 root project 6 May  3 21:43 /srv/projecta

[root@localhost ~]# setfacl -m u:student:rx /srv/projecta
[root@localhost ~]# ll -d /srv/projecta
drwxrws---+ 2 root project 6 May  3 21:43 /srv/projecta

[root@localhost ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: project
# flags: -s-
user::rwx          <==預設的擁有者權限
user:student:r-x   <==針對 student 的權限
group::rwx         <==預設的群組權限
mask::rwx          <==預設的 mask 權限
other::---

如上所示,setfacl -m 為設定的指令與選項,而設定的項目則主要有:

  • 針對個人: u:帳號名稱:rwx-
  • 針對群組: g:群組名稱:rwx-

至於 getfacl 則是查閱 ACL 設定的指令。輸出結果與上述的設定項目類似,只是當帳號或群組名稱沒有寫的時候,代表為檔案擁有者的帳號與群組之意。 因此就能夠得到上述的結果。

至於 getfacl 輸出的結果中,有個 mask 的項目,10.1.4 所述,umask 為拿掉的權限,在 getfacl 當中,mask 則是可給予的權限之意。 預設 mask 會全部都給予~如果我們將 mask 拿掉只剩下 x 時,會發生的問題如下:

[root@localhost ~]# setfacl -m m::x /srv/projecta
[root@localhost ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: project
# flags: -s-
user::rwx
user:student:r-x                #effective:--x
group::rwx                      #effective:--x
mask::--x
other::---

由於 mask 的關係,因此 student 這個帳號雖然給予 rx 的權限,但是實際上可以取得的權限則僅有 x 而已 (觀察 effective 的輸出項目)。 此外,如果要取消掉這個設定值時,可以使用如下的方式處理。

[root@localhost ~]# setfacl -m m::rwx /srv/projecta
[root@localhost ~]# getfacl /srv/projecta

亦即重新設定進去即可。那如果使用 pro1 這個帳號實際在 /srv/projecta 操作時,會出現的權限狀態情況如下:

[root@localhost ~]# su - pro1
[pro1@localhost ~]$ cd /srv/projecta
[pro1@localhost projecta]$ mkdir newdir
[pro1@localhost projecta]$ touch newfile
[pro1@localhost projecta]$ ll -d new*
drwxrwsr-x. 2 pro1 project 6 May  4 00:37 newdir
-rw-rw-r--. 1 pro1 project 0 May  4 00:37 newfile

讀者們可以發現在 /srv/projecta 目錄內的新檔案並沒有預設的 ACL 設定值,因此 student 的權限很可能被修改掉而無法保持 rx 的權限設定。 此時,我們可以額外指定『預設的 ACL 權限』資訊,如下設定:

[root@localhost ~]# setfacl -m d:u:student:rx /srv/projecta
[root@localhost ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: project
# flags: -s-
user::rwx
user:student:r-x
group::rwx
mask::rwx
other::---
default:user::rwx
default:user:student:r-x
default:group::rwx
default:mask::rwx
default:other::---

若讀者發現設定錯誤,想要將某一條 ACL 的權限設定取消時,例如將 student 的規則取消,則可以使用如下的方式來處理:

[root@localhost ~]# setfacl -x u:student /srv/projecta

取消設定比較單純,不過要注意取消的情況得要使用 -x 這個選項,而非 -m 的選項。此外,由於取消設定是不需要處理權限的, 因此取消時,僅需要處理『 u:帳號 』或『 g:群組 』這樣就好了!那如果要將該檔案的所有 ACL 設定都取消時,可以使用底下的方式:

[root@localhost ~]# setfacl -b /srv/projecta
[root@localhost ~]# ll -d /srv/projecta/
drwxrws---. 3 root project 33 May  4 00:37 /srv/projecta/

讀者可以發現到,權限位置最末位的 + 號不見了,因為已經完整的取消的緣故。

例題:
  1. 有兩個群組需要建立,一個是老師的 myteacher 一個是學生的 mystudent,兩個群組建立時,請使用系統帳號的群組 GID 號碼範圍
  2. 兩個群組各有三個人,分別是 myteacher1 ~ myteacher3 以及 mystudent1 ~ mystudent3,請使用預設的情況建立好這六個帳號,同時注意, 六個人都需要有個別的次要群組支援
  3. 六個人的密碼均是 password 喔!
例題:
  1. mystudent1 ~ mystudent3 需要有共享目錄,該目錄名稱 /srv/myshare ,同時,除了 mystudent 具有完整的權限之外,其他人不可有任何權限。
  2. 由於 myteacher 的群組是老師,老師們需要進入 /srv/myshare 查閱學生的進度,但是不可干擾學生的作業,因此應該要給予 rx 的權限才對
  3. 但由於 myteacher3 並不是這個班級的老師,因此這個老師帳號不可以進入該目錄。

10.4:課後練習操作

前置動作:請使用 unit10 的硬碟進入作業環境,並請先以 root 身分執行 vbird_book_setup_ip 指令設定好你的學號與 IP 之後,再開始底下的作業練習。

請使用 root 的身份進行如下實做的任務。直接在系統上面操作,操作成功即可,上傳結果的程式會主動找到你的實做結果。 另外,因為題目是有連續性的,請依照順序完成題目,盡量不要跳著做。

  1. 請回答底下問答題,答案請寫入 /root/ans10.txt 當中:
    1. 一般我們在建立 linux 帳號時,哪三個檔案會記錄這個帳號的 UID, GID, 支援群組, 密碼等資訊?
    2. 一般帳號被建立後(假設帳號名稱為 myusername),基本上會有哪一個目錄與哪一個檔案會被建立?
    3. 若設定 umask 033 後,新建的檔案與目錄權限各為幾分?
    4. 在 /etc /var 與 /usr 裡面,各有一個不屬於任何人的檔案,請將檔案的完整檔名找出來,並寫下來
  2. 建立一個名為 /root/myaccount.sh 的大量建立帳號的腳本,這個腳本執行後,可以完成底下的事件:
    1. 會建立一個名為 mygroup 的群組
    2. 會依據預設環境建立 30 個帳號,帳號名稱為 myuser01 ~ myuser30 共 30 個帳號,且這些帳號會支援 mygroup 為次要群組
    3. 每個人的密碼會使用【 openssl rand -base64 6 】隨機取得一個 8 個字元的密碼, 並且這個密碼會被記錄到 /root/account.password 檔案中,每一行一個,且每一行的格式有點像【myuser01:AABBCCDD】
  3. 有個名為 gooduser 的帳號不小心被刪除了,還好,這個帳號的家目錄還存在。 請依據這個提示,重建這個帳號 (記住,UID與GID應該要回復到原本尚未被刪除前的狀態),且該用戶的密碼設定為 mypassword, 同時,這個帳號請重新設定為可以使用 sudo 的!
  4. 由於你管理的系統需要有專題群組的夥伴共同使用系統,因此你將這些專題夥伴加入同一個次要群組支援!
    1. 專題群組的名稱設為: myproject
    2. 專題組員的名稱分別為: mypro1, mypro2, mypro3,且這三個帳號都加入了 myproject 群組的次要支援
    3. 這三個帳號的密碼均為 MyPassWord
    4. 這個專題組員可共用 /srv/mydir 目錄,其他人則沒有任何權限
  5. 由於你幫學校老師管理 FTP 伺服器,這個伺服器的使用者不能提供可登入系統的 shell,但是可以使用 FTP 與 email 等網路服務:
    1. 帳號名稱為: ftpuser1, ftpuser2, ftpuser3,這三個帳號可以使用 ftp 網路功能,但是不能在系統前登入 tty 或使用終端機登入系統;
    2. 這三個帳號的密碼均為 MyPassWord
  6. 建立一個名為 mysys1 的系統帳號,且這個系統帳號 (1)不需要家目錄 (2)給予 /sbin/nologin 的 shell (3)也不需要密碼
  7. 修改新建帳號的預設資訊
    1. 讓未來新建的用戶,其家目錄預設都會有一個名為 web 的子目錄存在?
    2. 讓新建用戶的 history 預設可以記憶 5000 筆記錄(已存在帳號不受影響)
    3. 讓新建帳號的 shell 將使用 /sbin/nologin
  8. 特別目錄的權限應用:
    1. 剛剛建立的 /srv/mydir 目錄,在不更改原有的權限設定下 (因為原本就是給 myproject 群組用的), 現在,要讓加入 users 群組的帳號們,也能夠進入該目錄查閱資料 (只能進入與查閱,不能寫入),該如何處置?
    2. 那個 gooduser 的帳號,其實是老師的帳號,在不更改既有權限的情況下, gooduser 也需要能夠進入該目錄做任何事情, 且未來在 /srv/mydir 所新建立的任何檔案(或目錄)資料,gooduser 也能夠進行任何動作。(hint:就是有預設值的意思)

作業結果傳輸:請以 root 的身分執行 vbird_book_check_unit 指令上傳作業結果。 正常執行完畢的結果應會出現【XXXXXX;aa:bb:cc:dd:ee:ff;unitNN】字樣。若需要查閱自己上傳資料的時間, 請在作業系統上面使用: http://192.168.251.250 檢查相對應的課程檔案。

修改歷史:
  • 2016/05/04:跟基礎篇的帳號那章很像,不過加入了比較多的例題,同時提供了簡易的大量建置帳號的 shell script
  • 2017/04/02:趁著放假,趁著小孩去睡覺,來實驗一下增加的習題!大家加油練習吧!
2016/05/04以來統計人數
計數器
其他連結
環境工程模式篇
鳥園討論區
鳥哥舊站

今日 人數統計
昨日 人數統計
本月 人數統計
上月 人數統計