====== Advanced Permissions - NFSv4 ACLs ======
[[/knowledge-base/linux-topics/file-storage|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''.
===== Commands =====
* ''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 [[http://man7.org/linux/man-pages/man1/nfs4_setfacl.1.html|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 ''-e''switch, 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 [[http://man7.org/linux/man-pages/man1/nfs4_getfacl.1.html|nfs4_getfacl(1)]] manual page for more info.
===== Access Control Entries (ACE) =====
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 [[http://man7.org/linux/man-pages/man5/nfs4_acl.5.html|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 [[wp>Kerberos_(protocol)|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]@eecs.utk.edu**. 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
* **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.
===== Notes =====
==== Full Permission Entries ====
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
A::OWNER@:rwatTcCy
A::GROUP@:tcy
A::EVERYONE@:tcy
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.
==== Inheritance ====
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 [[http://man7.org/linux/man-pages/man2/umask.2.html|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 ''A:fdi:joeuser@eecs.utk.edu:RWX'' on a directory, then you need to set your umask to at most ''007'' (e.g. with a command like''umask 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.
==== Troubleshooting Incorrect ACLs ====
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.
===== Examples =====
- Give **joeuser** read permissions to the file ''file1'':nfs4_setfacl -a "A::joeuser@eecs.utk.edu:R" file1
- 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 "A::userweb@eecs.utk.edu: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 "A::userweb@eecs.utk.edu: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.
- Give your research group named ''research1'', read access to your project directory ''project1'': find project1 -type d -exec nfs4_setfacl -a "A:g:research1@eecs.utk.edu:RX" {} \;f
find project1 -type f -exec nfs4_setfacl -a "A:g:research1@eecs.utk.edu: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.