[openstack-dev] generate ec2 keypairs from a token

Matthieu Huin matthieu.huin at enovance.com
Mon Jul 29 16:46:09 UTC 2013

Hello Steven,

I am moving this discussion to openstack-dev as requested. As stated earlier, 
the purpose is to improve this blueprint: 

First, thanks for your explanations, they made the problem much clearer. I've updated
the wiki page accordingly, please tell me if I missed or misunderstood something.

Some in-line answers follow.

Thank you,

Matthieu Huin 

mhu at enovance.com

----- Original Message -----
| From: "Steven Hardy" <shardy at redhat.com>
| To: "Matthieu Huin" <mhu at enovance.com>
| Cc: ayoung at redhat.com
| Sent: Monday, July 29, 2013 11:01:02 AM
| Subject: Re: generate ec2 keypairs from a token
| Hi Matthieu,
| Putting Adam Young on Cc as we discussed this feature at Summit.  Note we
| should probably try to direct future discussions like this to openstack-dev
| where possible 
| On Mon, Jul 29, 2013 at 08:13:02AM -0000, Matthieu Huin wrote:
| > Good morning Steven,
| > 
| > On behalf of my employer, I've been looking into the problem of
| > generating ec2 keypairs from a trust token and produced a blueprint:
| > https://blueprints.launchpad.net/keystone/+spec/ec2-keypairs-from-tokens
| Thanks for drafting this, I've been meaning to do it but have been too busy
| with other tasks.
| > I am not sure I totally grasp what is at stake though, since I don't
| > know Heat very much. Since you mention the problem in your own blueprint
| > ( https://blueprints.launchpad.net/heat/+spec/instance-users ), could
| > you check my blueprint and possibly give me more insight on the intended
| > use case ?
| So the use-case for heat is to allow an in instance user to authentiate
| with our CFN compatible API (which supports ec2 style signed requests,
| which require an AWS style keypair to generate).
| https://github.com/openstack/heat/blob/master/heat/api/aws/ec2token.py
| https://github.com/openstack/heat-cfntools/blob/master/heat_cfntools/cfntools/cfn_helper.py#L56
| Currently we generate a keypair associated with a user created in the heat
| template, to which we add a "heat_stack_user" role, which is used to limit
| access to specific API actions (via policy.json):
| https://github.com/openstack/heat-templates/blob/master/cfn/AutoScalingMultiAZSample.template#L91
| https://github.com/openstack/heat/blob/master/heat/engine/resources/user.py#L80
| https://github.com/openstack/heat/blob/master/heat/common/heat_keystoneclient.py#L86
| The problem with this is that it doesn't scale - we're creating lots of new
| keystone users (for the User resource and also the WaitConditionHandle
| resource, which creates a pre-signed request), for every stack which
| defines these resources.
| The other problem is it requires the user creating the stack containing
| these resources which create keystone users to be a keystone admin:
| https://bugs.launchpad.net/heat/+bug/1089261
| So using keystone trusts with the scheme described in your BP should allow
| us instead to create a trust token, then create an ec2 keypair associated
| with the *trustor* (user being impersonated) of the token, or just with the
| token itself I guess:
| https://github.com/openstack/identity-api/blob/master/openstack-identity-api/v3/src/markdown/identity-api-v3-os-trust-ext.md
| So this should remove the need to be keystone admin to create an ec2
| keypair associate with the user owning/creating a heat stack.
| However this creates a new issue, which is that we must drop all roles from
| the user when creating the trust token (before we create the ec2 keypair),
| as the credentials are to be deployed inside an (implicitly untrusted)
| instance.  We can use the "roles" key of the trust token POST to do this,
| but then we lose the ability to restrict access via policy.json (as you can
| only drop roles not add them).  I've not yet figured out the best solution
| to this last problem.

I believe this is out of scope for this blueprint, but here are a few ideas:

* the trustor (ie the stack creating user) should have the "heat_stack_user" role,
and delegate this role only (and the one needed to request an ec2 keypair) to the trustee.
* keystone's ec2 API should have a way to generate keypairs tied to a specific role
for untrusted users.
* if impersonation is not set in the trust, the trust token could provide the union of
both trustee's and trustor's roles (maybe it's already the case ?). This means we could
have a heat_stack_user created specifically for heat and that can only make minimal calls
to the API, that would be trusted to request ec2 keypairs on behalf of the stack creating
user as needed. The keypairs would grant the rights defined by the heat_stack_user

| So ref your wiki page:
| https://etherpad.openstack.org/ec2KeypairsFromTokens
| > the server makes sure this token was generated from a trust, for example
| > by checking the presence of a "trust" section. If not, an error message
| > is returned
| So this is OK for the heat use case, but it seems to be possibly missing an
| opportunity to make the mechanism more generic, ie just allow creating an
| ec2 keypair from a token, and if it's a trust token use the trustor ID, if
| it's a normal token use the ID of the token-owning user?
| I guess you need feedback from the keystone devs on what makes sense here.

I assumed we should encourage using these new calls only for the specific case 
where you do them on behalf of another user. If you want a keypair for yourself, 
you can use the normal API for that.
| > Can there be several keypairs generated from one given token, or should
| > credential creation return an existing keypair if available ?
| Yes, probably, as the lifecycle of the ec2 keypair may be different to that
| of the trust token, you can have multiple ec2 keypairs associated with a
| user, so it seems reasonable to allow the same wrt a trust token (maybe?)

I agree on that.

| > the user making the API call is either the keypair's "user id" or
| > "trustee id".
| The terminology is confusing, but I think you mean "trustor id", which is
| the user being impersonated?
No, I meant the trustee id. This refers to what happens when authenticating,
deleting or getting credentials. So we have three possibilities:

1. The user making the call didn't generate the keypairs from a trust. Then she
is referenced in the backend by her user id.
2. The user making the call generated the keypair from an impersonating trust.
then she is referenced in the backend by the trustee's id (the user id in the
backend being the one of the impersonated trustor).
3. The user making he call generated the keypair from a trust where impersonation
was disabled. Then she is referenced in the backend by the user id.

I hope it is clearer that way ?

| > if the keypairs' validity is linked to the token's validity, there is
| > some cleanup to take into account, ie drop the keypair from the backend
| > when the token expires.
| Yes, if the trust token expires or is deleted, the keypairs should be
| deleted or invalidated, but note as mentioned above that the reverse
| shouldn't be true, ie deleting the ec2 keypair(s) should be possible without
| affecting the trust token.

Yes, I added it in the spec.

| Thanks,
| --
| Steve Hardy
| Red Hat Engineering, Cloud

Matthieu Huin 

mhu at enovance.com

More information about the OpenStack-dev mailing list