1. 程式人生 > >LINUX ACL 學習筆記

LINUX ACL 學習筆記

一、 為什麼要使用ACL
先讓我們來簡單地複習一下Linux的檔案許可權。


在 linux下,對一個檔案(或者資源)可以進行操作的物件被分為三類: file owner(檔案

的擁有者),group(組,注意不一定是檔案擁有者所在的組), other (其他)而對於每一類

別又分別定義了read, write and execute/search 許可權 (這裡不討論SUID, SGID以及

Sticky bit的設定)

通過ls -l命令就我們就可以列出一個檔案的許可權

程式碼:

[[email protected] ~]$ ls -l
-rw-rw---- 1 leonard admin 0 Jul 3 20:12 test.txt

在這裡說明了對於test.txt這個檔案leonard使用者(由於是file owner)擁有read & write
許可權. 所有屬於admin 組的使用者(group)擁有read & write 許可權. 其他任何使用者(other)
對於檔案沒有任何的許可權

如果我們現在希望john這個使用者也可以對test.txt檔案進行讀寫操作. 我自己大概會想到
以下幾種辦法 (這裡假設john不屬於admin group)

1. 給檔案的other類別增加讀和寫的許可權. 這樣由於john會被歸為other類別,那麼
他也將擁有讀寫的許可權。
2. 將john加入到admin group. 那麼john會被歸為group類別,那麼他將擁有讀寫的許可權。
3. 設定sudo, 使john能夠以leonard的身份對test.txt進行操作,從而獲得讀寫許可權。

第一種做法的問題在於所有使用者都將對test.txt擁有讀寫操作,顯然這種做法不可取。
第二種做法的問題在於john被賦予了過多的許可權.所有屬於admin組的檔案,john都可以擁
有其等同的許可權了。
第三種做法雖然可以達到只限定john使用者一人擁有對test.txt檔案的讀寫許可權.但是需要
對sudoers檔案進行嚴格的格式控制. 而且當檔案數量和使用者很多的時候,這種方法就相當
地不靈活了。
看來好像都沒有一個很好的解決方案. 其實問題就出在Linux 檔案許可權裡面,對於other的
定義過於廣泛,以至於很難把許可權限定於一個不屬於file owner和group的使用者身上. 那麼
Access Control List (ACL)就是用來幫助我們解決這個問題的。

簡單地來說ACL就是可以設定特定使用者或者使用者組對於一個檔案/資料夾的操作許可權. 需要
掌握的命令也只有三個: getfacl, setfacl, chacl

在接下去討論之前大家可以先安裝上ACL的RPM包
程式碼:


# rpm -ivh libacl-2.2.39-1.1 acl-2.2.39-1.1.i386.rpm

如果配置好了yum可以直接安裝這兩個包

# yum -y install libacl acl

另外還需要磁碟分割槽的支援
永久啟用acl。我這裡以自己的分割槽/data為例
# vi /etc/fstab
LABEL=/data         /data        ext3    defaults,acl      1 2

在啟用了acl引數之後重新載入/data分割槽
# mount -o remount /data
# cat /etc/mtab | grep /data
/dev/sda5 /data ext3 rw,acl 0 0
出現上面的資訊代表分割槽的acl功能已經正常載入

二、ACL的名詞定義

先來看看在ACL裡面每一個名詞的定義.這些名詞我大多從man page上摘下來雖然有些枯燥,
但是對於理解下面的內容還是很有幫助的

ACL 是由一系列的Access Entry所組成的. 每一條Access Entry定義了特定的類別可以對
檔案擁有的操作許可權. Access Entry有三個組成部分: Entry tag type, qualifier 
(optional), 許可權

我們先來看一下最重要的Entry tag type, 它有以下幾個型別

ACL_USER_OBJ: 相當於Linux裡file_owner的許可權
ACL_USER: 定義了額外的使用者可以對此檔案擁有的許可權
ACL_GROUP_OBJ: 相當於Linux裡group的許可權
ACL_GROUP: 定義了額外的組可以對此檔案擁有的許可權
ACL_MASK: 定義了ACL_USER, ACL_GROUP_OBJ和ACL_GROUP的最大許可權 (這個我下面還會專門討論)
ACL_OTHER: 相當於Linux裡other的許可權

讓我們來據個例子說明一下. 下面我們就用getfacl命令來檢視一個定義好了的ACL檔案

程式碼:

[[email protected] data]# getfacl test.txt
# file: test.txt
# owner: root
# group: family
user::rw-
user:zyq:rw-
group::rw-
group:jackuser:rw-
mask::rw-
other::---

前面三個以#開頭的定義了檔名,檔案所有者和檔案擁有組. 這些資訊沒有太大的作用,我
們可以用 --omit-header來省略掉
user::rw- 定義了ACL_USER_OBJ, 說明file owner擁有讀和寫的許可權
user:zyq:rw- 定義了ACL_USER,這樣使用者zyq就擁有了對檔案的讀寫許可權,實現了我們一開始要達到的目的
group::rw- 定義了ACL_GROUP_OBJ,說明檔案的group擁有read和write 許可權
group: jackuser:rw- 定義了ACL_GROUP,使得jackuser組擁有了對檔案的read 和write許可權
mask::rw- 定義了ACL_MASK的許可權為read and write
other::--- 定義了ACL_OTHER的沒有任何許可權操作此檔案

從這裡我們就可以看出ACL提供了我們可以定義特定使用者和使用者組的功能. 那麼接下來我們就來
看一下如何設定一個檔案的ACL


三、 如何設定ACL檔案

首先我們還是要講一下設定ACL檔案的格式. 從上面的例子中我們可以看到每一個Access Entry
都是由三個被:號分隔開的欄位所組成. 第一個就是Entry tag type

user 對應了ACL_USER_OBJ和ACL_USER
group 對應了ACL_GROUP_OBJ和ACL_GROUP
mask 對應了ACL_MASK
other 對應了ACL_OTHER

第二個欄位稱之為qualifier.也就是上面例子中的zyq和jackuser組.它定義了特定使用者和使用者組
對於檔案的許可權.這裡我們也可以發現只有user和group才有qualifier,其他的都為空

第三個欄位就是我們熟悉的許可權了. 它和Linux的許可權一樣定義,這裡就不多講了

下面我們就來看一下怎麼設定test.txt這個檔案的ACL讓它來達到我們上面的要求

一開始檔案沒有ACL的額外屬性

程式碼:

[[email protected] data]# ll test.txt                   
-rw-r--r-- 1 root root 0 12-27 22:55 test.txt
[[email protected] data]# getfacl test.txt                   
# file: test.txt
# owner: root
# group: root
user::rw-
group::r--
other::r--

[[email protected] data]# getfacl -c test.txt     
user::rw-
group::r--
other::r--

我們先讓使用者zyq擁有對test.txt檔案的讀寫許可權

程式碼:

[[email protected] data]# setfacl -m u:zyq:rw test.txt
[[email protected] data]# getfacl -c test.txt         
user::rw-
user:zyq:rw-
group::r--
mask::rw-
other::r--

這時我們就可以看到zyq使用者在ACL裡面已經擁有了對檔案的讀寫許可權. 這個時候如果我們
檢視一下linux的許可權我們還會發現一個不一樣的地方

程式碼:

[[email protected] data]# ll test.txt
-rw-rw-r--+ 1 root root 0 12-27 22:55 test.txt

在檔案許可權的最後多了一個+號. 當任何一個檔案擁有了ACL_USER或者ACL_GROUP的值以後我
們就可以稱它為ACL檔案.這個+號就是用來提示我們的
我們還可以發現當一個檔案擁有了ACL_USER或者ACL_GROUP的值時ACL_MASK同時也會被定義

接下來我們來設定jackuser組擁有read 許可權

程式碼:

[[email protected] data]# ll test.txt
-rw-rw-r--+ 1 root root 0 12-27 22:55 test.txt
[[email protected] data]#
[[email protected] data]# setfacl -m g:jackuser:r test.txt
[[email protected] data]# getfacl -c test.txt
user::rw-
user:zyq:rw-
group::r--
group:jackuser:r--
mask::rw-
other::r--

[[email protected] data]# ll test.txt
-rw-rw-r--+ 1 root root 0 12-27 22:55 test.txt

到這裡就完成了我們上面講到的要求.是不是很簡單呢


四、ACL_MASK 和 Effective 許可權

這裡需要重點講一下ACL_MASK, 因為這是掌握ACL的另一個關鍵

在Linux 檔案許可權裡面大家都知道比如對於rw-rw-r--來說, 第二組中的那個rw-是指檔案
組的許可權. 但是在ACL裡面這種情況只是在ACL_MASK不存在的情況下成立. 如果檔案有ACL_MASK
值,那麼當中那個rw-代表的就是mask值而不再是group 許可權了

讓我們來看下面這個例子

程式碼:

[[email protected] data]# ll test.sh
-rwxrw-r-- 1 root family 0 12-27 23:04 test.sh

這裡說明test.sh檔案只有file owner: root擁有read, write, execute/search 許可權. Family
組只有讀和寫的許可權。現在我們想讓使用者zyq也對test.sh具有和root一樣的許可權。

程式碼:

[[email protected] data]# setfacl  -m u:zyq:rwx test.sh
[[email protected] data]# getfacl -c test.sh
user::rwx
user:zyq:rwx
group::rw-
mask::rwx
other::r--

這裡我們看到zyq已經擁有了rwx的許可權. mask值也被設定為rwx.那是因為它規定了ACL_USER, 
ACL_GROUP和ACL_GROUP_OBJ的最大值
現在我們再來看test.sh的Linux 許可權, 它已經變成了

程式碼:

[[email protected] data]# ll test.sh
-rwxrwxr--+ 1 root family 0 12-27 23:04 test.sh

那麼如果現在family組的使用者想要執行test.sh的程式會發生什麼情況呢? 它會被許可權 deny.原
因在於實際上family組的使用者只有讀和寫的許可權.這裡當中顯示的rwx是ACL_MASK的值而不是group
的許可權

所以從這裡我們就可以知道,如果一個檔案後面有+標記,我們都需要用getfacl來確認它的權
限,以免發生混淆

下面我們再來繼續看一個例子
假如現在我們設定test.sh的mask為read only,那麼family組的使用者還會有write 許可權嗎?

程式碼:

[[email protected] data]# setfacl -m mask::r test.sh
[[email protected] data]# getfacl -c test.sh
user::rwx
user:zyq:rwx                    #effective:r--
group::rw-                      #effective:r--
mask::r--
other::r--

這時候我們可以看到ACL_USER和ACL_GROUP_OBJ旁邊多了個#effective:r--, 這是什麼意思呢?
讓 我們再來回顧一下ACL_MASK的定義. 它規定了ACL_USER, ACL_GROUP_OBJ和ACL_GROUP的最大
許可權.那麼在我們這個例子中他們的最大許可權也就是read only.雖然我們這裡給ACL_USER和ACL_GROUP_OBJ
設定了其他許可權,但是他們真正有效果的只有read許可權.

這時我們再來檢視test.sh的Linux 檔案許可權時它的group 許可權也會顯示其mask的值(i.e. r--)

程式碼:

[[email protected] data]# ll test.sh
-rwxr--r--+ 1 root family 0 12-27 23:04 test.sh

五、 Default ACL

上面我們所有講的都是Access ACL, 也就是對檔案而言. 下面我簡單講一下Default ACL. Default ACL
是指對於一個目錄進行Default ACL設定,並且在此目錄下建立的檔案都將繼承此目錄的ACL

同樣我們來做一個試驗說明
比如現在leonard使用者建立了一個dir目錄

程式碼:

[[email protected] data]$ mkdir mydir

我希望所有在此目錄下建立的檔案都可以被smbuser使用者所訪問. 那麼我們就應該對mydir目錄設定Default ACL


我 先利用root使用者在/data/建立一個mydir的資料夾,然後將這個資料夾的default user許可權設定為smbuser可以rw- 以root身份在mydir目錄下建立一個test.txt的檔案。其他的不做限制,然後切換到smbuser。發現smbuser使用者可以修改 test.txt檔案中的內容但是無法在mydir目錄中建立和刪除檔案/資料夾

程式碼:

[[email protected] data]# id
uid=0(root) gid=0(root) groups=0(root)
[[email protected] data]# ll mydir/
總計 0
[[email protected] data]# getfacl mydir/
# file: mydir/
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

[[email protected] data]# setfacl -m d:smbuser:rw mydir/
[[email protected] data]# getfacl mydir/
# file: mydir/
# owner: root
# group: root
user::rwx
group::r-x
other::r-x
default:user::rwx
default:user:smbuser:rw-
default:group::r-x
default:mask::rwx
default:other::r-x

[[email protected] data]# cd mydir/
[[email protected] mydir]# touch test.txt
[[email protected] mydir]# su - smbuser
[[email protected] ~]$ cd /data/mydir/
[[email protected] mydir]$ touch a
touch: 無法建立 “a”: 許可權不夠
[[email protected] mydir]$ rm test.txt
rm: 無法刪除 “test.txt”: 許可權不夠
[[email protected] mydir]$ echo hello world>>test.txt
[[email protected] mydir]$ cat test.txt
hello world


這 裡我們可以看到ACL定義了default選項, smbuser使用者擁有了default的read, write, excute/search 許可權.但是卻無法刪除和建立檔案。經過試驗,發現還必須將mydir目錄的ACL_USER修改為smbuser後,切換到smbuser使用者才能夠在 mydir目錄中建立和刪除檔案/資料夾

[[email protected] data]# setfacl  -m u:smbuser:rwx mydir/
[[email protected] data]# getfacl -c mydir/
user::rwx
user:smbuser:rwx
group::r-x
mask::rwx
other::r-x
default:user::rwx
default:user:smbuser:rw-
default:group::r-x
default:mask::rwx
default:other::r-x

[[email protected] data]# su - smbuser
[[email protected]erver ~]$ cd /data/mydir/
[[email protected] mydir]$ touch a
[[email protected] mydir]$ ll
總計 4
-rw-rw-r--+ 1 smbuser family  0 12-27 23:43 a
-rw-rw-r--+ 1 root    root   19 12-27 23:33 test.txt
[[email protected] mydir]$ rm * -rf
[[email protected] mydir]$


下面的試驗我們看到在mydir下建立的檔案或資料夾都自動的加上了default的許可權

[[email protected] mydir]# su - smbuser
[[email protected] ~]$ cd /data/mydir/
[[email protected] mydir]$ ll
總計 0
-rw-rw-r--+ 1 root root 0 12-27 23:48 a
-rw-rw-r--+ 1 root root 0 12-27 23:48 test.tt
[[email protected] mydir]$ rm * -rf
[[email protected] mydir]$ touch test.txt
[[email protected] mydir]$ ll
總計 0
-rw-rw-r--+ 1 smbuser family 0 12-27 23:48 test.txt
[[email protected] mydir]$ getfacl -c test.txt
user::rw-
user:smbuser:rw-
group::r-x                      #effective:r--
mask::rw-
other::r--

[[email protected] mydir]$ mkdir smbuserdir
[[email protected] mydir]$ getfacl -c smbuserdir/
user::rwx
user:smbuser:rw-
group::r-x
mask::rwx
other::r-x
default:user::rwx
default:user:smbuser:rw-
default:group::r-x
default:mask::rwx
default:other::r-x

[[email protected] mydir]$ ll
總計 4
drwxrwxr-x+ 2 smbuser family 4096 12-27 23:49 smbuserdir
-rw-rw-r--+ 1 smbuser family    0 12-27 23:48 test.txt


六、 ACL 相關命令

前 面的例子中我們都注意到了getfacl命令是用來讀取檔案的ACL, setfacl是用來設定檔案的Acess ACL. 這裡還有一個chacl是用來改變檔案和目錄的Access ACL and Default ACL. 它的具體引數大家可以去看man page. 我只想提及一下chacl -B. 它可以徹底刪除檔案或者目錄的ACL屬性(包括Default ACL). 比如你即使用了setfacl -x刪除了所有檔案的ACL屬性,那個+號還是會出現在檔案的末尾.所以正確的刪除方法應該是用chacl -B


用cp來複制檔案的時候我們現在可以加上-p選項.這樣在拷貝檔案的時候也將拷貝檔案的ACL屬性.對於不能拷貝的ACL屬性將給出警告

mv命令將會預設地移動檔案的ACL屬性. 同樣如果操作不允許的情況下會給出警告


七. 需要注意的幾點

如果你的檔案系統不支援ACL的話,你也許需要重新mount你的file system
mount -o remount, acl [mount point]

如果用chmod命令改變Linux 檔案許可權的時候相應的ACL值也會改變.反之改變ACL的值,相應的檔案許可權也會改變

八. 參考資料

1. man acl 個人感覺man page已經講的比較詳細,只是上面名詞比較多看起來會比較繁瑣
2. http://www.suse.de/~agruen/acl/linux-acls/online/ 如果你英語不錯的話可以看一下這篇關於POSIX ACL的介紹,上面有許多不錯的例子