[openstack-dev] [all] [clients] [keystone] lack of retrying tokens leads to overall OpenStack fragility

Adam Young ayoung at redhat.com
Tue Sep 16 16:55:38 UTC 2014


On 09/15/2014 08:28 PM, Nathan Kinder wrote:
>
> On 09/12/2014 12:46 AM, Angus Lees wrote:
>> On Thu, 11 Sep 2014 03:21:52 PM Steven Hardy wrote:
>>> On Wed, Sep 10, 2014 at 08:46:45PM -0400, Jamie Lennox wrote:
>>>> For service to service communication there are two types.
>>>> 1) using the user's token like nova->cinder. If this token expires there
>>>> is really nothing that nova can do except raise 401 and make the client
>>>> do it again. 2) using a service user like nova->neutron. This should
>>>> allow automatic reauthentication and will be fixed/standardied by
>>>> sessions.
>>> (1) is the problem I'm trying to solve in bug #1306294, and (for Heat at
>>> least) there seems to be two solutions, neither of which I particularly
>>> like:
>>>
>>> - Require username/password to be passed into the service (something we've
>>>    been trying to banish via migrating to trusts for deferred
>>>    authentication)
>>> - Create a trust, and impersonate the user for the duration of the request,
>>>    or after the token expires until it is completed, using the service user
>>>    credentials and the trust_id.
>>>
>>> It's the second one which I'm deliberating over - technically it will work,
>>> and we create the trust anyway (e.g for later use to do autoscaling etc),
>>> but can anyone from the keystone team comment on the legitimacy of the
>>> approach?
>>>
>>> Intuitively it seems wrong, but I can't see any other way if we want to
>>> support token-only auth and cope with folks doing stuff which takes 2 hours
>>> with a 1 hour token expiry?
>> A possible 3rd option is some sort of longer lived, but limited scope
>> "capability token".
>>
>> The user would create a capability token that represents "anyone possessing
>> this token is (eg) allowed to write to swift as $user".  The token could be
>> created by keystone as a trusted 3rd party or by swift (doesn't matter which),
>> in response to a request authenticated as $user.  The client then includes
>> that token in the request *to cinder*, so cinder can pass it back to swift
>> when doing the writes.
>> This capability token would be of much longer duration (long enough to
>> complete the cinder->swift task), which is ok because it is of a much more
>> limited scope (ideally as fine grained as we can bother implementing).
> With UUID tokens, it would even be possible to implement a "one-time
> use" sort of token.  Since Keystone needs to be asked to validate a UUID
> token, the token could be invalidated by Keystone after the first
> verification.  Since the token is limited based off of number of times
> of usage, there should be less concerns about a long validity period
> (though it would make sense to use something sane still).  This approach
> wouldn't be possible with PKI tokens since Keystone is not in the
> validation path.
>
> Your idea of passing the "capability token" in the request would work
> well with this, as the token only needs to be extracted and used once
> instead of being passed from service to service and validated at each
> hop (user>cinder->swift in your example).
>
> The idea would be to leave normal tokens with a smaller validity period
> (like the current default of an hour), but also allow one-time use
> tokens to be requested.

It is dumb to make service get a token just to hand the token back to 
Keystone.

Guang Yee has pushed for years to get a capability into Keystone where 
certain API calls did not require a token, but would instead the 
permission would be based on whatever the users capabilites were at the 
time.

The problem is that "Admin" in the default policy (and hardcoded in V2) 
is definded to mean "User has the role admin on anything"  which is, of 
course, suboptimal (to say the least).

So validating a Token should not require a token.  We could add to the 
request some standard Stanza for saying "Here is the project/domain that 
I want to do this with"  so that we can atleast Keep Keystone's current 
behavior somewhat sane....




>
>> (I like this option)
>>
>>
>> A 4th option is to have much longer lived tokens everywhere (long enough for
>> this backup), but the user is able to expire it early via keystone whenever
>> they feel it might be compromised (aiui this is exactly how things work now -
>> we just need to increase the timeout).  Greater exposure to replay attacks,
>> but if detected they can still be invalidated quickly.
>>
>> (This is the easiest option, it's basically just formalising what the
>> operators are already doing)
>>
>>
>> A 5th option (wow) is to have the end user/client repeatedly push in fresh
>> tokens during long-running operations (and heat is the uber-example since it
>> basically wants to impersonate the user forever).  Those tokens would then
>> need to be refreshed all the way down the stack for any outstanding operations
>> that might need the new token.
>>
>> (This or the 4th option seems ugly but unavoidable for "forever" services like
>> heat.  There has to be some way to invalidate their access if they go rogue,
>> either by time (and thus needs a refresh mechanism) or by invalidation-via-
>> keystone (which implies the token lasts forever unless invalidated))
> I think Keystone trusts are better for "forever" services, though I see
> no reason why a trust token also couldn't have a limited number of uses
> with a longer validity period.  The trust itself doesn't need an
> expiration, so the trust can be executed at some future point in time to
> get a limited use trust token.
>
>>
>> However we do it:  the "permission" to do the action should come from the
>> original user - and this is expressed as tokens coming from the original
>> client/user in some form.   By allowing services to create something without
>> the original client/user being involved, we're really just bypassing the token
>> authentication mechanism (and there are easier ways to ignore the token ;)
> Yeah, this is ugly.  You give up any control you have as soon as you
> hand off your token.  This is where restricted tokens would be ideal.
> As it stands today, most services that are using trusts intercept the
> user's token and create the trust AFAIK.  More ideal from a security
> standpoint would be to ask the user to create a trust, which they
> perform with a more privileged token than they ever pass around to any
> service other than Keystone (like an unscoped token).  They would then
> pass the trust ID to the service that needs to execute the trust at a
> later date along with a more restricted scoped token.  This would
> require behaviour such as I describe in this writeup:
>
>    https://blog-nkinder.rhcloud.com/?p=101
>
> -NGK
>
> _______________________________________________
> OpenStack-dev mailing list
> OpenStack-dev at lists.openstack.org
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev




More information about the OpenStack-dev mailing list