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
(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

- Require username/password to be passed into the service (something we've
   been trying to banish via migrating to trusts for deferred
- 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

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:



OpenStack-dev mailing list

OpenStack-dev mailing list

Reply via email to