[OpenAFS] Re: Ideas for finer grain set acl controls

Michael Meffie mmeffie@sinenomine.net
Wed, 11 Nov 2009 14:38:51 -0500


Andrew Deason wrote:
> Recent discussions have shown that there are a few possible ways we
> could go about restricting ACL-setting access. With this email I hope to
> detail all of the ones that have come up so far, and demonstrate the
> pros and cons of each.

Andrew,

Thank you for expanding on the ideas being considered.

There seems to be consensus a volume level control is what is
desired, regardless of the options currently under consideration.

My opinion is we need to find an option that would be must
intuitive to end-users, and I'm not sure we know enough yet
to say which approach would be the least confusing and
surprising for end-users. I hope some others will chime in
to express some opinions.


> Since the rest of this is quite long, here's a quick summary of the
> conclusions. We have three methods: 'method 1' is the "volume ACL
> policies" idea, 'method 2' is the "volume-level ACL overlays" idea, and
> 'method 3' is the "volume ACL masks" idea. To cover all uses cases, we'd
> either do method 1, or a combination of 2 and 3. Or we could just
> implement all of them; I don't see anything stopping us from
> implementing everything desribed here.
> 
> The bottom line is that I find method 1 to be the most flexible and the
> least confusing to end-users, but it is the most confusing to
> administrators, and it is the slowest (when changing the volume-level
> permissions). Using methods 2+3 has the opposite pros/cons.
> 
> Here are the details. Each method has an explanation for what it
> generally is and how it works, followed by its use in a few simple
> use-case scenarios, followed by the pros/cons.
> 
> Method 1, "volume ACL policies":
> 
> With this method, we maintain policies of who is allowed to set what ACLs
> in a volume. For example, to allow nobody but system:powerusers to grant
> idwka rights to system:anyuser, we'd have a policy for system:anyuser
> that would look like this:
> 
> system:powerusers rlidwka
> system:anyuser    rl
> 
> After that policy is set, any time a user not in system:powerusers tries
> to grant system:anyuser more than rl rights, they will get an EACCES
> error. This does not change the existing ACLs in the volume; an
> administrator will need to run an auditing tool to make sure that
> existing ACLs comply with the volume policy.
> 
> "How do I prevent system:anyuser/system:authuser write access?"
> --
> 
> You would call something like this
> 
>  vos setpolicy -add-positive   \
>    -user system:anyuser        \
>    -set-rights rl              \
>    -for-user system:anyuser    \
>    -in-volume user.adeason
> 
> to prevent people fromt giving system:anyuser write access. To ensure
> that existing ACLs don't permit write access, you would need to run
> something like
> 
>  vos auditpolicy -vol user.adeason
> 
> "How do I prevent group.foo write access?"
> --
> 
> To prevent an arbitrary normal group from getting write access, things
> are slightly different. You would need to prevent users from taking away
> negative idwka rights, and then assign negative idwka rights to all
> directories in the volume. So, something like
> 
>  vos setpolicy -remove-negative \
>    -user system:anyuser         \
>    -set-rights rl               \
>    -for-user group.foo          \
>    -in-volume user.adeason
> 
> Would allow users to only remove 'rl' rights from group.foo in negative
> ACLs. Then you would need to set negative idwka ACLs on all directories
> in the volume.
> 
> "How do I guarantee group.bar read access?"
> --
> 
> Prevent normal users from taking away read access from group.bar, and
> from granting negative read access for group.bar:
> 
>  vos setpolicy -remove-positive \
>    -user system:anyuser         \
>    -set-rights idwka            \
>    -for-user group.bar          \
>    -in-volume user.adeason
>  
>  vos setpolicy -add-negative    \
>    -user system:anyuser         \
>    -set-rights idwka            \
>    -for-user group.bar          \
>    -in-volume user.adeason
> 
> Then, grant read access for group.bar in all directories in the volume.
> 
> Method 1 pros:
> 
>  - More flexible for a variety of situations. In particular, this allows
>    administrators (or an arbitrary administrator-defined set of users)
>    to override the volume policies, and set e.g.  system:anyuser write
>    on a particular directory if they wish.
> 
>  - No performance overhead at access-check time. All of the additional
>    access checks are done during SetACL.
>  
>  - Minimal end-user confusion. ACLs accurately represent exactly what
>    rights different users have. Trying to set an ACL that violates the
>    policy will result in EACCES, so they know the SetACL operation
>    didn't work. It may be confusing as to why it did not, but at least
>    it is clear that the ACL was not changed.
>  
> Method 1 cons:
> 
>  - Volumes need to be 'audited' (or all of the ACLs just need to be set)
>    to make sure they comply with the ACL policy, which can be slow, and
>    is just another step that needs to be done.
>  
>  - Higher end-administrator confusion (perhaps). Setting the policies
>    can get confusing.
> 
> Method 2, "volume-level ACL overlays":
> 
> With this method, we maintain a single additional ACL in the volume
> metadata, which is applied to access checks in the volume, after
> performing the per-directory ACL check. It can be thought of as similar
> to the fileserver -implicit flag, but more generalized.
> 
> For example, if we wanted a volume where system:backups was guaranteed
> to have 'rl' rights, and system:evilusers was guaranteed to not have
> _any_ rights, the volume-level ACL would look like:
> 
> positive:
>  system:backups rl
> negative:
>  system:evilusers rlidwka

This is compelling to me, as users should already be familiar
with ACL based rights, so we are just augmententing what is
already in place.

I could see an updated fs tool to show "volume level acl(s)"
which could only be set be someone in the SUsers.

fs la /afs/example.com/user/mike
Access list for /afs/example.com/user/mike
Normal rights:
   group:foo rlidwka
   system:anyuser: rl
   mike rlidwka
   system:backups  rl (volume)
Negative rights:
   andrew rlidka
   system:evilusers rlidwka (volume)

where the (volume) indicated volume level acls, which
are read-only for a user with admin rights on a directory.


> 
> Thus, any time an access check is done on an ACL anywhere in the
> volume... after we do the normal directory ACL check, we look at this
> volume-level ACL. If the accessing user is in system:backups, they will
> get rl rights, and if they are in system:evilusers, all of their rights
> will go away.
> 
> "How do I prevent system:anyuser/system:authuser write access?"
> --
> 
> You can't. If we allow you to specify the 'anonymous' user, you could
> assign negative idwka rights to 'anonymous' on the volume-level ACL to
> prevent system:anyuser write access. But there is no way to prevent
> access for system:authuser.
> 
> Note: giving a negative ACL on, say, system:anyuser would prevent _any_
> user from getting rights; that's not what we'd want.

Since system:anyuser represents all users, it seems to me we could
introduce a way to indicate anonymous users. Perhaps with a new
system group, system:anonusers which represents users that are
not authenticed?

At that point we would specify a volume level negative right,

Negative rights:
   system:anonusers idwka



> 
> "How do I prevent group.foo write access?"
> --
> 
> Just grant negative idwka access to group.foo on the volume. Something
> like:
> 
>  vos setacl -vol user.adeason -acl group.foo idwka -neg
> 
> Members of group.foo will now not be able to write anything in the
> volume.
> 
> "How do I guarantee group.bar read access?"
> --
> 
> Same as above, just grant positive read rights. Something like:
> 
>  vos setacl -vol user.adeason -acl group.bar rl
> 
> Method 2 pros:
> 
>  - Changing the volume-level rights is quick.
> 
>  - Minimal end-administrator confusion; this is relatively simple to
>    understand.
>  
>  - Simpler than method 1 to implement.
> 
> Method 2 cons:
> 
>  - We have no way to restrict access of special groups like
>    system:anyuser, system:authuser, or host IP groups. To get this, we'd
>    have to combine with method with method 1 or 3.
>  
>  - There is no way to override the volume-level ACL, and have an
>    administrator force e.g. system:anyuser write access on a particular
>    directory.
>  
>  - Higher end-user confusion. With legacy 'fs listacl', there is no way
>    to see that there is a volume-level ACL in play, and users may have
>    no idea why access is failing for certain cases. Of course, with new
>    tools we can fix that.
>  
>  - Performance impact is an extra O(n) ACL calculation for the
>    volume-level ACL. But those ACLs should be small anyway.
> 
> Method 3, "volume ACL masks"
> 
> With this method, we maintain a mapping of users to a rights mask. Any
> time an ACL access check is performed, if a positive ACL entry matches a
> user in that table, the acquires rights are masked to the rights mask in
> the table.
> 
> For example, if we wanted to prevent users from giving away write
> access to system:anyuser, and prevent users from giving admin access to
> system:authuser, we could have a table like so:
> 
> system:anyuser rl
> system:authuser rlidwk
> 
> So any time an ACL entry for system:anyuser appears, everything is
> treated as if the rights in that ACL entry were logically ANDed with
> 'rl'.
> 
> "How do I prevent system:anyuser/system:authuser write access?"
> --
> 
> Set the rights mask for them to just 'rl'. Something like:
> 
>  vos setaclmask -vol user.adeason -user system:anyuser -mask rl
> 
> So any time an ACL entry for system:anyuser appears in the volume,
> everything will act as if the rights were limited to rl.
> 
> "How do I prevent group.foo write access?"
> --
> 
> You can't. Well, you could, but then someone could do this instead:
> 
>  pts createg adeason:foo
>  pts addu group.foo adeason:foo
>  fs sa dir adeason:foo rlidwka
> 
> which would bypass the check for 'group.foo' appearing in the ACL list.
> 
> "How do I guarantee group.bar read access?"
> --
> 
> You can't.
> 
> Method 3 pros:
> 
>  - Changing the rights mask is quick.
> 
>  - Maybe small end-administrator confusion (I don't know, is this simple
>    to understand?)
> 
>  - Runtime performance overhead is O(1).
> 
>  - Simpler to implement than method 1.
>  
> Method 3 cons:
> 
>  - Only works for restricting special groups like system:anyuser,
>    system:authuser, host IP groups, etc. Cannot restrict 'normal'
>    groups, and cannot add rights.
>  
>  - No way to override the ACL masks on a particular directory, if the
>    administrator wants to.
> 
>  - Higher end-user confusion with legacy client tools.
> 
> 
> I assume that if we don't do method 1, we could combine both of methods
> 2 and 3.
> 
> To summarize the major areas where each one is better:
> 
>                      Better     | Worse
> 		     ---------------------
> flexibility:       : method 1   | method 2+3
> end-user confusion : method 1   | method 2+3
> end-admin confusion: method 2+3 | method 1
> policy-change speed: method 2+3 | method 1
> 
> There are other pros and cons, but I think those areas are the only ones
> where it matters much.
> 

Thanks,
Mike