Dynamic Policy in Keystone

Ever get that feeling that an epiphany is right around the corner? I spent a good portion of the OpenStack summit with that feeling. I knew that it would not be earth shattering, or lead me to want to rewrite Keystone, but rather a clarification of how a bunch of things should fall together. The “click” happened on the second to last day, and it can be summarized in a few key points.

When discussing the OAUTH1.0 extension to Keystone, several people commented on how it was similar to trusts, and that we should have a unified mechanism between them for delegation. During a discussion with David Chadwick, he mentioned that the role assignments themselves were a form of delegation, and lamented that we were losing the chain of delagtion by how we delegate roles. So the first point was this:

Keystone should have a single, unified mechanism for delegation.

One key feature that feeds into that is the ability to break a big role into a small one. I had posted a spec for hierarchical roles prior to the summit, but wasn’t clear for how to implement it; I could see how it coule be implemented on the token side, but all people I talked to insisted it made more sense on the enforcement side. That is the second big point.

Role inheritance should be expanded by policy enforcement.

Policy is almost all static. Each OpenStack project had it’s own policy file in its own it repo. Extending it to cover is user requests for things like project specific policy or more granular roles has not been possible.

UPDATE: I’ve been asked to make clearer what problems this addresses.

  1. Determine what roles a user can assign to another user
  2. Allow a user to determine what roles they need to perform some action
  3. Allow some user interface to determine what a user is capable of doing based on their roles
  4. Establish an iterative process solve the long-standing bug that a user with admin on any scope has admin on all scoped.
  5. Allow a user to delegate a subset of their capabilites to a remote service.

What we have now is a simple set of specs that build on each other that will, in the end, provide a much more powerful, flexible, and consistant delegation mechanism for Keystone. Here are the General steps:

  1. Graduate oslo policy to a library
  2. Add to the policy library the essential code to enforce policy based on a keystone token.  I’ve looked at both the Keystone and Nova pieces that do this, and they are similar enough that we should not have too much problem making this happen.
  3. Add in the ability to fetch the policy.json file from Keystone.
  4. Add a rule to the Keystone policy API to return the default policy file if no policy file is specified for an endpoint.
  5. Merge the current default policy files from all of the projects into a single policy file, with namespaces that keep the rules from conflicting across services.  Reduce the duplication of rules like “admin_or_owner”  so that we have a consistent catalog of capabilities across OpenStack.  Make this merged file the default that is served out of Keystone when an endpoint asks for a policy file and Keystone does not have an endpoint specific file to give it.
  6. Make a database schema to hold the rules from the policy file.  Use this to generate the policy files served by Keystone.  There should be no functional difference between the global file and the one produced in the above merge.
  7. Use the hierarchical role definitions to generate the rules for the file above.  For example, rules that essentially say “grant access to a user with any role on this project”  will now say  “grant access to any user with the member role, or with any role that inherits the member role.  The member role will be the lowest form of access.  Admin will inherit member, as will all other defined roles.
  8. Break member up into smaller roles.  For example,  we could distinguish between actions that can only read state from those that can change it:  “Observer”  and “Editor”  Member would inherit editor, and editor would inherit observer.
  9. Change the rules for specific API policy enforcement points to know about the new roles.  For example, the API to create a new image in glance might now require the editor role instead of the member role.  But, since member inherits editor, all current users will be able to perform the same set of operations.
  10. Change the role assignment mechanism so that a user can only assign a role that they themselves have on the designated scope.  In order to assign Member, the user must have the member role, or a role that inherits Member,such as admin.  Role assignment, trusts, oauth, and any other mechanism out there will follow this limitation.  We will have to perform additional limitations, such as determining what happens to a delegated role when the person that does the delegation has that role removed;  perhaps one will need a specific role in order to perform “sticky” role assignments that last past your employment, or perhaps we will allow a user to pass some/all their delegations on to another user.

 

This is still in the planning stage.  One nice thing about a plan like this is that each stage shows value on its own, so that if we only get as far as, say stage 3, we still have a better system than we do today.  Many of the details are still hiding in the weeds, and will require more design.  But I think the above approach makes sense, and will make Keystone do what a lot of people need it to do.

7 thoughts on “Dynamic Policy in Keystone

  1. Adam, I’m not clear of the relationship between the policy module, endpoint_policy extension and their connection with policy.json.

    Policy module in Keystone has its own backends, are the “policies” this module stores the same as the entries in policy.json?

    I’m really interested in the part of access control in Keystone, looking forward to your reply.

  2. Good question Darren. The answer is worthy of its own blog post.

    Right now, the backend is under utilized; People tend to run Keystone with the policy.json out of the repo, and stored in the file system. So, while the one stored in the backend are supposed to be the same as the ones the Keystone server uses, this is rarely the case, and one of the things I’d like to fix.

    I’ll try to go in more depth in a full post.

  3. Thanks to your answer Adam, now I’m much more clear of their relationships.

    I don’t really think that using the file system is a long-time solution to the access control since it stops domain- and -project-level admins from making their own policies because they may not be able to get access to the policy.jsons hosted by cloud providers.

    But I still think there are some benefits by using policy.json, first it’s handy to have a overall look at the commands and rules, second in a situation where policy.jsons are not constantly changing, we are actually dealing with memory which is faster than backends.

    So I wonder since there are named rules referenced by “rule:AlreadyNamedRule”, we may interact several times with the backend for protecting one command, how to mitigate this overhead?

    Anyway, I will keep close watch on your future post 🙂 .

  4. We should not be interacting with the backend on a per command basis. Instead, I see the policy.json file as something generated by the Keystone server, fetched by the service endpoint, and cached. Much like certs and revocation lists are cached in the PKIZ token format. I think that we will need a generic caching mechanism for this type of data, and we’ll make the bets effort to hold it in Memory on the server side, falling back to the file system, then falling back to refetching from Keystone.

  5. I read most of your design plans about this topic, you do have a great LOGIC!

    But, by saying “Move the keystone policy enforcement to keystone client”, do you mean using ksc to call oslo.policy instead of what is now protected by @controller.protected() in controllers of Keystone?

    Honestly, if it is, it seems radical to me: ksc are installed by end users and the cloud provider shouldn’t trust the policy engines deployed by end users.

    Please Correct me if I misunderstand your opinion.
    🙂

  6. Keystone client is the common library. I just want the logic in Keystone client, so remote servers can check, and call into the policy function. Its more akin to middleware than client work.

Leave a Reply

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