Monday, September 6, 2010

ZFS and NFSv4 ACL’s

I've been doing granular file access control lists since Netware 2.0. I'm used to being able to specify (for example) permissions such that a file can be modified, but not renamed or deleted, or setting permissions on a file so that it can be executed, but not read - (Yes, Netware could do that). And of course, it's obvious that more than one user or group permission should be allowable. I'm also used to having some control over inheritance, so that I can 'kneecap' permissions on a nested directory.

Obviously I've been very unimpressed with Unix's trivial rwxr-x--- style permissions. Sun band-aided the decades old rwxr-x--- up with POSIX getfacl and setfacl. That was a start. We now have NFSv4 style ACL’s on ZFS. It looks like they are almost usable.

For an experiment, I decided to clean up a few 'home directories' where the existing permissions are a mess of randomness left over from a decade of ufsdump/ufsrestore, POSIX ACL's, tar, cpio, pax, samba, rsync and who knows what else. Here's my attempt at simple ACL's on an OpenSolaris ZFS volume.

Specific requirements:

  • Owner gets the equivalent of 'full control'.
  • Group gets the equivalent of 'read only'.
  • Everyone gets nada.
  • Newly created files get predictable permissions

To ensure predictable permissions, I want inheritance in some form or another such that:

  • New files are automatically created to allow owner the equivalent of read, write, create, delete, modify, including ACL's and attributes, but without the ‘execute’ bit set.
  • New files are automatically created to allow group 'read-only' but without the ‘execute’ bit set.
  • New directories are automatically created to allow the owner the equivalent of read, write, create, delete, modify, browse, including ACL's and attributes.
  • New directories are automatically created as group read and browse.
  • New files and directories are automatically created with no permissions for ‘everyone’

Keep in mind that the newest ACL implementation needs the Solaris version of ls, chmod, etc., rather than the default gnu versions that ship with OpenSolaris. Also – I’m using Solaris ‘CIFS’, not samba.

First I set:

zfs set aclinherit=passthrough-x  filesystem

passthrough-x appears to mean 'only inherit the 'execute' bit if the application specifically requests the bit when the file is created'. At least that's what it appears to mean.

Then I fixed existing files. Note that I wanted to touch only the files (not the directories), hence the 'find'.

find . -type f  -exec /usr/bin/chmod A=\
owner@:rw-pdDaARWc--s::allow,\
group@:r-----a-R-c---::allow,\
everyone@:full_set::deny {} \;

Explanation:

find . -type f  \
-exec /usr/bin/chmod A=\
<= The 'A=' resets all ACL's rather than adding more ACL's
owner@:rw-pdDaARWc--s::allow,\ <= Set file owner to 'full control' minus the execute bit.
group@:r-----a-R-c---::allow,\ <= Set group to 'read'.
everyone@:full_set::deny {} \;  <= Set everyone else to 'deny all'.

This has a side effect of removing the execute bit from executable files. My standard policy is 'no executable files in home directories'. Those smart enough to know what the 'x' bit is are smart enough to know how to fix what just  broke. I wouldn’t do this in directories full of executable files.

Lastly, I tweaked the directories. Setting inheritance ensures that new files and directories have the desired ACL's:

find . -type d -exec /usr/bin/chmod  A=\
owner@:full_set:d:allow,\
owner@:rw-pdDaARWc--s:f:allow,\
group@:r-x---aAR-c---:d:allow,\
group@:r-----a-R-c---:f:allow,\
everyone@:full_set:fd:deny {} \;

Explanation:

find . -type d \
-exec /usr/bin/chmod  A=\
<= The 'A=' resets all ACL's rather than adding more ACL's
owner@:full_set:d:allow,\ <= Set directory owner to 'full control' with inheritance for newly created directories, including the execute bit.
owner@:rw-pdDaARWc--s:f:allow,\ <= Set directory owner to 'full control' with inheritance for newly created files, excluding the execute bit.
group@:r-x---aAR-c---:d:allow,\ <= Set group  to 'rx-' with inheritance for newly created directories
group@:r-----a-R-c---:f:allow,\ <= Set group to 'r' with inheritance for newly created files
everyone@:full_set:fd:deny {} \; <= Kneecap everyone else

In theory, new files will be created with the equivalent of rw-r-----, new directories will be created equivalent to rwxr-x---.

Maybe.

Helpful docs:

1 comment:

  1. I have had some trouble managing ACLs with CIFS, especially when touching files from both the Solaris side and the Windows side.

    I'd love to read a follow-up on a few simple tests to verify if it worked as you expected. Any unexpected results?
    .

    ReplyDelete