April 23, 2009

Access Control List

What are ACLs and why would you want to use them?

ACLs are Access Control Lists for files and directories. ACLs are an addition to the standard Unix file permissions (r,w,x,-) for User, Group, and Other. ACLs give users and administrators flexibility and fine-grained control over who can read, write, and execute files. This can all be done without adding mysterious groups and pestering the system administrator.

Commercial Unix operating systems (except SCO) have all had ACL functionality for quite awhile. Microsoft's NTFS also has similar capabilities. The new Linux 2.6 kernel supports ACLs for EXT2, EXT3, XFS, JFS, and ReiserFS.

Fedora Core 10, Red Hat's first distribution with a 2.6 kernel, is a good vehicle for taking Linux ACLs for a test drive. This document is a basic HOWTO/tutorial on using ACLs with Fedora.


Assumptions

* You are using Fedora Core 10
* You have another partition besides /, /boot, and swap defined, or some unpartitioned free space on one of your disks
* You are using the EXT2, EXT3, or XFS filesystems
* You can login as root

If you have no free space on the disk, and all of your files and binaries are located in the root ( / ) partition, then you may not want to experiment with ACLs.

Note: ReiserFS cannot be mounted with the "acl" option, and jfs_mkfs appears to be seriously broken. Therefore, this HOWTO will be limited to EXT2, EXT3, and XFS.

Getting Started

Assuming you have an EXT2 or EXT3 partition that you are willing to use for testing, we can get started. On my test machine, I have the following available partitions:

* /dev/hda5 /home (ext3)
* /dev/hda9 /XFS (xfs)

For the examples in this HOWTO, I will be using the home directory of user "vinod", which is /home/vinod. Note that this directory belongs to a separate Linux partition, not the the root ( / ) partition. If you have some extra unpartitioned space on one of your disks, this would be a good time to create a test partition. You can do this with the fdisk command, then you can format it with the mke2fs command. Make sure you read up on all the required steps before you do this, otherwise you can nuke your system, disk, or data!

You will need to unmount the partitions of your choice, and then remount them with the "acl" option. First, I made a copy of my /etc/fstab file:

[root@fc10 root]# cp -v /etc/fstab /etc/fstab.org

`/etc/fstab' -> `/etc/fstab.org'

Then, I made the following modifications in red to the /etc/fstab config file. For clarity, I am only including hard disk entries:

LABEL=/ / ext3 defaults 1 1
LABEL=/boot /boot ext3 defaults 1 2
LABEL=/home /home ext3 rw,acl 1 2
LABEL=/tmp /tmp ext3 defaults 1 2
LABEL=/usr /usr ext3 defaults 1 2
LABEL=/var /var ext3 defaults 1 2
/dev/hda8 swap swap defaults 0 0
/dev/hdd1 /Data ext3 ro,noatime 1 2
LABEL=/XFS /XFS xfs rw,noatime 0 2

Now, you will need to remount the /home partition with the "acl" option. The easiest way to do this is with the "remount" option, since it will work even while the partition is in use:

[root@fc10 root]# mount -v -o remount /home

/dev/hda5 on /home type ext3 (rw,acl)

Another way to remount the partition with the "acl" option is to make sure that nobody else is on the sytem and the /home partition is not in use, then unmount, then mount the partition:

[root@fc10 root]# umount /home

[root@fc10 root]# mount /home

[root@fc10 root]# mount -l

/dev/hda2 on / type ext3 (rw) [/]
/dev/hda1 on /boot type ext3 (rw) [/boot]
/dev/hda5 on /home type ext3 (rw,acl) [/home]
/dev/hda7 on /tmp type ext3 (rw) [/tmp]
/dev/hda3 on /usr type ext3 (rw) [/usr]
/dev/hda6 on /var type ext3 (rw) [/var]
/dev/hdd1 on /Data type ext3 (ro,noatime) []
/dev/hda9 on /XFS type xfs (rw,noatime) [/XFS]

If you had trouble unmounting your target partitions, you may need to drop to single user mode with the init 1 command. This should allow you to unmount the filesystems. After that, you can remount the filesystems and issue an init 3 or init 5 command to put you back into your regular operating environment.

Using ACLs

Now, we can actually start using ACLs. The basic commands that we are interested in are:

* getfacl
* setfacl

We will first look at the getfacl command. The owner of the directory we will be working with is "vinod", and the guest user will be "pundir" and the guest group will be "STN". First, create a test file, then look at the permissions and the ACL:

[vinod@fc10 vinod]$ cd /home/vinod

[vinod@fc10 vinod]$ cp /etc/services pizza


[vinod@fc10 vinod]$ ls -l pizza
-rw-r--r-- 1 vinod vinod 19936 May 28 16:59 pizza

[vinod@fc10 vinod]$ getfacl pizza

# file: pizza
# owner: vinod
# group: vinod
user::rw-
group::r--
other::r--

So far, there is nothing very exciting to see. Now, let's change the ACL so that user "pundir" can read and write to the file:

[vinod@fc10 vinod]$ setfacl -m u:pundir:rw- pizza

[vinod@fc10 vinod]$ getfacl pizza

# file: pizza
# owner: vinod
# group: vinod
user::rw-
user:pundir:rw-
group::r--
mask::rw-
other::r--

[vinod@fc10 vinod]$ ls -l pizza

-rw-rw-r--+ 1 vinod vinod 19936 May 28 16:59 pizza

You will notice that there is now an extra user entry in the ACL, and there is a "+" next to the file in the output from the ls command. The "+" indicates that an ACL has been applied to the file or directory. Now, let's add a group ("STN") and another user ("varinder") to the ACL for pizza:

[root@fc10 vinod]# setfacl -m u:varinder:r--,g:STN:r-- pizza


[root@fc10 vinod]# getfacl pizza

# file: pizza
# owner: vinod
# group: vinod
user::rw-
user:pundir:rw-
user:varinder:r--
group::r--
group:STN:r--
mask::rw-
other::r--

Hmmm...what's the mask entry? This is the effective rights mask. This entry limits the effective rights granted to all ACL groups and ACL users. The traditional Unix User, Group, and Other entries are not affected. If the mask is more restrictive than the ACL permissions that you grant, then the mask takes precedence. For example, let's change the mask to "r--" and give user "varinder" and group "STN" the permissions rwx, and see what happens:

[vinod@fc10 vinod]$ setfacl -m u:varinder:rwx,g:STN:rwx pizza


[vinod@fc10 vinod]$ setfacl -m mask::r-- pizza


[vinod@fc10 vinod]$ getfacl --omit-header pizza

user::rw-
user:pundir:rw- #effective:r--
user:varinder:rwx #effective:r--
group::r--
group:STN:rwx #effective:r--
mask::r--
other::r--

The ACL now shows an "effective" rights mask. Even though "varinder" has been given rwx permissions, he actually only has r-- permissions because of the mask.

In most cases, I want the effective mask to allow whatever permissions I granted to named users and groups, so my mask will be rw- or rwx. I will reset it like this:

[vinod@fc10 vinod]$ setfacl -m m::rw- pizza

[vinod@fc10 vinod]$ getfacl --omit pizza

user::rw-
user:pundir:rw-
user:varinder:rw-
group::r--
group:STN:rwx #effective:rw-
mask::rw-
other::r--

What about using the setfacl command to change normal User, Group, and Other permissions? No problem! This can be used instead of chmod:

[vinod@fc10 vinod]$ setfacl -m u::rwx,g::rwx,o:rwx pizza


[vinod@fc10 vinod]$ ls -l pizza

-rwxrwxrwx+ 1 vinod vinod 19965 May 29 09:31 pizza



[vinod@fc10 vinod]$ getfacl --omit pizza

user::rwx
user:pundir:rw-
user:varinder:rw-
group::rwx
group:STN:rwx
mask::rwx
other::rwx

Note that the mask changed! Whenever you change the permissions of a user or a group with setfacl, the mask is changed to match. Therefore, if you want a restrictive mask, it must be applied after the user and group permissions are modified.

Another thing to keep in mind is that the chmod command does not alter the file's ACL...the ACL information will remain intact, except that the mask entry can change as described above.


Remove Specific Entries from an ACL


You can remove specific ACL entries with the -x option. In this example, we will remove the entry for user "varinder" and user "pundir" but leave the other entries alone:

[vinod@fc10 vinod]$ getfacl --omit pizza

user::rwx
user:pundir:rw-
user:varinder:rw-
group::rwx
group:STN:rwx
mask::rwx
other::rwx

[vinod@fc10 vinod]$ setfacl -x u:varinder,u:pundir pizza

[vinod@fc10 vinod]$ getfacl --omit pizza

user::rwx
group::rwx
group:STN:rwx
mask::rwx
other::rwx

Remove Entire ACL

To completely remove an ACL from a file or directory:

[vinod@fc10 vinod]$ setfacl -b pizza

You can also use:

[vinod@fc10 vinod]$ setfacl --remove-all pizza

Using the --set Option

If you want to explicitly set all of the file permissions on a file or a group of files, you must use the --set option. This is different from the -m option, which only modifies the existing ACL. The --set option replaces all permissions and ACLs with the new values. When you use the --set option, all of the User, Group, and Other permissions must be defined. Here is an example:

[vinod@fc10 vinod$ setfacl --set u::rw,g::rw,o::-,u:varinder:r pizza

[vinod@fc10 vinod]$ getfacl --omit pizza user::rw- user:varinder:r-- group::rw- mask::rw- other::---

Using setfacl Recursively

If you want to apply ACLs to an entire directory and all of its subdirectories, use the -R option. Given the directory hierarchy /home/vinod/Level1/Level2/Level3/Level4, the following command will add an ACL entry for group "STN" to all of the Level* directories and their contents:

[vinod@fc10 vinod]$ setfacl -R -m g:STN:r-x /home/vinod/Level1

No comments:

Post a Comment