apfacl(1)

Change access controls (ACLs) on files and directories in PixStor

SYNOPSIS

apfacl paths… [-l] [-a spec [-i index]] [-x spec] [-s spec | -S path] [-m from_spec to_spec] [-R] [–test]

DESCRIPTION

apfacl is a tool for manipulating the Access Control List (ACLs) on files and directories in a PixStor filesystem.

An ACL is made up of entries (ACEs) which grant file permissions to a specific user or group. This includes three ‘special’ entries representing the file owner@ and group@, and everyone@ else.

This tool does not have the ability to change a file’s owner.

An ACE is specified using the same syntax as nfs4_acl(5), see the ACE SPECS section below.

Multiple operations can be applied at once. In that case, the order of operations is: set, modify, remove, add, list; regardless of the order they are specified on the CLI.

When adding ACEs, identical entries are de-duplicated. When removing ACEs, missing entries are silently ignored.

See also: apchmod(1) which supports partial changes to ACEs, e.g. setting and removing individual permission bits.

NOTE - this tool only supports GPFS filesystems with ACL semantics (mmlsfs -k) set to nfs4

OPTION SUMMARY

      paths              paths to set acl on

-l, --list               print the ACL
-a, --add SPEC           append new ACEs, or insert starting at index with -i
-i INDEX                 with -a; index to insert new ACEs at (default=append)
-x, --remove SPEC        remove ACEs matching spec
-s, --set SPEC           replace the ACL on a file
-S, --set-file PATH      replace ACL with those read from file
-m, --modify SPEC SPEC   replace existing individual ACEs
-R, --recursive          apply the change recursively
    --no-check           don't check the current ACL before applying changes
    --include-symlinks   include symlinks when applying changes recursively
    --test               print the updated ACL without applying the change
-V, --version            show the current version number
-h, --help               show this help message and exit

OPTIONS

  • -l, –list

    Display the current ACL.

    On its own, this will print the current ACL on the file to stdout, and exit without making changes. It can also be used in combination with other flags, to display the results of an ACL change.

    This is the default mode if no flags are specified.

  • -a, –add

    Add one or more ACEs to the file.

    The value is a comma-separate list of one or more ACE specs (see below)

    If identical entries already exist in the ACL, the matching new entries will be skipped.

    By default, new entries are appended. The -i flag will insert the new entries at a specific index.

  • -i

    The index to insert ACEs at with –add

    Index is zero-indexed, so an index of 1 would insert an ACE as the second entry in the list.

    If an index goes beyond the end of the list, the new entry will be effectively appended.

    A negative index can be used to insert entries relative to the end of the ACL, for example -1 will insert an ACE as the second-to-last entry in the list.

    If an identical entry already existing in the ACL, it will be removed (de-duplicated) and re-inserted at the requested index.

    Note - de-duplication occurs before insert, which may affect where the index places the new entries relative to the existing entries.

    When not specified, ACEs will be appended to the end of the ACL

  • -x, –remove

    Remove one or more ACEs from a file.

    The ACE spec can be a full ACE, or just a user or group. If just a user or group is specified, then all existing entries which match that user or group will be removed.

    apfacl /mmfs1/test -x A:g:readonly:r,pixadmin,g:admin
    

    If no existing entries match the requested ACEs, they will be silently ignored.

  • -s, –set

    Replace the current ACL on a file.

    The whole ACL will be replaced, including the ‘special’ entries.

    The input ACL will be applied ‘as is’. Care should be taken if applying the ACL from a directory recursively, as it may result in files being made executable.

  • -S, –set-file

    Replace the current ACL on a file with an ACL read from a spec file.

    The format of the input spec file is the same as the output generated by –list, one ACE spec per line. Any comments - indicated by the # charater - or blank lines are ignored.

    The special - character can be used in place of a file path to read the spec from stdin. This allows for copying an ACL by piping –list to –set-file

    apfacl /mmfs1/source --list | apfacl /mmfs1/target --set-file -
    
  • -m, –modify

    Replace a specific entry.

    Both specs must be as defined in the ACE SPECS section. The source spec can be principal-only format.

    apfacl /mmfs1/data -m pixadmin:R pixadmin:RW
    

    The source ACE is replaced ‘in place’, meaning the new ACE will be placed in the same position as the old. If the source ACE doesn’t exist, the new ACE will not be inserted.

    If multiple entries are matched by the source spec, only the first will be replaced. This can be combined with -x, –remove to strip out remaining, duplicate entries

    apfacl /mmfs1/test -m admin:R admin:RW -x admin:R
    

    If the replacement results in multiple identical entries, they will not be de-duplicated.

    For modifying individual ACEs, apchmod(1) may be a better tool. To achieve the first example above,

    apchmod /mmfs1/data pixadmin:+W
    
  • -R, –recursive

    Apply the ACL operation to a directory tree recursively.

    Changes are applied top-down. Symlinks will not be traversed.

  • –no-check

    By default, apfacl will compare the current file ACL to what the ACL will be after applying updates. If the current ACL is unchanged by the updates, the new ACL will not be applied.

    This means that change time (ctime) will not be updated for such unchanged files.

    The –no-check flag causes this comparison to be skipped - the new ACL will be applied regardless of its current value.

    When all the target files are expected to be updated, the –no-check flag will make the process faster.

  • –include-symlinks

    Include symlinks when applying changes recursively.

    It is not possible to get or set the ACL on a symlink object itself. ACLs will be read from and written to the target of a symlink.

    By default, apfacl will skip any symlinks it encounters when applying a change recursively.

    This flag will force apfacl to apply ACLs changes to symlinks (targets) when –recursive is used. Be aware that broken symlinks, or symlinks pointing to paths outside GPFS will cause errors.

    apfacl will handle symlinks passed to it on the command line (non-recursively), regardless of whether this flag is used.

  • –test

    Apply the ACL changes in test mode.

    The changes will be performed on the current ACL and the result will be printed to stdout but the result will not be applied to the file(s)

  • -V, –version

    Show the current version number

  • -h, –help

    Prints the help message.

ACE SPECS

ACE specs use the same format as nfs4_acl(5)

[type:][flags:]principal:permissions

The abbreviated forms flags:principal:permissions and principal:permissions are supported, where type defaults to allow (A) and flags defaults to none set.

For -x, –remove and -m, –mofify operations, one can specify just a user or group - with user or g:group - to remove any and all entries or replace the first entry associated with that user or group

apfacl /mmfs1/test -x admin

apfacl /mmfs1/test -m viewonly viewonly:R

This should not to be confused with admin: which would be expanded to only match exactly A::admin: - that is, an entry which grants no permissions to ‘admin’

For any other operations, specifying only a user or group will raise an error.

ACE matching for removal and de-duplication is based on the whole ACE (except when removing by principal only). This includes matching inheritance flags, except for files, where inheritance flags are ignored, since they can’t be set.

In other words, A:f:admin:r is equivalent to A::admin:r for files, but not for directories.

ACE TYPE

ACE type is one of

A    allow - allow actions granted by the permissions
D    deny - prevent actions denied by the permissions
L    alarm - generate a system alarm for an attempted access which requires the permissions
U    audit - log an attempted access which requires the permissions

NOTE - GPFS can only save and retrieve AUDIT and ALARM ACEs. No action is taken if they are ‘triggered’.

ACE FLAGS

ACE flags is zero or more of the following

GROUP FLAG

g    group - indicated that the principal refers to a group, rather than a user

INHERITANCE FLAGS

d    directory inherit - newly created child directories will inherit the ACE
f    file inherit - newly created child files will inherit the ACE without inheritance flags.
     Newly created child directories will also inherit the ACE, but if the parent ACE is not also directory-inherit
     the child directory ACE will be given the no-inherit flag.
i    inherit only - the ACE doesn't apply to the directory itself,
     but will be inherited by newly created child directories, with the inherit-only flag removed
I    inherited - indicates that the ACE was inherited (informational)
n    no propogate - newly create child directories will inherit the ACE, but without inheritance flags

Inheritance flags can only be applied to directories. For files, they are silently ignored, except for ‘inherited’, which is purely informational.

inherit-only is only valid in combination with file-inherit and/or directory-inherit. Specifying inherit-only without file or directory -inherit will result in an error.

ACE matching for removal and de-duplication takes into account inheritance flags, except for files, since they’re ignored. In other words, A:f:admin:r is equivalent to A::admin:r for files, but not for directories.

Inheriting ACEs do not get applied to any already existing children of a directory.

ADMINISTRATION FLAGS

S    successful access - generate the audit or alarm event for a successful access attempt
F    failed access - generate the audit or alarm event for a failed access attempt

Successful and Failed can only be set for audit and alarm ACEs. For allow and deny ACEs, an error will be raised.

PRINCIPAL

Can be one of the ‘special’ users (OWNER@, GROUP@, EVERYONE@), a user name or uid, or a group name or gid if used with the group flag.

For example, A::admin:r would apply to user ‘admin’, while A:g:admin:r would apply to group admin.

NOTE - Internally, the principal is stored by id. Therefore when setting an ACE with a user or group name, apfacl will attempt to lookup the corresponding uid/gid. If this fails, an UnknownUserName or UnknownGroupName error will be returned.

Similarly, when reporting ACLs, the internal id is converted to a user or group name. If this is not possible - e.g. if the user/group no longer exists - then the uid/gid will be reported as is.

PERMISSIONS

Permissions is made up of zero or more of

a    append - append data to a file or create sub-directories (mkdir)
c    read ACL - read the NFS4 ACL on a file or directory
C    write ACL - write the NFS4 ACL on a file or directory
d    delete - delete a file or directory itself
D    delete child - delete a child file or directory from within a directory (no effect when applied to files)
n    read named - read named attributes of a file or directory
N    write named - write named attributes of a file or directory
o    write owner - change the owner of a file or directory (chown)
r    read - read file data or list directories
t    read attrs - read attributes of a file or directory
T    write attrs - write attributes of a file or directory
w    write - write file date or create files within a directory
x    execute - execute a file or move into a directory (cd)
y    synchronize - allow clients to use synchronous I/O within the server

NOTE - GPFS supports setting read named, write Named, and synchronize, but they have no effect within GPFS

Permissions can also use aliases - see the ALIASES section below.

ALIASES

Aliases are provided for the more simple POSIX read/write/execute permissions

R    rntcy
W    watTNcCy, plus D for directories
X    tcy, plus x for directories

For example, A::admin:RW will grant user ‘admin’ permissions roughly equivalent to POSIX rw-

The fact that X doesn’t include execute permission means that one can apply RX recursively to make files and directories accessible without making files executable. To explicitly make files executable, one would include the lowercase executable bit - RXx

Note - permissions delete and write owner are not included in any of the aliases. To set all the permissions, one can use RWXdo for directories and RWXdDox for files

COMPARISON TO MMGETACL

Taking the following ACE, as listed by mmgetacl(1), as an example

group:admin:r-x-:allow:DirInherit
 (X)READ/LIST (-)WRITE/CREATE (-)APPEND/MKDIR (X)SYNCHRONIZE (X)READ_ACL  (X)READ_ATTR  (X)READ_NAMED
 (-)DELETE    (-)DELETE_CHILD (-)CHOWN        (X)EXEC/SEARCH (-)WRITE_ACL (-)WRITE_ATTR (-)WRITE_NAMED

The mask entries correspond to:

READ/LIST    - r
WRITE/CREATE - w
APPEND/MKDIR - a
SYNCHRONIZE  - y
READ_ACL     - c
READ_ATTR    - t
READ_NAMED   - n
DELETE       - d
DELETE_CHILD - D
CHOWN        - o
EXEC/SEARCH  - x
WRITE_ACL    - C
WRITE_ATTR   - T
WRITE_NAMED  - N

Therefore, the above ACE corresponds to A:dg:admin:ryctnx

EXAMPLES

VIEW ACL

$ apfacl /mmfs1/hello --list
# path: /mmfs1/hello
A::OWNER@:acCnNortTwy
A::GROUP@:cnrty
A::EVERYONE@:cnrty

Also supports recursive to view ACLs for all files in a tree

APPEND AN ACE

The following all produce the same ACE

NFS4 literal

apfacl /mmfs1/hello -a A::admin:cnrty

POSIX alias

apfacl /mmfs1/hello -a A::admin:R

Abbreviated

apfacl /mmfs1/hello -a admin:R

ADD MULTIPLE ACES AT INDEX

Inserts the entries at index 3, after the ‘special’ entries (owner/group/everyone), ahead of any other existing entries

apfacl /mmfs1/hello -a A::admin:R,A:g:admin:R -i 3

MOVE ACE TO INDEX

When adding an ACE at index, if a matching ACE exists, de-duplication will effectively move it to the requested index

$ apfacl /mmfs1/test --list
# path: /mmfs1/test
A::OWNER@:acCDnNortTwxy
A::GROUP@:cnrty
A::EVERYONE@:r
A::manage:r
A::admin:rw

$ apfacl /mmfs1/test -a A::admin:rw -i 3 --list
# path: /mmfs1/test
A::OWNER@:acCDnNortTwxy
A::GROUP@:cnrty
A::EVERYONE@:r
A::admin:rw
A::manage:r

REMOVE AN ACE

Remove is based on exact match - i.e. same user/group, permissions, flags (inherit)

apfacl /mmfs1/hello -x A:g:manage:cnrty

REPLACE AN ACE

apfacl /mmfs1/test -m admin:R admin:RW

A similar effect can be achieved by applying a remove and add in the same command

apfacl /mmfs1/test -x A::admin:R -a A::admin:RW

However, in this case, order is not preserved. The new entry will be placed at the end of the list. To preserve order, the desired index must be specified explicitly with -i

apfacl /mmfs1/test -x A::admin:R -a A::admin:RW -i 3

RECONCILE ACES FOR A USER

Replace the first existing entry for a given user, preserving the current entry position

apfacl /mmfs1/test -m admin A::admin:R

Remove all entries applying to a given user, and append a singular new entry

apfacl /mmfs1/test -x admin -a A::admin:R

These may be useful for applying an ACE recursively, where the existing entries for a user are not the same on all files.

COPY ACL

Using -S, –set-file with - means read from stdin

apfacl /mmfs1/source --list | apfacl /mmfs1/target -S -

This is equivalent to doing

apfacl /mmfs1/source --list > acl.txt
apfacl /mmfs1/target -S acl.txt

COPY ACL WITHOUT A GIVEN USER

Similar to above, but also specifying -x, –remove to strip out any entries from the source which apply to user ‘admin’

apfacl /mmfs1/source --list | apfacl /mmfs1/target -S - -x admin

ADD INHERITING ACL

Adds two entries, a directory inherit with the execute bit, and a file inherit without.

Because we’re using X, we can apply this recursively without making files executable.

In the case of the file, the inheritance flags are ignored, making the two entries identical. They are therefore de-duplicated into a single entry.

$ apfacl -R /mmfs1/dir1 -a A:f:admin:R,A:d:admin:RX --test
# path: /mmfs1/dir1
A::OWNER@:acCDnNortTwxy
A::GROUP@:cnrtxy
A::EVERYONE@:cnrtxy
A:d:admin:cnrtxy
A:f:admin:cnrty

# path: /mmfs1/dir1/file1
A::OWNER@:acCnNortTwy
A::GROUP@:cnrty
A::EVERYONE@:cnrty
A::admin:cnrty

SET FILE OWNER PERMISSIONS

Set (POSIX) read/write permission on an existing OWNER@ entries.

$ apfacl /mmfs1/data --list
# path: /mmfs1/data
A::OWNER@:R
A:fd:OWNER@:RX

$ apfacl /mmfs1/data -m A::OWNER@:R A::OWNER@RW --test
# path: /mmfs1/data
A::OWNER@:RW
A:fd:OWNER@:RX

$ apfacl /mmfs1/data -m OWNER@ A::OWNER@RW --test
# path: /mmfs1/data
A::OWNER@:RW
A:fd:OWNER@:RX

A similarly effect be achieved with a combination of remove and add, but this may result in the entries being de-duplicated, or moved.

$ apfacl /mmfs1/data -x A::OWNER@:R -a A::OWNER@:RW --test
# path: /mmfs1/data
A:fd:OWNER@:RX
A::OWNER@:RW

$ apfacl /mmfs1/data -x OWNER@ -a A::OWNER@:RW --test
# path: /mmfs1/data
A::OWNER@:RW

THREAD SAFETY

apfacl is not thread-safe.

For each file, apfacl will load the current ACL, preform the requested transformation, then write the whole ACL back to the file. This means that, if two processes try to change the ACL on a file at the same time, the last write will replace any other changes.

EXIT STATUS

On success, apfacl will exit with status 0

On failure, apfacl will exit with status 1. An error message will be printed to stderr.

If an error occurs in the middle of a recursive change, apfacl will exit immediately with status 1. ACL changes will not be applied to any remaining files.

SEE ALSO

ap_pushacl, mmgetacl(1), mmputacl(1), nfs4_acl(5), nfs4_setfacl(1), setfacl(1)