Advanced Permissions - NFSv4 ACLs

Traditional UNIX/Linux permissions with owner, group, and “other” permissions and modes are sufficient for a large number of applications. However, sometimes a richer permission model is required to give exactly the correct level of access to a file or directory. NFSv4 ACLs (Access Control Lists) are mechanism to manipulate access controls on EECS network-mounted filesystems to supplement traditional Unix permissions. Network mounted file systems include every user's /home/username home directory and directories in /research and /storage.

  • nfs4_setfacl – This is the main command that you will use. This is used to add, remove, or modify the ACL of a file. There are 4 options of real interest, though there are others (see the nfs4_setfacl(2) manual page, or run the command with -H to see all available options).
    • -a – This option tells nfs4_setfacl to add the specified Access Control Entry (ACE - defined below). Basically, this adds a new rule.
    • -x – This option causes nfs4_setfacl to remove the specified control. Note that this needs to match the rule exactly. Usually, to remove a control, it is easier to invoke nfs4_setfacl with the -eswitch, or to use nfs4_getfacl, then copy/paste the line you'd like to remove.
    • -e – This switch, instead of directly modifying the ACL, puts you into a file editor with the ACL, so that you can add/remove/modify all the entries at once. Note that it puts you into whichever editor is specified in your EDITOR environment variable (run echo $EDITOR to see what yours is set to), or vi if none is specified.
    • –test – This switch tells nfs4_setfacl to not actually modify the ACL, but print out what it would be once it applied the operation you specified.

  • nfs4_getfacl – This command is very simple: it prints out the ACL of the file or directory you give it. Note that it can only take one file/directory at a time. See the nfs4_getfacl(1) manual page for more info.

An ACE, or Access Control Entry, is a single control statement, indicating the access of a specific entity (a user or group usually). Thus, an Access Control List (ACL) is a list of ACEs. This article will discuss some simple and common options for an ACE, but for a full description, see the nfs4_acl(5) man page.
We will begin with the structure of an ACE:

[access type]:[flags]:[principal]:[permissions]

All parts are required for every operation, though the [flags] section may be empty.

  • [access type] – Given the type of storage systems that EECS uses, there is only one real access type: A (for Allow). This means that if the given principal requires the permissions specified in the ACE, the operation will be granted.

  • [flags] – Again, given the backend EECS uses, there are only two (sets of) flags one should consider using:
    • g – This is the group flag. It indicates that principal is a Linux group, not a user. Thus, if this flag is left out, the principal will be interpreted as a username.
    • fdi – These flags collectively indicate that the ACE is to be inherited and only makes sense on directories. If set, any file created below the directory will have the given ACE. Additionally, any directory created below one with these flags will have the ACE, and will also have a second ACE with the inheritance flags. Put another way, inheritance flags are recursive. See the Examples and Notes section below if you are thinking about using inherited ACEs.

  • [principal] – The principal is the entity to which the ACE refers (the name comes from the Kerberos authentication protocol). This can be interpreted as a user or a group, depending on the presence or absence of the g flag in the [flags] field. The field can be specified as follows:
    • [entity]@[domain] – This is the general form of a principal, but in practice, since EECS has only one domain, this will be [entity] The [entity] is either a username or a group name in EECS.
    • OWNER@ – This special principal refers to the owner of the file/directory, and in a Linux environment, it must always be specified. This means, every file must have an @OWNER ACE in its ACL.
    • ROUP@ – This principal refers to the default group of a file. Just like with the OWNER@, every ACL must have an ACE for the OWNER@.
    • EVERYONE@ – This is a special catch-all principal which applies to any entity that is not matched by any of the above. Think of this as equivalent to “other” (aka “world”) in the traditional UNIX/Linux permissions model.

  • [permissions] – While there are a wealth of permissions possible with NFSv4 ACLs, only a few subsets apply to EECS systems. Luckily, the nfs4_setfacl command recognizes certain short-cuts, which should be familiar to Linux users, and are the only ones discussed here:
    • R – This represents read permissions. File-principal pairs with this set can inspect the contents of a file or directory same as with traditional read permissions</li>
    • W – Unsurprisingly, this permission entry gives write access, and is needed by any principal needing to make changes to a file. When this permission is applied to directories, it allows the principal to create, delete, and rename files and directories beneath the directory with this permission. In particular, it does not allow the principal to create/delete/rename the directory itself. To do so, the principal would need write permissions on the directory's parent directory.
    • X – Just like the “x” in the traditional model, this provides execute permissions. When applied to a file, it allows the file to be run as a program or script. When put on a directory, it allows a principal to traverse that directory (but not necessarily read it!), i.e. that principle could cd to that directory.

As mentioned above, the permissions outlined in this article are short-cuts for the actual full permissions which extend beyond read, write, and execute. That means there are many other flags which govern such access as editing the ACL on a file itself or trigger certain audit alarms when a file is accessed. When viewing the ACL for a file with nfs4_getfacl, you will notice many other permission entries for a file:

jruser:hydra9 ~> nfs4_getfacl testfile

# file: testfile

In general, for setting ACEs, it is recommended you stick with the shortcuts. And, if you are unsure, use the –test flag to see what your operation would do.

There are exceptions in certain operations–e.g. when removing an ACE–that the real permissions must be specified exactly. Furthermore, if, in setting an ACE, you use the real permissions rather than one of the shortcuts, you must specify all of them.

Inherited permissions are a particularly tricky case for a variety of technical reasons which are beyond the scope of this article. EECS IT recommends that you don't use inherited permissions unless you have familiarized yourself well with NFSv4 ACLs by reading all the manual pages linked to this article. That said, here are a few caveats if you need to use them:

  • When specifying the flags fdi, you must all of them. If you do not, you will not create the inherited ACE.
  • Once you create a single inherited ACE, all other (non-inherited) ACEs already specified will be copied into a set of inherited ones. You should take the time to review this and correct any which do not grant access as you would like, but you cannot remove them.
  • Once you have created your ACL with inherited access controls, you must then set the group field of your umask(2) to something permissive enough to allow any extra principals in your inherited list (other than the OWNER@, GROUP@, and EVERYONE@) to have the access you would like. Take a moment to let that sink in. For example, if you have an ACE like on a directory, then you need to set your umask to at most 007 (e.g. with a command likeumask 007). If instead you only gave joeuser the RX permissions, you could set your umask to 027. No, it does not make any sense, and yes it is a bug, but it is not likely to be fixed soon.

Fixing permissions that have gotten out-of-whack is a potentially frustrating process. If you find yourself in such a situation, open permissions in edit mode (the -e< option to nfs4_setfacl) and removing all the non-standard permissions (everything other than the non-inherited OWNER@, GROUP@, and EVERYONE@ entries), and starting over. It may be easier than fixing a messed up ACL.

  1. Give joeuser read permissions to the file file1:
    nfs4_setfacl -a "" file1
  2. Allow the webserver running as user userweb to access your personal web directory (webhome), and all files underneath. You can use the find command and its -exec command to run a command on a set of files
     find ~/webhome -type d -exec nfs4_setfacl -a "</span>:RX" {} \;

    That command gives RX (i.e. read and execute) permissions to all directories (the –type d option to find) under the ~webhome directory.

    find ~/webhome -type f -exec nfs4_setfacl -a "</span>:R" {} \;

    The second command gives userweb read (R) access to any non-directory file (–type f) in ~webhome. Note, you may want to do this if you want certain files to be accessible via the web, e.g. behind a password, but not to local EECS users. Very useful for making answers to quizzes, etc. password protected.

  3. Give your research group named research1, read access to your project directory project1:
    find project1 -type d -exec nfs4_setfacl -a "</span>:RX" {} \;f
    find project1 -type f -exec nfs4_setfacl -a "</span>:R" {} \;

    Much like in the web server example, you can use the find command to specify one set of permissions (RX) for directories and a slightly different one for files.