Image permissions, round 2

Scott Seago sseago at redhat.com
Tue Jun 7 12:16:35 UTC 2011


On 06/07/2011 05:08 AM, Mark McLoughlin wrote:
> On Thu, 2011-06-02 at 10:47 -0400, Scott Seago wrote:
>
>>> We obviously need the concept of permissions that apply to individual
>>> users, as well as a 'world' permission that applies to everyone. For
>>> large organizations, group permissions will also be needed.
>>>
>>> In order to enforce user permissions, we clearly need to authenticate
>>> users. We probably need to support three different authentication modes:
>>>
>>>     i) For standalone usage of IWHD, a simple user/password database.
>>>        Perhaps just keep this in Mongo.
>>>
>>>    ii) When use with Conductor, IWHD should be able to authenticate using
>>>        Conductor's REST API - i.e. in IWHD config, allow an "HTTP
>>>        authentication URL" to be specified which IWHD will do Basic HTTP
>>>        authentication against.
>>>
>>> iii) For use with Conductor where Conducor isn't using its own DB as its
>>>        user store (perhaps it is using IPA, LDAP or even just the
>>>        local /etc/passwd), IWHD should be able to authenticate using PAM.
>>>
>>> Permissions will be represented by metadata tags on object, each of
>>> which can either contain "rw" or "r":
>>>
>> What about "x", where "x" grants a user the right to launch an instance
>> from it? i.e. Someone may have permission to view an image but not to
>> launch an instance using it?
>> Clearly in this case IWHD's enforcement is only indirect, since once the
>> calling client has the ID for the provider image, a deltacloud call will
>> launch it, but it might be useful for query purposes. i.e. having an API
>> call to return a list of those images that the user has permission to
>> launch (as opposed to merely the permission to read).
> Right, having the launch permission on an image will be useful to
> conductor ... but this would be a metadata tag which is opaque to IWHD.
>
Hmm. I'm not sure how well that will work, as it would essentially 
entail "yet another permissions system", this time implemented via 
metadata tags -- meaning that we'd need to define a scheme where we tag 
each object with some combination of action and username (or group) -- 
i.e. "execute:sseago", "execute:devteam", etc.

So actually I guess it's not all that complicated, but it's also 
yet-another-overloading-of-tags here.
> It doesn't make to include the launch permission in the set of
> permissions understood by IWHD ... because it doesn't understand the
> permission.
>
>
>>>    - 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. In any case, if we want to limit the ability of users
>>>      to create objects, then bucket permissions are probably the way to
>>>      go.
>>>
>>>    - Does Conductor authenticate as the Conductor user when talking to
>>>      IWHD?
>>>
>>>    - No need for a "w" permission, right? i.e. granting the permission to
>>>      write without the permission to read?
>>>
>>>    - The "rw" permission grants the user permission to delete the object.
>>>
>> - Are permissions only stored on images? i.e. we don't track separate
>> permissions on a per-build, per-provider image, etc basis? I'd think
>> we'd want to manage permissions only on top-level image objects unless
>> we have a clear use case  that requires more granular control.
> IWHD would have permissions on all objects. It doesn't differentiate
> between objects
>
So presumably we don't want to force users to recreate all permissions 
tags in each level of the hierarchy. Should it be possible to give a 
user access to see every build and provider image simply by granting 
access to the top level image (so that permissions are automatically 
inherited from Image to Build, from Build to Target Image, etc.)? Or do 
we need to require a user be individually granted access to each build 
(and target image and provder image) separately?

>> - What about 'create' permissions? i.e. who has permission to create and
>> build images? Or will this be handled exclusively via the 'quota'
>> mechanism (rather than permissions) -- i.e. if your quota is '0' you
>> can't create/build.
> The only create permission that makes much sense to me for IWHD is a
> write permission on buckets
>
What about the ability to create new images? i.e. "can this user create 
a new image (as opposed to a new build on an existing image?) This would 
need to be a permission not associated with any particular resource 
(i.e. analogous to Conductor site-wide permisions)

Once the top level image is in place, further "create" permissions would 
be attached to individual resources. In other words, in order to create 
a new build, you'd need 'create' (or 'create build') permissions on the 
image. Perhaps we'd need a similar permission on the TargetImage in 
order to push to a provider, although the specifics are less clear to me 
on that one.
>>> = 2. Environment Policy =
>>>
>>> Images are assumed to undergo a lifecycle where one version of the image
>>> may be in production, another in staging and another in development.
>>>
>>> These lifecycle phases are exposed to the user as environments in
>>> Conductor. Some images may only be available in development or you may
>>> may only have specific builds of an image available in each of the
>>> environments.
>>>
>>> The image administrator defines this policy - i.e. which environments
>>> the image is allowed in, and which version of an image is appropriate
>>> for each environment - using the aeolus-image CLI which, in turn, sets
>>> metadata tags on IWHD objects to represent the policy.
>>>
>>> When a user launches a deployable, or explicitly chooses an image to
>>> launch, Conductor enforces the policy by comparing the environment the
>>> user is launching the deployable/instance in to the the metadata tags.
>>>
>>> The metadata tags defining this policy are place on "image" objects in
>>> iwhd and are simply:
>>>
>>>     latest_build:<environment>   = build UUID
>>>     latest_build = build UUID
>>>
>> Do we need an explicit latest_build tag, or can the API just grab the
>> most recent build for an image (optionally filtered by tag)?
> Which API do you mean?
>
> Remember, these tags are opaque to IWHD
>
I'm talking about Conductor's way of finding the latest build. Instead 
of maintaining a single build per environment as "latest" we'd have a 
set of builds that's valid for each environment. For any given 
environment, "latest" would be found by getting the list of valid builds 
(all builds with either no environment tags or with a tag for this 
environment) and then taking the latest in the list.
>>> The policy is enforced as follows:
>>>
>>>     - When launching a deployable in an environment, Conductor resolves an
>>>       image reference to a set of provider images by first looking at the
>>>       environment specific latest_build tag. If this doesn't exist, it
>>>       looks at the global latest_build tag. If this doesn't exist, the
>>>       deployable can't be launched
>>>
>>>     - When listing images available to be launched in a given environment,
>>>       Conductor searches for all images with either an environment
>>>       specific or global latest_build.
>>>
>> So I had envisioned something slightly different. The problem with
>> managing environment-specific builds with only the 'latest_build' tag is
>> that you don't have a way of limiting usage per environment when the
>> deployable specifies a particular build.
> Well, there are a couple of things to consider here:
>
>    1) Do we want to a) make it impossible for users to run an unapproved
>       build in an environment, or do we want to b) just make the default
>       workflow such that they run approved builds but they can force an
>       unapproved choice if they wish
>
>    2) Even if we want 1.a), do we make this an administrator policy
>       decision (i.e. don't allow versioned image references) or do we
>       want to make 1.b) impossible no matter what the configuration
>
> IMHO, 1.a) is plausible enterprise deployment policy, but 1.b) is useful
> for less locked down environments
>
> Summary: I think we just need a "don't allow versioned image references"
> policy for administrators to configure
>
So this is the essential question -- the implementation difficulties 
below are of lesser importance - we can make it work if we need to -- 
the more important question is what behavior is desired.

My understanding of the environment-build connection is that we wanted 
an explicit mapping of what builds are valid/approved for each 
environment, rather than just defining a different "default build" per 
environment. If we do need to tag all "valid" builds, then we need to 
tag builds as I had proposed. If we're only doing this to provide a 
default build for each environment, then your proposal here is more 
straightforward -- although in that case perhaps we should call it 
default_build rather than latest_build, since it's not necessary the 
latest one the user will get -- the user will get whichever build has 
been tagged.
>>   Would it make more sense to,
>> instead of using latest_build tags, tag each build with the list of
>> allowable environments? If the build has no env tags, then it's
>> available for all environments. Then "latest build for $foo_environment"
>> is determined by filtering the build list for an image, omitting any
>> builds which:
>> 1) have at least one environment tag
>> 2) do _not_ have a tag for $foo_environment
> A few problems:
>
>    1) IWHD doesn't (yet? easily?) do lists as metadata values
>
Yes, this bit has caused problems for us before. I'm not sure we need a 
list here or just  a separate tag for each environment. We'd then just 
look for tags in the format of "environment:foo" -- i..e 
"environment:dev", "environment:ec2-testing", or whatever.
>    2) It becomes harder to resolve a versionless image reference to a
>       specific build - you get the list of builds and you have to decide
>       which one is the latest build for the environment
>
If the builds are timestamped, then "latest" is fairly easy to figure 
out. You get a list of valid builds for the environment and then you 
simply grab the one with the latest timestamp.
>    3) You can no longer restrict the ability to add a build to an
>       environment by restricting the permissions on the image object
>
Ahh so here's another "we need a use case" scenario. Ultimately, who 
should have permission to tag builds per environment -- the user with 
write permission on the build or the user with write permission on the 
image? If the latter, then this could be an issue.

But again, see above, the big question here is which of the two 
approaches matches the desired behavior properly.
>>> The image building CLI for this might look like:
>>>
>>>     $>   aeolus-image build -t ec2 -e my.tmpl -i -i 2d134860-9762-4cc3-8e63-4fab7d31ad1b
>>>     ...
>>>     Rebuilding image: -i 2d134860-9762-4cc3-8e63-4fab7d31ad1b
>>>     New build: 54848312-2d3e-405e-ac34-0c67bba22ee8
>>>     $>   aeolus-image add-env -i 2d134860-9762-4cc3-8e63-4fab7d31ad1b --env prod -b 54848312-2d3e-405e-ac34-0c67bba22ee8
>>>     Set latest_build:prod = 54848312-2d3e-405e-ac34-0c67bba22ee8 on image 2d134860-9762-4cc3-8e63-4fab7d31ad1b
>>>
>>> Note that these commands could be run by two users with different roles.
>>> The first user may only have permission to rebuild images, whereas the
>>> second user would be the only one that could update the latest_build tag
>>> on the image object.
>>>
>>> Open questions:
>>>
>>>    - There was discussion about whether the environment a user is in
>>>      should translate to access control permissions in IWHD - i.e. unless
>>>      I have been added to the development environment, not only should I
>>>      not be able to launch an instance using development images, but I
>>>      also should automatically not be able to see them using the CLI.
>>>
>> Yeah I don't think we need to explicitly add users to environments here.
>> This is handled by permissions/policy on conductor already. In
>> conductor, each pool belongs to a single environment. If we do not
>> intend to allow a user to access the development environment, then we
>> simply do not add this user to any of the development pools. So the
>> user-environment permissions are handled by granting users explicit
>> permissions to launch deployments in (environment-specific) pools
> Yeah, but this still means that which environments the user has been
> added to (by adding her to pools) does not influence her read/write
> permissions at an IWHD level.
>
> But again, I'm not sure what the important use case is here.
>
Right -- IWHD read/write is handled by IWHD permissions. The only place 
that environment-level read/write may matter would be if we wanted to 
enforce who has permission to set environment tags  (i.e. users can only 
tag for 'prod' if they have permissions on 'prod' -- that's something 
that would only be enforced by Conductor (cli/web) tools, though, as 
only conductor would know about those permissions).

So for this sort of write permission we would want to deal with users 
being added explicitly to the environment. For end users launching 
instances, though, they'd probably not have direct access to the 
environment. Rather they'd have access to a pool within the environment.
>>>      The implication here is that there would be a group visible to IWHD
>>>      for each environment which represents all the users added to the
>>>      environment. In the case of a shared identity store like IPA, this is
>>>      doable by having Conductor manage the group membership of the
>>>      environment groups. In the absence of a shared identity store,
>>>      perhaps we leave it up to the admin to set up these groups if they
>>>      so wish.
>>>
>>>      All that being said, I'm really struggling to convince myself that
>>>      this is terribly important. Given that so much of the discussion got
>>>      wedged on how to do this, I'd suggest punting on it for now if it's
>>>      not critical.
>>>
>> And, as I mentioned above, conductor already provides another way to do
>> this.
> Right, at the Conductor level. If the user goes to IWHD directly or
> through the CLI, the "users' environments" is no longer considered.
>
Sure -- so if we wanted to we could come up with some sort of automatic 
exporting here where we collect the set of users that have write access 
to an environment and export this as a group or other entity for IWHD to 
use to enforce who can set environment tags or something similar. I'm 
not sure we'd need this for anything other than this one purpose. What 
we don't do is manage the list of users with permision on an environment 
as an IPA/ldap group. Just like with IWHD permissions on images, 
Conductor permissions on environments (or pools or whatever) are managed 
as a list of explicit permission grants -- each one representing a 
single user (or group), a resource (in this case an environment) and a 
role (collection of actions the user/group is allowed to perform) -- so 
this isn't managed as a single group but as a collection of permission 
grants.
>>>    - The CLI commands for managing environment tags clearly require more
>>>      thought.
>>>
>>>    - If the user doesn't have write permissions to the image object, they
>>>      may be able to create a new build of the image, but they can't e.g.
>>>      update the description of the image which is stored in the image
>>>      object's body.
>>>
>> This sounds like we need another permission bit on the image. 'c' --
>> meaning they can create new builds under this image.
>> So (combining w/ the 'x' bit suggestion above) the valid permission
>> combinations are:
>> 1) 'r'
>> 2) 'rw' (although in practice 'w' without 'c' may not make sense
>> 3) 'rc'
>> 4) 'rwc'
>> 5) 'rx'
>> 6) 'rcx'
>> 7) 'rwcx' (omitting 'rwx' on similar grounds to not needing 2) )
> In order for IWHD to enforce this, it would need to understand the
> relationship between images and builds. It doesn't.
>
> I'm suggesting using the write permission on the image object to limit
> the ability to create new builds (or more precisely, tag a build as the
> latest build globally or for an environment).
>
Do we conflate 'create' and 'write' here? i.e. does the CLI only allow a 
user to create a new build for an image if the user has write access for 
that image? If we want to allow users to initiate new builds without 
write access on the top level image, then we'd need some way of 
determining who can do this -- or will we have to include this as an 
encoded "permission metadata tag" like you'd suggested for 
launch/execute" permissions above?

Scott

> Cheers,
> Mark.
>



More information about the iwhd-devel mailing list