HATEOAS Openstack Keystone

Of all the principals of REST, perhaps the most overlooked it Hypermedia as the Engine of Application State, or HATEOAS. This term tries to encapsulate several concepts together, but the primary is the principal of discoverability.

All future actions the client may take are discovered within resource representations returned from the server.

What does this mean for Keystone?

Keystone is currently a fairly simplistic application.  It can issue tokens to users,  and it can verify that a given token has been assigned to a user.  Assuming for the moment that this is all we want to be able to do,  we should be able to discover this from the top down.

Keystone listens on two ports: 5000 and 35357.  Pointing a browser at either of these should be the start of the discovery process.  Indeed,  we see that the server returns three hyperlinks to us.  The second and third links  are for documentation,  and lead us not to other resources controlled by the server,  but back to docs.openstack.org.  Only the first provides guidance,  but it makes an interesting design decision.  It points us to the sub url for a version of the Keystone library.  On my development server, this url is http://localhost:5000/v2.0/.  Submitting this URL only provides us with the same information again.

What should it show us?  Lets forget for a moment that this service is specifically for programmatic use, and imagine instead that we are building a web based user interface.  From previous experience,  we know that the URL to request a token is http://0.0.0.0:5000/v2.0/tokens.  However, this is specifically accessed via a POST action. 

Lets ignore authentication for a moment. Keystone integrates authentication with token access. However, they are distinct options. If we remove the password value from the “request token” form we get something that accepts:

userid
The user that should be associated with the token. This can be the authenticated user, but there are use cases where it we might want to delegate the ability to create a token.
tenantId
This limits the scope of the token

So without authentication, other applications need a way to indicate that they should provide this data in order to create a token. For a webUI, this would be something like:

Aside from this being a functional form in its own right, it provides sufficient information to another system to indicate how to create a new token.

The URL of the token validation is of the form  http://0.0.0.0:35357/v2.0/tokens/$TOKEN,  we would want a form that allows the user to submit that value.  A form can do a Get action, but it cannot rewrite the target hyperlink without Javascript, something we would avoid here.  We do not want to enumerate all tokens, as that would wrongly expose shared secrets.  Thus, a post to an URL with a parameter of the token ID, as well as any other identifying information required would be more useful.  This would be token id,  user id, and tenant id.  The HTML response code would be 200, and the body of the response would indicate valid or invalid.  This post could also return a hyperlink to the original  URL  of the form http://0.0.0.0:35357/v2.0/tokens/$TOKEN,  and that URL would still be accessible via HTTP GET.

This form could easily be displayed in JSON:

{"fields":["name","userid","tenantid"]}

This would could be extended with more information about fields types and so forth.

So from the top level of the Keystone site, once the user is authenticated and has passed down through the hyperlinks:


And clicking through to tokens:



Add New Token

Validate Token

These last two forms probably should only be shown if the content type is set to HTM or XHTML.

Right now, even if content type is set to HTML, Keystone resorts to XML. The first step is to add a marshaller for HTML alongside to the JSON and XML marshallers, and then to support each of the content types equally.

Should Keystone support HATEOAS? I’d say yes. It makes the system more transparent and less surprising. It will give the implementors a means to debug at the server level, while not denying them the ability to hit things programmatically or from the CLI. It will also, I think make the design more solid move forward, as it will be more visually obvious how the different members of the Keystone domain model fit together.

3 thoughts on “HATEOAS Openstack Keystone

  1. Hi Adam,
    Keystone is in the way to support HATEOAS,
    The problem is a browser policy called “Same Origin Policy”:
    (http://en.wikipedia.org/wiki/Same_origin_policy)
    This problem can solve only with cross-origin resource sharing
    (http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/)
    Now OpenStack is trying to implement it in Object Storage Api via:
    (http://docs.openstack.org/api/openstack-object-storage/1.0/content/assigning-cors-headers-to-requests.html#d6e721)
    But keystone does not support it yet, although they have raised find a solution in the form of extension via “domains”:
    https://blueprints.launchpad.net/keystone/+spec/keystone-domains
    and in the Essex Design Summit they talk about it:
    http://essexdesignsummit.sched.org/event/9d566ada9557a01e051903e8008cf898

  2. Rubén,
    Thanks for the response. I think you are equating Dashboard Discoverability with Keystone discoverability. Both are important. Same Origin Policy can be dealt with many ways, but I think the best is to get a real Single Sign on Solution, which means Kerberos or X509 certificates. I’ve written about those elsewhere.

    Dashboard can act as a proxy to the other services, which is probably the best way to get around the same origin policy, but it won’t scale horizontally. Cross Origin resource sharing is not a good idea in the short term, as it will require too much on the part of the client (hacked browser is a no-no).

    I think that this and the PKI issues will be great to discuss at the Summit.

  3. Keystone can’t work as a proxy anymore. I think that feature disappeared with Keystone Light.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>