Jump to: navigation, search

Domains

Revision as of 01:32, 20 July 2012 by Admiyo (talk)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Keystone Domains

The intent of domain is to define the administrative boundaries for management of Keystone entities. A domain can represent an individual, company, or operator owned space.

Problem Addressed

Keystone’s lack of administrative boundaries prohibits the possibility of safely exposing administrative activities directly to users of the system User Stories that currently are not possible:

   As a cloud user I want to be able to administer a set of users: 
       create users (aka sub-accounts) who can have access to my tenants/services 
       give users access to tenants in my domain.
       specify roles for users in my domain.
       create groups and place users into groups. 
             (ayoung) unclear if Groups should be separate from tenants
             (termie) This appears to be unrelated to the required work for domains and should be a separate feature. 
             (jrouault) Yes, it can be addressed seperately, but it is important to point out that groups are not equivelent to domains, but instead reside in domains.
   As a cloud user I want to be able to control the kind of access that users have to my tenants/services by specifying role assignments for groups. (termie) This appears to be unrelated to the required work for domains and should be a separate feature (with above). (gyee) Yes. Groups can be a separate feature.

(termie) Some comments: What appears to be being described is a way to define a user that is an admin for a variety of tenants, especially one where the boundaries between which tenants a user is admin for is very well defined. One thing of note here is that this feature was described before the flexibility and power of the internal policy engine was known and I think there is good reason to revisit the design in light of those features. Some examples:

  • Assuming the creation of a new Domain data object, rules could be described naively as:
  rule:add_user_to_tenant -> (role:keystone_admin
                              || (role:tenant_admin && tenant_id:%(target_tenant_id)s)
                              || (domain_role:domain_admin && domain_id:%(target_domain_id)s))
  Meaning that three people would have the rights to add a user to a tenant: (jrouault) i would rephrase this as three people have rights to give users 'access' to a tenant 
  • somebody who is an admin of the entire keystone service,
  • somebody who is the admin for that tenant, (gyee) that would be either the keystone admin or domain admin
  • somebody who is the admin for the domain that tenant is a member of.
  • Likewise for managing which tenants are part of a domain you'd have something like:
  rule:add_tenant_to_domain -> (role:keystone_admin
                                || (domain_role:domain_admin && domain_id:%(target_domain_id)s))

I see these rules, and Domain-aware rules like them as being most of the work required to assign permissions based on Domains. The rest of the work being adding Domain information to users and tenants. Questions: 1. If the only service that needs to know about domains is Keystone, why do we need to include domainID on serveral of the GET calls? Those calls are related to how a client/user interacts with the Keystone management system. If the client is a UI (e.g. Dashboard) it will want to know about domains in order to manage them. 2. Will users of different domains be allowed within the same group? No. Groups, as defined here, are bound to a domain. Only users of that domain can be a members of the groups defined in that domain (termie): I'd like to move the group concept out of this blueprint (gyee): no objection here 3. Are domains required? If so, what level (can a user be created without a domain id)? Well, I guess if an operator did not want to deal with domains, then just one domain would be created and all users would reside in that domain. 4. What is a real-world example of a company using domains? It is all about multi-tenancy. With domains, a cloud customer can be the owner of the domain. They can then create additional users in their domain. Create groups and assign the users to those groups. Create roles, or leverage global roles, and then create role assignments for users to their tenants.. etc. etc... 5. Can a tenant belong to more than one domain? No. But a domain can have more than one tenant. A user from one domain can be assigned a role association to a tenant in another domain (termie): So tenants are per-domain but users are global and can be part of tenants from other domains? This wouldn't allow "creating users in your domain" but it would allow you to add a created user to a tenant under your domain or give it roles within your domain. Most current projects will still require that their names be globally unique. (gyee) users are per domain as well. Cross domain role assignment is allow. (jrouault) termie, we need to be clear with terminology here. One does not "add a created user to a tenant". Rather, one would grant a user access to a tenant via role assignment. That user may exist in the same domain as the tenant, or a different domain entirely. 6. What do you see as the difference between the Admin roleRef and the Domain-Admin roleRef? Is the Admin roleRef assigned to services (nova) only, while Domain-Admin roleRef is assigned to actual cloud users? Domain Admin role assignment would give a user the ability to manage all the Domain entities (users, groups, role assignments, etc.). The Admin role assignment is service specific (e.g. Nova, Glance) (termie): roleRefs as defined before no longer exist, but it does seem likely that domains will have a separate repository of roles within their domain that are not the same as the roles that are passed to services (I used "domain_role" above in the examples to mark that). 7. How would you define trust relationships between domains? Is there a shared token? How can we prevent a rogue service from creating domains that include malicious endpoints? The only way a user from one domain A can get access to a tenant in another domain B is, is for the Domain B Admin to setup a role assignment to that effect. Authorization needs to be setup in Keystone (not there now) to control these CRUD operations. (termie): I think the examples above should cover this. 8. What should happen, with respect to domains, when a new service self-registers with Keystone? Ex: NewCompute starts up, securely identifes keystone, and attempts to make it's endpoint available within Keystone. Should it assume endpoint availability within all tenants (thereby all domains) or only the tenants that are connected via a defaulted domain? The service and its endpoints would be available for all domains... just like global role definitions are available for all domains. Some things live in global namespace, other things live in Domain namespac (termie): my understanding is that other services are likely domain-agnostic, only keystone will be using them as an administrative option, and horizon may provide some additional ui. (jrouault) that is correct, with services being global in nature they are domain agnostic 9. Should token expiration be allowed to vary domain by domain? That certainly would be a nice feature to have. Although, I don't think it is something required for Essex (termie): I'd say no, not worth our time. (gyee) +1 10. Why cant we have Groups to be part of tenant and allow all the functions mentioned here. Tenants, as currently defined by Keystone (good or bad) is just a collection of services/resources. I would keep groups at the Domain level at equal pairing with users and tenants. This allows you to leverage groups and role assignments across tenants within a domain. Would this not satisfy the needs? ie Group Operations: POST /groups Create a group in a Tenant DELETE /groups Delete a group from a Tenant GET /groups/{groupId} Get a group PUT /groups/{groupId} Update a group GET /groups/{groupId}/users List users of a particular group PUT /groups/{groupId}/users/{userId} Add a user to a group DELETE /groups/{groupId}/users/{userId} Remove a user from a group PUT /groups/{groupId}/roles/{roleId} Assigns a role to a group DELETE /groups/{groupId}/roles/{roleId} Removes a roles from a group 11. Can we split out the groups into a separate extension (OS-KSGRP for example)? This will allow for phased development, and more customizeable installs. The Domains extension would have a dependency on the group extension. Certainly. I personally feel the entire admin API should be a OS-KS extension, as it really is only a reference implementation. What is really important about keystonse is the service APIs and the middle-ware that integrates with the rest of OS. (termie): again, I don't think groups are even needed for domains. (gyee) groups are not a must have for domains, but a nice to have. Benefits

   True administrative boundaries and isolation
   Management put into the hands of the resource owners
   Better line of sight of control
   Users are responsible for their own changes and the ramifications
   Ease of management
   Custom groups to fit business needs
   Role assignments to groups to reduce administrative effort
   Opens the door for new types of roles
   Self Service, Password Management
   Custom Roles

Problems:

  • For things like billing, everything up the stack will need to be aware of domains, since in most cases the cardholder for the account would be a domain admin, not a tenant admin.
(jrouault) Actually, I do not see this a problem, but as a benefit.  Having the domain be a top level billable entity allows for multiple user accounts and tenant usage to roll-up to a single bill if that is desired by the cloud operator

Keystone Admin API additions Domain Operations:

   GET /domains                                    Get a list of all domains
   GET /domains/{domainId}                         Get a specific domain
   POST /domains                                   Create a domain
   PUT /domains/{domainId}                         Update a domain
   DELETE /domains/{domainId}                      Delete a domain
   GET /domains/{domainId}/users                   Get a domain's users
   GET /domains/{domainId}/tenants                 Get a domain's tenants
   GET /domains/{domainId}/roles                   Get a domain's roles
   GET /domains/{domainId}/groups                  Get a domain's groups
   (termie) drop groups? (gyee) we can do groups in another blueprint

(termie): drop this section? (gyee) yes if we are not going to do groups in this BP Group Operations:

   POST /groups                                                Create a group in a domain
   DELETE /groups                                            Delete a group from a domain
   GET /groups/{groupId}                                    Get a group
   PUT /groups/{groupId}                                    Update a group
   GET /groups/{groupId}/users                            List users of a particular group
   PUT /groups/{groupId}/users/{userId}                Add a user to a group
   DELETE /groups/{groupId}/users/{userId}         Remove a user from a group
   PUT /groups/{groupId}/roles/{roleId}                  Assigns a role to a group
   DELETE /groups/{groupId}/roles/{roleId}           Removes a roles from a group

(termie): this one too (gyee) yep Tenant Operations

   PUT /tenants/{tenantId}/groups/{groupId}/roles/{roleId}       Assigns tenant role to a group
   DELETE /tenants/{tenantId}/groups/{groupId}/roles/{roleId}  Removes a tenant role from a group

Keystone Admin API changes User Operations

   GET /users                                  Response will change to include domainId for each user
   POST /users                                 Request will change to include a domainId
   POST /users/{userId}                        Response will change to include the domainId
   GET /users/{userId}/roles                   Response to include domainId for each role
   GET /users/{userId}/roles/OS-KADM/{roleId}  Response will change to include domainId

(termie): I'd not include the domain_id in the roles, and instead have a domain_roles call or the equivalent, the roles are checked separately and domain roles don't get returned to services. Additionally, users only have roles within tenants or within domains, so these last two calls are not needed / supported. (jrouault) there are no role 'within' a tenant. There are roles that can be used to associate a user to a tenant (these are typically globally defined roles), and then there might be custom roles defined within in a domain that can be used for a similar purpose. Tentatively something closer to the following could work:

  • GET /users/{user_id}/domain/{domain_id}/domain_roles

(gyee) I am not sure if I unstanding your suggestion as all IDs (userId, roleId, etc) are globally unique. Why do we need to specify the domainId? (jrouault) I would argue that user resource would hang off of the domain, and not the other way around as you show it. Tenant Operations

   GET /tenants                              Response will change to include domainId
   POST /tenants                             Request will change to include the domainId
   GET /tenants/{tenantId}/users             Response will change to include the domainId for each user
   GET /tenants/{tenantId}/OS-KSADM/roles    Response will change to include the domainId for each role
   (termie): tenants don't have roles on their own, so this can be dropped (gyee) isn't tenant roles a fundamental concept in Keystone? Not sure if I understand your suggestion here.
   (jrouault) This call is listing the role associations that have been setup for the given tenant
   GET /tenants/{tenantId}/users/{userId}/roles    Response will change to include domainId
   (termie): as mentioned above, user-domain roles are not the same as user-tenant roles so this call would not return user-domain roles. (gyee) tenants and users are always part of a domain.
   (jrouault) this call is listing the role associations that have been setup for the given user on the specified tenant

Role Operations

   GET /OS-KSADM/roles                 Response will change to include domainId
   POST /OS-KSADM/roles                Request will change to include domainId
   GET /OS-KSADM/roles/{roleId}        Response will change to include domainId

(termie): in general none of these will need be touched as the domain-roles can be separate from these (gyee) again, roles will be part of a domain. Global roles are part of all domains. Compatibility Can we add to the spec how we will make this compatible with existing services running on the 2.0 API? Will this have any impact on other services? Will they need to store/manage/interact with domains, for example when storing tenant_id for project_id in Nova will Nova額 need to also store domain? Ideally current Keystone deployers and service developers can opt-in to this functionality and Keystone will use something like a default domain to abstract the concept from them There should be no impact to the Services API or Middle-ware. Those will remain the same. The only service that will need to know about domains is Keystone.


Looking at the discussion above it appears there is some confusion about roles and how they work in the domain. Let me try to expand on my thoughts here: Role Definitions basically creates a named role within the system that can then be assigned to one or more users. A Role Assignment maps subject (user/group) to a role, apart from role mapping it is also used to map subject (user/group) to a tenant. Role Definition Role definitions are available for use across all domains (global) or for a single domain. For example, Nova may may define a global role 'sysadmin' Alternatively, a domain administrator may create a custom role named 'FooBarAdmin' for use only within her domain. Role definitions are handled by Role Operations in the example API shown below. If the role object includes a domainId, then it means the definition is scoped to a specific domain

   POST   [KeystoneaseURI]/roles                Create a role definition
   PUT    [KeystoneBaseURI]/roles/\{roleId\}    Update a role definition 
   GET    [KeystoneBaseURI]/roles?serviceId     List role definitions.  
   GET    [KeystoneBaseURI]/roles/\{roleId\}    Get role definition
   DELETE [KeystoneBaseURI]/roles/\{roleId\}    Delete a role definition 

Role Assignments Role assignments can come in two flavors: Tenant-User and User-Only role assignment. A user-only role assignment links a user to a role. A tenant-user role assignment links a user to a role and to a tenant. (heckj): The User-Only role assignment doesn't make sense to me, especially as we're removing any sense of "global" roles. In it's place, I think a domain<->user role would be sensible, and I believe achieves what you're after. The way I'm thinking of that is a domain role is a association between a user and domain with a given Role name. Example tenant role assignment: “Bob” has the “nova-admin” role for tenant “tenant01” Example user role assignement: "Alice" has the "domainAdmin" role for domain XYZ. Or, "Jake" has the "keystoneAdmin" role User-only role Assignments are handled by User operations as demonstrated in the sample API below

   GET    [KeystoneBaseURI]/users/\{userId\}roles?serviceId 

List a users role assignments

   PUT    [KeystoneBaseURI]/users/\{userId\}/roles/\{roleId\} 

Create a user's role assignment

   DELETE [KeystoneBaseURI]/users/\{userId\}/roles/\{roleId\} 

Delete a usres's global role assignment Tenant-User role Assignments are handled by Tenant operations as demonstrated in the sample API below

   GET    [KeystoneBaseURI]/tenants/\{tenantId\}/roles?serviceId List tenant role assignment 
   GET    [KeystoneBaseURI]/tenants/\{tenantId\}/users/\{userId\}/roles?serviceId  List tenant role assignment for a user
   PUT    [KeystoneBaseURI]/tenants/\{tenantId\}/users/\{userId\}/roles/\{roleId\} Create tenant role assignment for a user
   DELETE  [KeystoneBaseURI]/tenants/\{tenantId\}/users/\{userId\}/roles/\{roleId\}  Delete tenant role assignment for a user