AFS to NFSv4 ACL conversion
From Linux NFS
If filesystems are migrated from AFS to NFSv4, one of the challenges will be mapping file permissions.
Below we describe an algorithm that maps an AFS ACL to an NFSv4 ACL. It is necessarily imperfect but I think it gets pretty close. If the resulting NFSv4 ACL is stored on a Linux server, the result will be further translated to a POSIX ACL. That process will lose more information. The result may still be adequate for some cases.
I expect the bigger challenge to be transitioning users. Our NFSv4 ACL tools and documentation both need work.
AFS ACL permissions affecting directories are:
(l)ookup (i)nsert (d)elete (a)dminister
AFS ACL permissions affecting files are:
(r)ead (w)rite loc(k)
Perms set only on directories in AFS, also allowed on files, symlinks, mount points in auristor. r/w/k perms on directory control files in that directory that don't have an ACL set.
So in auristor it's possible for a file to not have any ACL set.
I assume that directories do have ACLs set, and new subdirectories inherit same permissions as parents.
Both also allow 8 additional application-defined permissions A-H which I think we'll ignore. (If necessary, write a v4 protocol extension.)
"Negative permissions" always take precedence.
Auristor docs state that "i" is equivalent to "w" permissions when applied to a file. That's a rather strange rule given the way that AFS otherwise segregates directory and file permissions, so I'm going to ignore it until I have a chance to ask some questions.
Here's a first attempt at an AFS->NFSv4 translation algorithm:
Given a directory: Start with an empty NFSv4 ACL. Iterate through the ACEs of the AFS ACL one at a time, negative ACEs first. For each ACE:
- If the AFS ACE is a negative ACE, any new NFSv4 ACEs generated in this step should be ACCESS_DENIED_ACE, otherwise ACCESS_ALLOWED_ACE.
- If this is a directory, create two NFSv4 ACEs, one with ACE4_DIRECTORY_INHERIT_ACE set, the other with NFS4_ACE_INHERIT_ONLY_ACE and NFS4_ACE_FILE_INHERIT_ACE set. On the first ACE, convert mode bits as follows:
l->ACE4_EXECUTE|ACE4_READ_DATA i->ACE4_WRITE_DATA|ACE4_APPEND_DATA d->ACE4_DELETE_CHILD a->ACE4_WRITE_ACL
- On the second ACE, convert mode bits as follows:
r->ACE4_READ_DATA w->ACE4_WRITE_DATA|ACE4_APPEND_DATA a->ACE4_WRITE_ACL.
- Given a file: the same, but create only one ACE, with no inheritance bits set. If the source file has no AFS ACL, then the ACL on the destination file should be exactly what it would be if it was inherited from its parent. If the source file has an ACL, then determine the access bits on each destination as above, ignoring any l, i, or d bits. In addition, if the destination NFSv4 server supports the dacl attribute, then set ACE4_INHERITED_ACE on all ACEs when the source file has no AFS ACL, and set ACL4_PROTECTED on any flag on any ACL for which the source file has an AFS ACL set.
I don't think there's any way to handle loc(k) correctly. It should be just ignored and documented. ACE4_SYNCHRONIZE is vaguely similar but in practice it won't do the right thing on any NFSv4 server. A Linux server will ignore it, and a server that supports it probably uses read or write opens to decide permissions to lock, as is traditional for linux/unix.
Failures on mapping to NFSv4 ACLs:
- Without server (and client userspace tool) support for the NFSv4.1 DACL attribute and "automatic" inheritance, changes to directories won't automatically propagate to children. This is different from AFS, where the directory ACL controls permissions on all clients (and Auristor, where that's still the default behavior although files may optionally have their own ACLs). The NFSv4.a DACL attribute partly compensates this, though note that its "automatic" inheritance isn't quite the same, as it depends on user tools to propagate changes to directory permissions.
- loc(k) bit, as noted above.
Failures on mapping to POSIX ACLs as implemented on Linux:
- POSIX ACLs are unable to distinguish between insert and delete. The mapping should default to erring on the side of restrictiveness, and deny directory write permissions when insert and delete are not both permitted.
- POSIX ACLs inherit parent permissions only on creation, there's no way to emulate AFS behavior.
- POSIX ACL inheritance is very different: directories have an "access ACL" (which determines permissions) and a "default ACL" (which is inherited by children). The default ACL is inherited by both files and directories, and POSIX ACLs use the same bit for, for example, directory modification and file write. This means, for example, it's not possible to set an inheritable ACL giving child files write permission but denying modification permissions to child directories. In such cases by default we should err on the side of denying both permissions.
Whenever we're unable to map permissions exactly, we should default to erring on the side of denying permissions, and warning the user. A conversion tool may provide ways to override that default and the warnings. Care must be taken to prevent warnings from being unmanageable. When converting large filesystems, we should provide a readable summary and give the user a way to get the details if necessary.
Some remaining questions:
- interactions with mode bits: in the past I believe AFS simply ignored mode bits, allowing us to ignore them on conversion. I think that may no longer be true for AFS (or at least for Auristor).
- user & group naming
- file owners and groups