ZFS Delegated Administration in FreeBSD

If you trust your users well, you might feel slightly less anxious and allow your users to create new filesystems below their own home directories.

First, you must allow your users to mount filesystems, granted they have the necessary permissions elsewhere:

root@enterprise:~>sysctl vfs.usermount=1
vfs.usermount: 0 -> 1

You might want to edit the /etc/sysctl.conf file to make this change permanent.

I’ve grown fond of using permission sets. It seems natural to distinguish between permissions given to each user’s home directories and permissions given to descendent filesystems. It also makes managing the permissions a lot easier.

Next, let’s set up the absolutely minimum of permission sets, assuming the user’s home directories are stored below the enterprise_zdata/home dataset.

root@enterprise:~>zfs allow -s @local      create,mount         enterprise_zdata/home
root@enterprise:~>zfs allow -s @descendent create,destroy,mount enterprise_zdata/home

Let’s see what we just achieved:

root@enterprise:~>zfs allow enterprise_zdata/home
---- Permissions on enterprise_zdata/home ----
Permission sets:
        @descendent create,destroy,mount
        @local create,mount

Now, create the user’s home directory, assign ownership and these permission sets to the user and his/hers home directory:

root@enterprise:~>zfs create                      enterprise_zdata/home/trond
root@enterprise:~>chown trond:trond ~trond
root@enterprise:~>zfs allow -lu trond @local      enterprise_zdata/home/trond
root@enterprise:~>zfs allow -du trond @descendent enterprise_zdata/home/trond

The results from the commands above should be visible using this command:

root@enterprise:~>zfs allow enterprise_zdata/home/trond
---- Permissions on enterprise_zdata/home/trond ----
Local permissions:
        user trond @local
Descendent permissions:
        user trond @descendent
---- Permissions on enterprise_zdata/home ----------
Permission sets:
        @descendent create,destroy,mount
        @local create,mount

By using permission sets you can easily modify the permission sets and each change becomes instantly avaiable to the users. Let’s sum this up with the permission sets I feel are a good compromise between system security and user’s freedom:

root@enterprise:~>zfs allow -s @local create,mount enterprise_zdata/home
root@enterprise:~>zfs allow -s @descendent clone,compression,create,destroy,diff,exec,hold,mount,promote,readonly,receive,recordsize,release,rename,rollback,send,snapdir,snapshot,userprop enterprise_zdata/home

If you want to blow away a complete permission set, use a command like this one:

root@enterprise:~>zfs unallow -s @local enterprise_zdata/home

Bear in mind this won’t remove a previous assignment. Remove assignments using a command like this one:

root@enterprise:~>zfs unallow @local enterprise_zdata/home/trond

If you want to remove, say the snapshot subcommand only, use a command like this one:

root@enterprise:~>zfs unallow -s @descendent snapshot enterprise_zdata/home

Here’s a list of the filesystems I’ve created within my own home directory, and their origin:

NAME                                    USED  AVAIL  REFER  MOUNTPOINT
enterprise_zdata                       21,4G   891G   224K  legacy
enterprise_zdata/home                  11,2G   891G   368K  /home
enterprise_zdata/home/trond            11,2G   891G  1,29G  /home/trond
enterprise_zdata/home/trond/arbeid     9,00M   891G  9,00M  /home/trond/arbeid
enterprise_zdata/home/trond/cvsroot     597K   891G   597K  /home/trond/cvsroot
enterprise_zdata/home/trond/gitarbeid  2,35G   891G  2,35G  /home/trond/gitarbeid
enterprise_zdata/home/trond/hgarbeid    288M   891G   288M  /home/trond/hgarbeid
enterprise_zdata/home/trond/mail        143M   891G   129M  /home/trond/mail
enterprise_zdata/home/trond/rfc        2,28G   891G  2,28G  /home/trond/rfc
enterprise_zdata/home/trond/svnarbeid  4,82G   891G  4,82G  /home/trond/svnarbeid
enterprise_zdata/home/trond/svnroot    1,18M   891G  1,18M  /home/trond/svnroot