ACL Functions

ACL functions allow for fetching and setting Access Controls (permissions) on files.

Currently, only ‘opaque’ ACLs are supported, meaning the ACLs can only be copied, not inspected.

Description

ace_v4 struct

The ace_v4 struct returned by arcapix.fs.gpfs.clib.acl.get_nfs4_acl() has the following fields

aceType    # Allow or Deny
aceFlags   # Inherit specifications, etc.
aceIFlags  # GPFS Internal flags
aceMask    # NFSv4 mask specification
aceWho     # User/Group identification

All fields are of type int.

The aceType field is one of: AT_ALLOW, AT_DENY, AT_AUDIT, AT_ALARM

The aceFlags field is a combination of

AF_FILE_INHERIT
AF_DIR_INHERIT
AF_NO_PROPAGATE
AF_INHERIT_ONLY
AF_SUCCESSFUL
AF_FAILED
AF_GROUP_ID
AF_INHERITED

The aceIFlags field is either AI_SPECIAL_ID indicating the ACE is a special (owner, group, everyone), or 0. For convenience, the is_special() function checks this field.

The aceMask field indicates what permissions apply to the ACE. It is made of a combination of

AM_READ
AM_LIST_DIR
AM_WRITE
AM_ADD_FILE
AM_APPEND
AM_ADD_SUBDIR
AM_READ_NAMED
AM_WRITE_NAMED
AM_EXECUTE
AM_SEARCH
AM_DELETE_CHILD
AM_READ_ATTR
AM_WRITE_ATTR
AM_DELETE
AM_READ_ACL
AM_WRITE_ACL
AM_WRITE_OWNER
AM_SYNCHRONIZE
AM_ALL

where AM_ALL is a shorthand for a combination of all the permissions.

In addition, the following combination aliases are provided, which roughly correspond to POSIX permissions

AM_POSIX_READ
AM_POSIX_WRITE
AM_POSIX_EXECUTE

The aceWho flag is one of AS_OWNER, AS_GROUP, AS_EVERYONE if this is a special ACE; a group id if aceFlags includes AF_GROUP_ID; or else a user id. The arcapix.fs.gpfs.clib.utils.acl.get_ace_name() convenience function will translate this to a name.

class arcapix.fs.gpfs.clib.acl.ace_v4(aceType=0, aceFlags=0, aceIFlags=0, aceMask=0, aceWho=0)

NFSv4 ACL entry.

arcapix.fs.gpfs.clib.acl.copy_acl(source, dest)

Copy ACL from one file to another.

Parameters
  • source (str) – path to file from which ACL should be copied

  • dest (str) – path to file to which copied ACL should be applied

arcapix.fs.gpfs.clib.acl.get_nfs4_acl(pathname)

Get NFSv4 ACL for a path.

Parameters

pathname (str) – path of file or directory to get ACL for.

Returns

list of NFSv4 entries

Return type

list of ace_v4

arcapix.fs.gpfs.clib.acl.getacl(source)

Get a file’s acls.

Parameters

source (str) – path to a file to get acls from.

Returns

opaque_acl object holding the file’s acls

arcapix.fs.gpfs.clib.acl.is_group(ace)

Returns whether an ACE applies to a group.

In that case, the ACE aceWho is a group id

arcapix.fs.gpfs.clib.acl.is_special(ace)

Returns whether the ACE is a special.

Special ACEs apply to the file owner user, owner group, or everyone.

The specific type is deferminted by the ACE aceWho attribute

e.g.

>>> is_special(ace) and (ace.aceWho == AS_OWNER)
True
arcapix.fs.gpfs.clib.acl.is_user(ace)

Returns whether an ACE applies to a user.

In that case, the ACE aceWho is a user id

arcapix.fs.gpfs.clib.acl.put_nfs4_acl(pathname, acl)

Put an NFSv4 ACL for a path.

Parameters
  • pathname (str) – path of file or directory to get ACL for.

  • acl – a list of ace_v4 NFSv4 entries

The ACL can either be from get_nfs4_acl() or manually constructed.

Note

For copying ACLs between files, copy_acl() is more efficient.

For appending an ACE to a file, arcapix.fs.gpfs.clib.utils.acl.append_nfs4_aces() if more efficient.

arcapix.fs.gpfs.clib.acl.putacl(dest, opaque_acl acls)

Set a file’s acls.

Parameters
  • dest (str) – path to file whose acls should be changed.

  • acls (opaque_acl) – opaque_acl object with acls to set. This should be an object returned from a getacl() call

Examples

Copy ACLs from one file to another

>>> from arcapix.fs.gpfs.clib.acl import copy_acl
>>>
>>> copy_acl('/mmfs1/test01.txt', '/mmfs1/test02.txt')

Check if file owner has read and write permission

>>> from arcapix.fs.gpfs.clib.acl import get_nfs4_acl
>>> from arcapix.fs.gpfs.clib.acl import is_special, AS_OWNER
>>> from arcapix.fs.gpfs.clib.acl import AT_ALLOW, AM_READ, AM_WRITE
>>>
>>> acl = get_nfs4_acl("/mmfs1/test")
>>>
>>> # check first entry is the ACE for the file owner
>>> # (this is typically true, but not necessarily)
>>> assert is_special(acl[0]) and acl[0].aceWho == AS_OWNER
>>>
>>> # check it is an 'allow' ACE
>>> # if it was deny we would have to invert the check
>>> assert acl[0].aceType == AT_ALLOW
>>>
>>> # check the mask allows read/write
>>> assert acl[0].aceMask & (AM_READ | AM_WRITE)

List all ACEs and whether execute permission is granted

>>> from arcapix.fs.gpfs.clib.acl import get_nfs4_acl, AT_ALLOW, AM_EXECUTE
>>> from arcapix.fs.gpfs.clib.utils.acl import get_ace_name
>>>
>>> acl = get_nfs4_acl("/mmfs1/test.bin")
>>>
>>> for ace in acl:
...    if ace.aceType == AT_ALLOW:
...        can_exec = bool(ace.aceMask & AM_EXECUTE)
...    else:
...        can_exec = not bool(ace.aceMask & AM_EXECUTE)
...    type, name = get_ace_name(ace)
...    print("%s:%s - %s", type, name, can_exec)
...
special:owner@ - True
special:group@ - False
special:everyone@ - False
group:admin - True

Add read permission to all existing ACL entries

Note - this ignores whether the existing ACEs are allow or deny. If an ACE were deny, this would take away read permission

>>> from arcapix.fs.gpfs.clib.acl import get_nfs4_acl, put_nfs4_acl, AM_READ
>>>
>>> # get the current ACL
>>> acl = get_nfs4_acl('/mmfs1/test')
>>>
>>> # add read permission to each ACE
>>> for ace in acl:
...     ace.aceMask |= AM_READ
...
>>> # apply the updated ACL
>>> put_acl('/mmfs1/test', acl)

Remove the last entry from an ACL

>>> from arcapix.fs.gpfs.clib.acl import get_nfs4_acl, put_nfs4_acl
>>>
>>> # get the current ACL
>>> acl = get_nfs4_acl('/mmfs1/test')
>>>
>>> # drop the last entry
>>> acl.pop()
>>>
>>> # apply the updated ACL
>>> put_acl('/mmfs1/test', acl)