Joey's Notes: Access Control Lists
By Joey Prestia
Linux has the ability to use access control lists at the file level. This allows file owners and system administrators to define who has access and what level of access they have beyond the level of fliesystem permissions.
Assume that a company has a team of employees working on a project. Each employee, depending on their role and level of responsibility, needs a different set of permissions; this can be implemented via access control lists (another, and perhaps better term is discretionary access control lists.) In the event that the material is classified to some but not to all, these ACLs make things easy for the company in that security can be handled without the need to involve more people other than those directly concerned.
ACLs are available with the ext3 file system. By default, Red Hat Enterprise Linux 5 sets the capability for ACLs on all the ext3 partitions at install time. What this means is that if you create a new partition that was not in existence at install time and try to use access control lists on it, you can't: you will have to add the mount option ACL in the /etc/fstab file to make that feature available.
Most relevant commands support ACL lists, but some don't; if you're in doubt, you should check the man pages to make sure. "tar", for example, does not support access control lists.
Setting up a partition for ACLs
Let's walk through setting up and using ACLs to get the feel of the fine grained-level of control that is available by using access control lists. Since I have unpartitioned space on this drive, I will run through the process of setting up ACLs on the new partition:
[root@localhost ~]# fdisk /dev/hda [root@localhost ~]# partprobe [root@localhost ~]# mkfs.ext3 -L /srv/data /dev/hda10
Next, I need to edit the /etc/fstab file and add the new partition and the mount options for access control lists.
[root@localhost ~]# vi /etc/fstab LABEL=/ / ext3 defaults 1 1 LABEL=/boot /boot ext2 defaults 1 2 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /dev/shm tmpfs defaults 0 0 LABEL=/home /home ext3 usrquota,grpquota 1 2 proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 LABEL=/tmp /tmp ext3 defaults 1 2 LABEL=/usr /usr ext3 defaults 1 2 LABEL=/var /var ext3 defaults 1 2 LABEL=SWAP-hda3 swap swap defaults 0 0 LABEL=/srv/data /srv/data ext3 defaults,acl 1 1
After that, I'll make a directory and mount our new partition.
[root@localhost ~]# mkdir /srv/data [root@localhost ~]# mount -a
Now, I'll add a group called "programming", and create several users belonging to that group: "teamleader", "prog1", "prog2", and "tech". I'll also need to change the ownership and permissions on this directory to those appropriate for our new group. As a result, files created in this directory will belong to group "programming".
[root@localhost ~]# groupadd programming [root@localhost ~]# chown .programming /srv/data [root@localhost ~]# chmod 2770 /srv/data [root@localhost ~]# useradd teamleader -G programming [root@localhost ~]# passwd teamleader [root@localhost ~]# useradd prog1 -G programming [root@localhost ~]# passwd prog1 [root@localhost ~]# useradd prog2 -G programming [root@localhost ~]# passwd prog2 [root@localhost ~]# useradd tech -G programming [root@localhost ~]# passwd tech [root@localhost ~]# cd /srv/data [root@localhost data]# ls lost+found [root@localhost data]# su teamleader [teamleader@localhost data]$ [teamleader@localhost data]$ touch project [teamleader@localhost data]$ chmod 700 project
At this point the teamleader has created a project and restricted access to it via the filesystem.
Using getfacl
The command "getfacl" shows the ACL/permission information for a specified file or directory:
[teamleader@localhost data]$ getfacl project # file: project # owner: teamleader # group: programming user::rwx group::--- other::---
Using setfacl
This command sets access controls. There are three fields on the command line that you need to be aware of:
identifier:user/group:permissions
The identifier can be expressed as:
u - will affect the access rights of the specified user g - will affect the access rights of the specified group o - will affect the access rights of all others m - will affect the effective rights mask
user/group is the intended username or groupname, which can also be expressed as a UID or GID.
permissions are:
r or 6 - read access w or 4 - write access x or 1 - execute permission - or 0 - no permissions
Of course permissions may be combined such as r-x or 5 depending on what you want. Using the command in its simplest form looks like this:
setfacl [options] identifier:user/group: permissions filename
Creating ACLs
[teamleader@localhost data]$ setfacl -m u:prog1:rwx project [teamleader@localhost data]$ setfacl -m u:prog2:rw- project [teamleader@localhost data]$ getfacl project # file: project # owner: teamleader # group: programming user::rwx user:prog1:rwx user:prog2:rw- group::--- mask::rwx other::---
At this point we promoted our programmers permissions: "prog1" can now read, write, and execute; and "prog2" has read and write access. Notice also that the output from "getfacl" now has a "mask" field at the bottom: the mask is a maximum rights level and can be used to immediately restrict the permissions on this file. In addition, if you do an "ls -l", the listing will show a "+" at the end of the permissions for each filename that has ACLs enabled:
[teamleader@localhost data]$ ls -l total 13 drwx------ 2 root programming 12288 Mar 19 21:59 lost+found -rwxrw----+ 1 teamleader programming 0 Mar 22 20:30 project [teamleader@localhost data]$
The "programming" group needs at least read permissions on this file, since other programmers will need to see what is in the document. If we do not specify the group explicitly when we execute the "setfacl" command, it is assumed as you can see below:
[teamleader@localhost data]$ setfacl -m g::r project [teamleader@localhost data]$ getfacl project # file: project # owner: teamleader # group: programming user::rwx user:prog1:rwx user:prog2:rw- group::r-- mask::rwx other::---
Restricting effective rights
By changing the mask, I can change the current effective permissions to the most restrictive level as defined by the mask and have those become the effective permissions. Even if a user or group has permissions in excess of what the effective mask is set to, the mask will restrict their effective rights.
[teamleader@localhost data]$ setfacl -m mask::r project [teamleader@localhost data]$ getfacl project # file: project # owner: teamleader # group: programming user::rwx user:prog1:rwx #effective:r-- user:prog2:rw- #effective:r-- group::r-- mask::r-- other::---
Removing a user from an ACL
If we want to remove one of our programmers - e.g., "prog1" - from the ACL for this project and revert his permissions back to what the group has, this would be done as follows:
[teamleader@localhost data]$ setfacl -x u:prog1: project [teamleader@localhost data]$ getfacl project # file: project # owner: teamleader # group: programming user::rwx user:prog2:rw- group::r-- mask::rw- other::---
The "-x" switch removes the associated user, group, or other, from the associated access control list - so "prog1" now only has group level access (and probably a pay cut to go with it).
Transfer of ACL attributes from a specification file
What if we were to store our ACL attributes in a file containing the line "u:prog1:rwx"? We could use the "-M" switch to pass the attributes on to a new file.
[teamleader@localhost data]$ touch file [teamleader@localhost data]$ echo "u:prog1:rwx" > acl [teamleader@localhost data]$ setfacl -M acl file [teamleader@localhost data]$ getfacl file # file: file # owner: teamleader # group: programming user::rw- user:prog1:rwx group::rw- mask::rwx other::r--
We have successfully transferred the ACL attributes in the file "acl" to the empty file "file". Did you notice how the effective rights mask jumped up from "rw-" to "rwx"? If you did not want the effective rights mask to change when you modify permissions you could use the "-n" option alongside your other options to prevent it.
Copying the ACLs from one file to another
To copy a file's ACL to another file you would execute "getfacl
filewith.acl | setfacl -b -n -M - fileneeding.acl
" as I will show
below. The last "-" is important; it tells "setfacl" to read the data from
standard input, which is being supplied by the preceding pipe.
[teamleader@localhost data]$ getfacl filewith.acl # file: filewith.acl # owner: teamleader # group: programming user::rw- user:prog1:rwx group::rw- mask::rwx other::r-- [teamleader@localhost data]$ touch fileneeding.acl [teamleader@localhost data]$ getfacl filewith.acl | setfacl -b -n -M - fileneeding.acl [teamleader@localhost data]$ getfacl fileneeding.acl # file: fileneeding.acl # owner: teamleader # group: programming user::rw- user:prog1:rwx group::rw- mask::rwx other::r--
Inheriting a directory's ACL from the parent
Directories can have a default ACL, which defines the access permissions that files under the directory inherit when they are created. A default ACL affects subdirectories as well as files. First, let's set up a directory with a set of default permissions. Access defaults are created by using the "-d" switch when modifying a directory.
[teamleader@localhost data]$ mkdir work [teamleader@localhost data]$ setfacl -d -m g::r-x work/ [teamleader@localhost data]$ getfacl work/ # file: work # owner: teamleader # group: programming user::rwx group::rwx other::r-x default:user::rwx default:group::r-x default:other::r-x
Observe as I create a child directory below, "work/week1". Notice that "week1" will inherit the default ACL permissions of the parent directory "work":
[teamleader@localhost data]$ mkdir work/week1 [teamleader@localhost data]$ getfacl work/week1/ # file: work/week1 # owner: teamleader # group: programming user::rwx group::r-x other::r-x default:user::rwx default:group::r-x default:other::r-x
Inheriting a file's default ACLs from the parent
Last of all, let's see how these defaults propagate to a simple file created in the "work/week1" directory. I'll show the parent's ACL first, then create the file:
[teamleader@localhost data]$ getfacl work/week1/ # file: work/week1 # owner: teamleader # group: programming user::rwx group::r-x other::r-x default:user::rwx default:group::r-x default:other::r-x [teamleader@localhost data]$ touch work/week1/day1 [teamleader@localhost data]$ getfacl work/week1/day1 # file: work/week1/day1 # owner: teamleader # group: programming user::rw- group::r-- other::r-- [teamleader@localhost data]$ umask 0002
Note that the file was created with an active umask of 0002. This means that the file should have had permissions of 664; instead it was created with default permissions of 644 because of the default ACL on the directory and the inheriting of the ACL from the parent directory.
This is not an exhaustive list of all the possibilities; however, just these basics should be enough to get you started using access control lists. ACLs can be used to regulate permissions for special situations where regular Linux permissions will not quite handle the job; they can also lighten the administrative overhead when project-level managers learn to use them correctly and effectively. In addition, ACLs can be a valuable tool in any administrator's toolbox to help regulate security.
Resources
- POSIX Access Control Lists on Linux
- SUSE Linux Administration Guide
- Michael Jang's book "Red Hat Certified Engineer Linux Study Guide", 5th Edition
- Mark G. Sobell's book "A Practical Guide to Red Hat Linux", 3rd Edition
Talkback: Discuss this article with The Answer Gang
Joey was born in Phoenix and started programming at the age fourteen on a Timex Sinclair 1000. He was driven by hopes he might be able to do something with this early model computer. He soon became proficient in the BASIC and Assembly programming languages. Joey became a programmer in 1990 and added COBOL, Fortran, and Pascal to his repertoire of programming languages. Since then has become obsessed with just about every aspect of computer science. He became enlightened and discovered RedHat Linux in 2002 when someone gave him RedHat version six. This started off a new passion centered around Linux. Currently Joey is completing his degree in Linux Networking and working on campus for the college's RedHat Academy in Arizona. He is also on the staff of the Linux Gazette as the Mirror Coordinator.