Difference between revisions of "Setting Default File Permissions"

From PHASTA Wiki
Jump to: navigation, search
(Further progress)
(Add blurb on directories and executable permissions)
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
This page will review how to set default file permissions for a directory. This is often used when working in HPC "scratch" directories where members of the same research group (like us) want to give each other some default file permissions on every file created in those directories, regardless of who created them.
+
This page will review how to set default file permissions for a directory using [[File_Permissions_Basics_and_ACL|Access Control Lists (ACL)]]. This is often used when working in HPC "scratch" directories where members of the same research group (like us) want to give each other some default file permissions on every file created in those directories, regardless of who created them.
  
 +
The basis of this is to edit the ACL entries of the directories that we want default file permissions to apply to. To see more information on how ACL and file permissions work, see [[File_Permissions_Basics_and_ACL|File Permissions Basics and ACL]].
  
== Basics of Unix/POSIX File Permissions ==
+
== Setting ACL Rules ==
 +
 
 +
For most POSIX file systems, this can be done via <code>setfacl</code> ([https://linux.die.net/man/1/setfacl see manpage here]). For fancier filesystems, you may need to use other commands/tools to perform the same effective operation.
 +
 
 +
To set a ACL entry, use the <code>-m</code> to ''modify'' the given entry. The format for the ACL entry is identical to what is displayed when running <code>getfacl</code> on a file. Generalized, it takes the form:
 +
 
 +
[d[efault]:] [(u[ser]|g[roup]|m[ask]|o[ther]):](uid|gid|) [:perms]
  
=== What are they? ===
+
=== Examples ===
  
* All files and directories have permissions assigned to them
+
Using the user ID <code>sfseiei</code> and group ID <code>meisters</code>
* All files and directories have a designated user and group "owners", known as file owner and file group respectively
 
** By default, these are the ones that created the directory/file, but this can be changed using `chown`
 
* There are three different "levels" of file permissions in a standard POSIX: read (<code>r</code>), write (<code>w</code>), and execute (<code>x</code>).
 
** Read allows viewing the contents of the file/directory, and copying the files
 
** Write allows rewriting and deleting files. For a directory with write permissions, it also allows creation of subdirectories and creation of new files
 
** Execute allows files to be executed directly.
 
*** Note that for script files (such as <code>bash</code> or <code>python</code>), they can still be run by passing the file to it's interpreter if the file is readable (ie. <code>bash non_executableScript.sh</code> is still possible if <code>non_executableScript.sh</code> has <code>rw-</code> permissions).
 
* These different levels of file permissions are assigned to three different groups of users: file owner, file group, and "others".
 
** "Others" simply refers to any users that don't fall into the other two categories
 
* The file permissions for these three categories form the file <code>mode</code>  
 
  
==== Viewing them ====
+
'''Give a user read access to a file object:'''
As an example, if you run <code>ls -l</code> on a directory, you might see:
+
setfacl -m u:sfseiei:r fileobj
  
drwxr-x---+ 2 jrwrigh7 a1983 4.0K 2020-07-04 08:09 test2
+
'''Give a group read and write access to a file object:'''
  -rw-r-x---+ 1 jrwrigh7 a1983  38 2020-07-02 12:38 test2file
+
  setfacl -m g:meisters:rw fileobj
lrwxrwxrwx  1 jrwrigh7 a1983    9 2020-07-04 08:40 test2fileLink -> test2file
 
  
 +
'''Give a group read and write access to a directory and it's contents recursively'''
 +
setfacl -R -m g:meisters:rw directory
  
The first block (<code>-rw-r-x---+</code>) shows the permissions for the file (described below). The user owner is shown as <code>jrwrigh7</code> and the group owner is <code>a1983</code>.
+
* The <code>-R</code> flag is used for recursively applying the ACL entry
  
'''Permissions Block:'''
+
: ''Note that any new files created in this directory or subdirectories will '''not''' be readable or writable by members of the group''
* First character displays what kind of file it is, be it a link (<code>l</code>), directory (<code>d</code>), regular file (<code>-</code>), etc.
 
* The next 9 characters show the permissions for the file owner, file group, and "others".
 
** So for <code>test2file</code> in the above output:
 
*** File Owner: <code>rw-</code>
 
*** File Group: <code>r-x</code>
 
*** Others: <code>---</code>
 
* The last character is optional. A <code>+</code> means that there are other permission rules not displayed. This is where [[Setting_Default_File_Permissions#Setting ACL Rules|ACL rules]] come into play.
 
  
See [https://www.gnu.org/software/coreutils/manual/html_node/What-information-is-listed.html#What-information-is-listed the ls coreutils manual] for more information on the 'long' format for <code>ls</code>.
+
'''Give a group read and write access to a directory, it's contents, and have new files inherit these rules'''
 +
setfacl -Rd -m g:meisters:rw directory
  
==== Octal numbers ====
+
* The <code>-d</code> flag denotes that the changes should be added as a ACL default entry.  
The file <code>mode</code> is often conveyed in the form of three octal numbers (ie. base 8 numbers). It is very similar to how PHASTA handles specifying boundary conditions using bitwise logic.
+
** This makes any new files inherit these ACL default entries, '''but''' does not necessarily mean that they will be effective. See [[Setting_Default_File_Permissions#Common "Gotchas"|Common "Gotchas"]]
The first bit handles read, the second bit handles write, and the third handles execute.  
+
* See [[File_Permissions_Basics_and_ACL#Custom Permissions| Custom Permissions]] for more information on the importance and function of ACL default entries.
  
Using <code>test2file</code> as the example permissions block, it is stored as <code>110 101 000</code>. When translated into decimal, that equals <code>3 5 0</code>.
+
== Common "Gotchas" ==
  
Another way to think about it is that the octal number equivalent of a permission set = 1*r + 2*w + 4*x, where r, w, and x equal 0 or 1 depending on whether they're set.
+
=== Newly Created File Only Doesn't Fully Inherit Default ACL Rules ===
  
=== What determines the permissions for a new file? ===
+
tl;dr ACL Default entries are not the only thing that controls the permissions of new files. See [[File_Permissions_Basics_and_ACL#Custom Permissions| Custom Permissions]] for deeper explanation.
  
There are three sources that determine what file permissions will be set; <code>umask</code>, the "mode" parameter used by the program creating the file, and ACL.
+
This is probably most common with files that don't inherit the executable permission from the default ACL. In [[File_Permissions_Basics_and_ACL#How are new file permissions set?| How are new file permissions set?]], it is explained that the <code>ACL_MASK</code> (among others) will be set such that the resulting ACL permissions do not exceed the permissions set by the "mode" parameter (which is used by the program creating the file). Often, this "mode" parameter does not include execute permissions.
  
==== umask ====
+
This is normal behavior and can be overridden with manually running <code>setfacl</code> (or <code>chmod</code> if only the three basic permissions need to be changed).
  
<code>umask</code> is a function that contains file permission settings for any file created by a user and it is unique to the user. The user can change it at anytime using the <code>umask</code> command. To see what it is set to, simply run <code>umask</code> with no arguments.
+
'''Example:'''
  
==== "Mode" Parameter ====
+
I have a directory with the following ACL entries:
 +
$ getfacl .
 +
# file: .
 +
# owner: jrwrigh7
 +
# group: a1983
 +
user::rwx
 +
group::r-x
 +
group:a1983:r-x
 +
mask::r-x
 +
other::---
 +
default:user::rwx
 +
default:group::r-x
 +
default:group:a1983:r-x
 +
default:mask::r-x
 +
default:other::---
 +
: Note that all the <code>default:</code> entries have execute permissions except <code>other</code>
  
When a new file is created, the <code>syscall</code> <code>open()</code> (among others) is used and a file mode parameter must be chosen by that program. For example, `touch` will automatically apply the mode <code>666</code> to the file, which will make the file owner, file group, and "others" all have <code>rw-</code> permissions
+
I'll create new file in that directory using <code>touch</code>:
 +
$ touch testfile
 +
 +
$ getfacl testfile
 +
# file: testfile
 +
# owner: jrwrigh7
 +
# group: a1983
 +
user::rw-
 +
group::r-x                      #effective:r--
 +
group:a1983:r-x                #effective:r--
 +
mask::r--
 +
other::---
  
==== ACL ====
+
We see that the file did inherit the <code>default:</code> ACL entries for <code>group::</code>, <code>group:a1983:</code>, and <code>other::</code>. However, the <code>mask::</code> and <code>user::</code> are different than its corresponding <code>default:</code> value, and there is an <code>#effective:r--</code> message next to the <code>group::</code> and <code>group:a1983:</code> entries. The latter message is showing that the permissions for <code>group::</code> and <code>group:a1983:</code> are being overridden by the <code>mask::r--</code> entry.
  
The Access-control List (ACL) has the ability to set more nuanced permissions for files (ie. permissions for specific users or groups that are not file owner or file group). They can be set for a specific file/directory, or as a ''default'' setting. This default setting is set for a directory and is used for files and subdirectories created inside that directory.
+
This is because <code>touch</code> uses a "mode" parameter of <code>666</code> when creating the new file object (<code>6</code> translates to <code>rw-</code>, see [[File_Permissions_Basics_and_ACL#Permissions as Octal Numbers| Permissions as Octal Numbers]]). Since the <code>ACL_MASK</code> entry is used to limit the <code>group:</code> entries such that the effective permissions do not exceed the "mode" parameter. Since the "mode" parameter does not feature execute permissions for <code>ACL_GROUP_OBJ</code>, the <code>mask:</code> entry is set to remove the effective execute permission from the <code>group:</code> entries.
 +
Similarly, the <code>user:</code> is changes directly to comply with the "mode" parameter settings.
  
There are 6 different tags that ACL rules can apply to. From the <code>acl</code> manpage:
+
This is normal behavior and it actually a "feature". To make the file executable by the <code>group:</code> entries, simply use <code>setfacl</code> to change the mask entry:
  
  ACL_USER_OBJ    The ACL_USER_OBJ entry denotes access rights for the file owner.
+
  $ setfacl -m m:rx testfile
 
   
 
   
  ACL_USER        ACL_USER entries denote access rights for users identified by the entry's qualifier.
+
  $ getfacl testfile
   
+
# file: testfile
  ACL_GROUP_OBJ  The ACL_GROUP_OBJ entry denotes access rights for the file group.
+
  # owner: jrwrigh7
   
+
  # group: a1983
  ACL_GROUP      ACL_GROUP entries denote access rights for groups identified by the entry's qualifier.
+
user::rw-
   
+
  group::r-x
  ACL_MASK        The ACL_MASK entry denotes the maximum access rights that can be granted by entries of type ACL_USER, ACL_GROUP_OBJ, or ACL_GROUP.
+
  group:a1983:r-x
 +
  mask::r-x
 +
  other::---
 +
 
 +
Note that the <code>user:</code> entry did '''not''' change and, thus, the file is still not executable by the user. This maybe changed by using the standard <code>chmod</code> command or by using <code>setfacl</code>:
 +
 
 +
$ chmod +x testfile #equivalent to setfacl -m u:rwx testfile
 
   
 
   
  ACL_OTHER      The ACL_OTHER entry denotes access rights for processes that do not match any other entry in the ACL.
+
  $ getfacl testfile
 +
# file: testfile
 +
# owner: jrwrigh7
 +
# group: a1983
 +
user::rwx
 +
group::r-x
 +
group:a1983:r-x
 +
mask::r-x
 +
other::---
  
<code>ACL_USER_OBJ</code>, <code>ACL_GROUP_OBJ</code>, and <code>ACL_OTHER</code> correspond to the file owner, file group, and "other" permissions mentioned above and shown by <code>ls -l</code>. The other two (<code>ACL_GROUP</code> and <code>ACL_USER</code>) are for custom permissions.
+
=== Directories Require Executable Permissions ===
  
The <code>ACL_MASK</code> entry plays an important role in [[Setting_Default_File_Permissions#How are file permissions set?|how new file permissions are set]].
+
In order to give "full" access to a directory, the user must have read ''and'' execute permissions to that directory. With only read permissions, a user can view the contents of the directory, but may not actually enter it.
  
=== How are new file permissions set? ===
+
== System Specific Instructions ==
The manpage for ACL is a great resource to answering this question. Most of the information below is simply paraphrasing what is written in the "Object Creation and Default ACLs" section.
 
  
When creating a file/subdirectory in a parent directory:
+
=== NAS ===
  
* If the parent directory '''has''' default ACL rules, only the ACL default rules and "mode" parameter are used:
+
Currently, the group ID of PHASTA members is <code>a1983</code>. To grant the group <code>r-x</code> permissions to your <code>/nobackup/</code> directory:
** The new file/subdirectory first inherits the default ACL rules of its parent directory
 
** The new file/subdirectory has its ACL entries adjusted such that no permissions exceed the "mode" parameter.
 
*** The <code>ACL_USER_OBJ</code> and <code>ACL_OTHER</code> are changed directly
 
*** The <code>ACL_GROUP</code>, <code>ACL_GROUP_OBJ</code>, and <code>ACL_USER</code> are changed ''through'' adjusting the <code>ACL_MASK</code>
 
** Additionally, if a new subdirectory is created, it will inherit its parents default ACL rules. Note that a file ''cannot'' have default ACL rules set.
 
  
* If the parent directory '''does not''' have default ACL rules, only <code>umask</code> and "mode" parameter are used:
+
* Run <code>setfacl -Rd -m g:a1983:rx /nobackup/$USER</code>
** The new file/subdirectory's <code>ACL_USER_OBJ</code>, <code>ACL_GROUP_OBJ</code>, and <code>ACL_OTHER</code> are set based on the permissions set by <code>umask</code>
+
** This will make all new files inherit those permissions
** The new file/subdirectory's are then adjusted to limit permissions to be no looser than the "mode" parameter
+
* Run <code>setfacl -R -m g:a1983:rx /nobackup/$USER</code>
 +
** This will give all current files group permissions
  
Note that this all means that if you have a default ACL rule that gives execute permissions to a group, the group will not have execute permissions by default ''unless'' the "mode" parameter also has execute permissions. Most compilers will use the execute permission bit for the "mode" parameter of it's executable, but other files will not.
+
'''Note:''' The [[Setting_Default_File_Permissions#Newly Created File Only Doesn't Fully Inherit Default ACL Rules|issue with files not inheriting executable permissions]] is present here. This must be fixed on a file-by-file basis unfortunately using either <code>setfacl -m m:rx testfile</code> or (if the file group is the group you want to give permissions to) <code>chmod g+x testfile</code>.
 
 
== Setting ACL Rules ==
 

Latest revision as of 10:32, 11 March 2021

This page will review how to set default file permissions for a directory using Access Control Lists (ACL). This is often used when working in HPC "scratch" directories where members of the same research group (like us) want to give each other some default file permissions on every file created in those directories, regardless of who created them.

The basis of this is to edit the ACL entries of the directories that we want default file permissions to apply to. To see more information on how ACL and file permissions work, see File Permissions Basics and ACL.

Setting ACL Rules

For most POSIX file systems, this can be done via setfacl (see manpage here). For fancier filesystems, you may need to use other commands/tools to perform the same effective operation.

To set a ACL entry, use the -m to modify the given entry. The format for the ACL entry is identical to what is displayed when running getfacl on a file. Generalized, it takes the form:

[d[efault]:] [(u[ser]|g[roup]|m[ask]|o[ther]):](uid|gid|) [:perms]

Examples

Using the user ID sfseiei and group ID meisters

Give a user read access to a file object:

setfacl -m u:sfseiei:r fileobj

Give a group read and write access to a file object:

setfacl -m g:meisters:rw fileobj

Give a group read and write access to a directory and it's contents recursively

setfacl -R -m g:meisters:rw directory
  • The -R flag is used for recursively applying the ACL entry
Note that any new files created in this directory or subdirectories will not be readable or writable by members of the group

Give a group read and write access to a directory, it's contents, and have new files inherit these rules

setfacl -Rd -m g:meisters:rw directory
  • The -d flag denotes that the changes should be added as a ACL default entry.
    • This makes any new files inherit these ACL default entries, but does not necessarily mean that they will be effective. See Common "Gotchas"
  • See Custom Permissions for more information on the importance and function of ACL default entries.

Common "Gotchas"

Newly Created File Only Doesn't Fully Inherit Default ACL Rules

tl;dr ACL Default entries are not the only thing that controls the permissions of new files. See Custom Permissions for deeper explanation.

This is probably most common with files that don't inherit the executable permission from the default ACL. In How are new file permissions set?, it is explained that the ACL_MASK (among others) will be set such that the resulting ACL permissions do not exceed the permissions set by the "mode" parameter (which is used by the program creating the file). Often, this "mode" parameter does not include execute permissions.

This is normal behavior and can be overridden with manually running setfacl (or chmod if only the three basic permissions need to be changed).

Example:

I have a directory with the following ACL entries:

$ getfacl .
# file: .
# owner: jrwrigh7
# group: a1983
user::rwx
group::r-x
group:a1983:r-x
mask::r-x
other::---
default:user::rwx
default:group::r-x
default:group:a1983:r-x
default:mask::r-x
default:other::---
Note that all the default: entries have execute permissions except other

I'll create new file in that directory using touch:

$ touch testfile

$ getfacl testfile 
# file: testfile
# owner: jrwrigh7
# group: a1983
user::rw-
group::r-x                      #effective:r--
group:a1983:r-x                 #effective:r--
mask::r--
other::---

We see that the file did inherit the default: ACL entries for group::, group:a1983:, and other::. However, the mask:: and user:: are different than its corresponding default: value, and there is an #effective:r-- message next to the group:: and group:a1983: entries. The latter message is showing that the permissions for group:: and group:a1983: are being overridden by the mask::r-- entry.

This is because touch uses a "mode" parameter of 666 when creating the new file object (6 translates to rw-, see Permissions as Octal Numbers). Since the ACL_MASK entry is used to limit the group: entries such that the effective permissions do not exceed the "mode" parameter. Since the "mode" parameter does not feature execute permissions for ACL_GROUP_OBJ, the mask: entry is set to remove the effective execute permission from the group: entries. Similarly, the user: is changes directly to comply with the "mode" parameter settings.

This is normal behavior and it actually a "feature". To make the file executable by the group: entries, simply use setfacl to change the mask entry:

$ setfacl -m m:rx testfile

$ getfacl testfile
# file: testfile
# owner: jrwrigh7
# group: a1983
user::rw-
group::r-x
group:a1983:r-x
mask::r-x
other::---

Note that the user: entry did not change and, thus, the file is still not executable by the user. This maybe changed by using the standard chmod command or by using setfacl:

$ chmod +x testfile #equivalent to setfacl -m u:rwx testfile

$ getfacl testfile
# file: testfile
# owner: jrwrigh7
# group: a1983
user::rwx
group::r-x
group:a1983:r-x
mask::r-x
other::---

Directories Require Executable Permissions

In order to give "full" access to a directory, the user must have read and execute permissions to that directory. With only read permissions, a user can view the contents of the directory, but may not actually enter it.

System Specific Instructions

NAS

Currently, the group ID of PHASTA members is a1983. To grant the group r-x permissions to your /nobackup/ directory:

  • Run setfacl -Rd -m g:a1983:rx /nobackup/$USER
    • This will make all new files inherit those permissions
  • Run setfacl -R -m g:a1983:rx /nobackup/$USER
    • This will give all current files group permissions

Note: The issue with files not inheriting executable permissions is present here. This must be fixed on a file-by-file basis unfortunately using either setfacl -m m:rx testfile or (if the file group is the group you want to give permissions to) chmod g+x testfile.