This is how Image Warehouse will implement what was discussed in the
thread "Image permissions, round 2".
-- Pete
* Image Warehouse permissions *
v2 2011-07-01
= attributes specification
The iwhd can run without authorization at all (as is now) or with authorization
(and supporting authentication). It is the only transition mechanism. There
is no mechanism by which iwhd running with authorization presents a compatible
view to unauthenticated clients that are deployed currently.
Owners may provide "world" access, with an an ACL entry for "*".
Authenticated
clients not explicitly listed are granted that access. Unauthenticated access
is special-cased: it has read and list access if allowed with entry '*', but
it never has write access (reason [1]).
The root, buckets, and objects may have an attribute _acl and _owner.
The _owner contains a name of the object owner (foo implies owner in all
examples below) (reason [2]). The _acl contains the following:
[
{ "name":"foo", "mode":"rwx" },
{ "name":"user1","mode":"rwx" },
{ "name":"user2","mode":"rw" },
{ "name":"user3","mode":"r" },
{ "name":"*", "mode":"r" }
]
In initial implementation, the attribute body literally contains
these data. In later implementation the list may be indexed internally.
Or, the contents of _acl can be looked up in Kerberos, LDAP, or other
component of FreeIPA. But it still looks like this when accessed through
iwhd REST API.
Users are user names that are delivered by Kerberos from IPA, or by
Basic or Digest auth, if we ever implement it. They are case-sensitive
and alphanumeric. Special characters are not allowed, except '*' and '@'.
When a root, bucket, or object is created, _owner is set. Root is set
from configuration, the rest is from API. Only the root user (_owner
of root) can change _owner. Also, an _acl is created that contains:
[ { "name":"foo", "mode":"rwx" } ]
Create and Delete are the same, with one exception: buckets owned
by someone else cannot be deleted even if the user is in _acl for
the root (e.g. can create buckets). So, 1777 /tmp semantics.
Metadata access permissions are the same as data, however _owner
can access metadata regardless of any permissions (reason [2]).
The x permission differs from r permission on root and buckets in
that it permits unfiltered access. A non-root user with r access
receives a list of his own buckets or objects (filtered list).
This is an expensive and contended operation, so there may be an
index of buckets that has _owner in actual bucket records (reason [4]).
Groups are postponed (reason [3]). We only reserve @-syntax for them.
= use model note
Mark made the following curious statement:
- Permissions on buckets - I don't think we need these. We are storing
all our objects in single buckets, so it's hard to see what we would
use these for.
We in iwhd believe that multi-tenancy is absolutely essential (same as
in CloudFS). If Conductor wants to dump everything into one bucket, we
do nothing to preclude that. However, our use model presupposes
that every tenant gets to create a number of buckets (plus a few
system buckets for shared images).
= performance impact (TBD - action zaitcev)
extra DB overhead per
- list bucket
- filtered list on root
- create/delete bucket
- create/delete object
- create object and set custom ACL
= checklist
+ non-unix; ACL; user==_owner
- default user: configurable, for transition period
-- rejected. just '*' and that's it
+ root user - can do chown; configurable name... owner of root object?
+ root object (permits to create buckets)
- write permission on bucket == delete on object.
-- delete on bucket - see 1777.
+ default ACL: create object&bucket adds built-in default ACL
-- no configurable _default like in POSIX 1.e
+ chown prohibited (except for root); owner always exists, req. for quota
- concurring access atomicity
<== ACL update is not atomic unless we add "modify" op (HTTP method?)
- group concept
-- postponed, but is necessary
+ permissions of metadata and data on the object
+ tenants own, create/delete/list isolated
-- however provider is root; tenants must encrypt if no trust provider
+ tenants metadata no leaks
= reasoning
[1] Why unauthenticated access cannot write even if "*:w"?
Because they cannot create "_owner". Maybe later we special-case write into
pre-existed object, and creation of new attributes. This is still not
compatible with iwhd in "without authorization" mode, because they cannot
write into buckets (== create objects).
[2] Why have _owner attribute at all? The initial _acl affords the same
permissions that _owner does, and we permit anyone with "w" to remove
permissions by updating _acl. This makes no sense!
Because of a couple of reasons (at least).
First, _owner provides a safety net, so users can restore permissions
or delete anything they created. Provider (root user) does not want to
field trivial help calls. Also, users are charged per byte, so it is
only fair to give them this control.
Second, although quotas checked incrementally and do not need _owner
normally, if a consistency checker has to recalculate quotas, it will
need _owner.
[3] Why no groups?
Because we want something working quickly. Anyone who deals with ACLs in
practical terms says that they are essential. Mark's memo says "for large
organizations, group permissions will also be needed." We plan on
adding groups as a syntax, e.g. entries in _acl will have '@' at the front,
then the accessor is matched against the group after '@', and if succeeds,
it is granted access described by bits. This seems compatible.
[4] Why have filtered access and a whole separate x bit?
The x permission is separate in order to prevent leaking of data and
metadata among tenants. We expect that next to nobody is going to
have it set, but we'll see. This is still under discussion as an
efficient implementation is being determined. We do not want any
requiest to list buckets to lock the whole DB and read 10,000,000
_acl attributes.