[openstack-dev] [keystone] Inherited domain roles

Tiwari, Arvind arvind.tiwari at hp.com
Thu Jun 6 22:02:33 UTC 2013


Hi Henry,



I am totally agree with David Chadwick that roleDefs itself should have enough info so that underline system (role assignment) can make some decision whether roleDef is inheritable or not. Below is my proposal which is extensible and pretty much aligned with David's thoughts.



I want to introduce wild card character (may be *) to handle inheritance behavior.






Type


          RoleDef structure


Description


Role Assignment examples


1.


Inheritable non-project roleDef




{

  "id": "1111",

  "links": {1111},

  "name": "domain-admin",

  "domainId": "*",

  "projectId": ""

}




domainId=* which means this roleDef is inheritable to any domain.



projectId="" means it is not a project specific roleDef and cannot be used for role assignment where project is involved.



E.g. domain-admin or domain-user


1. An inherited role assignment for a cloud provider's user (basically a cloudadmin) wd look as below and says "cloud-admin-userId has domain-admin role in all the domains"



{

   "roleId": "1111",

   "domainId": "*", <<< Inherited by all domains

   "subjectId": "cloud-admin-userId from cloud providers domains" << it can be a groupId

}



2. Below is an example of non-inheritance role assignment, which says "userId from domain XXXX has role domain-admin in domain xxxx"

{

   "roleId": "1111",

   "domainId": "XXXX", <<< (Concrete domain binding)

   "subjectId": "userId from XXXX domain" << it can be a groupId

}



3. This approach can be extensible to cross domain role assignments.

"user from YYYY domain has domain-admin role in domain XXXX"



{

   "roleId": "1111",

   "domainId": "XXXX",

   "subjectId": "userId from YYYY domain" << it can be a groupId

}




2.


Non-inheritable non-project role




{

   "id": "2222",

   "links": {2222},

   "name": "XXXX-domain-admin",

   "domainId": "XXXX",

   "projectId": ""

}






In case of public cloud environment we have to provide APIs to customer so that they can define *IAM* roles and this is to support that use case.



This roleDef is bind to "domainId": "XXXX" which means this roleDef should be used for role assignment in XXXX domain.



projectId="" means it is not a project specific roleDef and cannot be used for role assignment where project is involved.





Note: this may be not a use case of private cloud




1.  Non- Cross domain role assignments

{

   "roleId": "2222",

   "domainId": "XXXX", <<<< (* or YYYY is not possible)

   "subjectId": "userId from XXXX domain" << it can be a groupId

}



2. Cross domain role assignments are even possible

{

   "roleId": "2222",

   "domainId": "XXXX", <<<< (* or YYYY is not possible)

   "subjectId": "userId from YYYY domain" << it can be a groupId

}






3.


Inheritable project roleDef


{

  "id": "3333",

  "links": {3333},

  "name": "nova-net-admin",

  "domainId": "*",

  "projectId": "*"

}




"domainId": "*" and  "projectId": "*" means this roleDef can be used for inherited role assignment but with a context of (1 or *) projects.



All the Open Stack service role can fall under this category e.g. Nova-admin, swift-admin etc...


1.  Cloud provider want to maintain "nova-net-admin" on all customer domains and on all projects. (Roles inherited by all projects in all domains)

{

   "roleId": "3333",

   "domainId": "*",

   "projectId": "*", <<< (projectId cannot be concrete if domain is *)

   "subjectId": "cloud-admin-userId" << it can be a groupId

}



2.  Below is the example of inheritance with in a domain, which says "userId from XXXX domain has nova-net-admin role on all the projects"

{

   "roleId": "3333",

   "domainId": "XXXX",

   "projectId": "*",

   "subjectId": "userId from XXXX domain" << it can be a groupId

}



3    Below is an example of concrete project binding with in a domain, which says "userId from XXXX domain has nova-net-admin role on Proj1 projects in domain XXXX"

{

   "roleId": "3333",

   "domainId": "XXXX",

   "projectId": "Proj1",

   "subjectId": "userId from XXXX domain" << it can be a groupId

}





Note: this can be extensible  for cross domain role assignment























If we follow this approach to address inheritance which is extensible and give least impact on the existing APIs and to the role data structure. Only thing we need is proper use of wild card to represent domain or project.






API usage





1


PUT /domains/*/users/user_id/roles/role_id

PUT /domains/{domain_id}/users/user_id/roles/role_id





2


GET /domains/*/users/{user_id}/roles

GET /domains/{domain_id}/users/{user_id}/roles


By default this will list all the role (inherited and bound to domain) for user_id.

We can add filter to list just inherited one.















3


PUT /projects/*/users/{user_id}/roles/{role_id}

PUT /projects/{proj_id}/users/{user_id}/roles/{role_id}





4


GET /projects/*/users/{user_id}/roles

GET /projects/{proj_id}/users/{user_id}/roles


By default this will list all the role (inherited and bound to specific project)  for user_id.

We can add filter to list just inherited one.




Note: Did not mentioned the group apis but that goes along with users.





Thought???





Thanks,

Arvind



-----Original Message-----
From: David Chadwick [mailto:d.w.chadwick at kent.ac.uk]
Sent: Thursday, June 06, 2013 4:49 AM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [keystone] Inherited domain roles



Hi Henry



My take on this is that whether a role is automatically inheritable or

not should be an attribute of the role itself, and should be independent

of who the role is assigned to. Therefore when the role is initially

defined, it should be stated by the Keystone admin whether it is an

inherited role or not.



Role assignment is a separate issue and should not be confused with the

basic definition of the role. Role assignment should simply be a matter

of naming the subject (domain, project or user) and the role. If you

dont want the role to be inherited then use a non-inheritable role.



The problem with all the APIs below is that they conflate role

definition and role assignment together in the same API call. There

should be no need to have user_ids in the definition of a role.

Similarly there should be no mention of inherited in the assignment of a

role to a user.



regards



David





On 05/06/2013 15:31, Henry Nash wrote:

> Hi

>

> As per the discussion during the keystone IRC meeting yesterday, I have been reviewing the proposals for this functionality.  There have been two objections to the current proposal (which can be found here: https://review.openstack.org/#/c/29781/10), which are:

>

> 1) The api changes should allow for a logical, generic future extension for support of inherited roles across all domains etc., should we chose to go that route

> 2) The use of a single api to list the various grants, filtered by a query string if necessary.

>

> My proposal for handling these two objections is as follows:

>

> 1) API extensions.

>

> There are several aspects of inherited roles that we are trying to cement, which are:

>

> a) The are dynamic - i.e. this isn't a case of a short hand for saying add this role to all the current projects in the domain - rather it is a role assignment that is attached to the domain but is added to the effective roles of any project (now and in the future) that exists in this domain

> b) The are separate from a role that is on the domain itself - i.e.  we need to ensure that we keep separate inherited and non-inherited roles.

> c) Maintain the philosophy that If you can create a role assignment with a given API, there should be an equivalent to read it back and delete it (i.e. you mustn't have the case where, for instance you can list a grant, but can't delete it at the conceptual level)

>

> The current proposal had been to do this by adding an "inherited" component of the url for create, check and delete grants to a domain, e.g.

>

> PUT /domains/{domain_id}/users/{user_id}/roles/{role_id}

> PUT /domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited

> GET /domains/{domain_id}/users/{user_id}/roles/{role_id}

> GET /domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited

> DELETE /domains/{domain_id}/users/{user_id}/roles/{role_id}

> DELETE /domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited

> etc.

>

> A counter proposal has been made to expand this, along this lines of:

>

> Role applicable to all projects within a domain

> PUT /domains/{domain_id}/users/{user_id}/roles/{role_id}/projects

>

> Roles inherited by all projects in all domains

> PUT /usrs/{user_id}/roles/{role_id}/projects

>

> Roles inherited by all domains, at the domain level

> PUT /usrs/{user_id}/roles/{role_id}/domains

>

> While I understand the desire to have extensibility if we wish to provide more "global-ness" of roles, I think the above proposal is less clear about whether these assignments are dynamic (see item a) above).  How about this as a counter proposal:

>

> Role applicable inherited by all projects within a domain (this is the same as the current proposal)

> PUT  /domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited

>

> Roles inherited by all projects in all domains - if we were to ever support this (not part of the current proposal)

> PUT  /domains/users/{user_id}/roles/{role_id}/inherited

>

> Roles inherited by all domains, at the domain level - if we were to ever support this (not part of the current proposal)

> PUT  /domains/users/{user_id}/roles/{role_id}/inherited

>

> To go along with the above, you would have the respective GET, CHECK & DELETE versions of those apis.

>

> 2) Single vs multiple apis

> I think this comment is actually misplaced in the gerrit review, and is intended to directed at the api extensions I proposed to allow the list of a users "effective" roles on a project (i.e. directly assigned, those by virtue of group membership and inheritance from the parent domain).  For this, I proposed adding an optional "effective" query parameter to each of:

>

> List user's roles on project: `GET /projects/{project_id}/users/{user_id}/roles

> List group's roles on project: `GET /projects/{project_id}/groups/{group_id}/roles

> Check user's role on project: `GET /projects/{project_id}/users/{user_id}/role/{role_id}

> Check group's roles on project: `GET /projects/{project_id}/groups/{group_id}/role/{role_id}

>

> e.g. GET /projects/{project_id}/users/{user_id}/roles?effective

> ...would get you the effective roles the user has on that project, as opposed to only the directly assigned ones if you issue the call without the "effective" query parameter.

>

> Dolph and I had already been discussing that the existing v3 api of:

>

> GET /users/{user_id}/roles

>

> ...which is meant to return all the role assignments for a user, but is in fact broken in the current Grizzly code (it always returns an error).  So I agree with the proposal that we should scrap the "effective" query parameter for the specific list/check calls for the project - and instead properly implement the "get all assignments for a user" call.  I propose the amended spec for this call is:

>

> #### List a user's effective role assignments: `GET /users/{user_id}/role-assignments`

>

> query_string: page (optional)

> query_string: per_page (optional, default 30)

> query_string: id, project_id, domain_id

>

> Response:

>

>      Status: 200 OK

>

>      [

>          {

>              "id": "--role-id--",

>              "name": "--role-name--",

>              "project_id": "--project-id--",

>              "source":

>              {

>                  "direct": true,  (optional)

>                  "domain_inherited: "--domain-id--", (optional)

>                  "group_membership: "--group-id--" (optional)

>              }

>          },

>          {

>              "domain_id": "--domain-id--",

>              "id": "--role-id--",

>              "name": "--role-name--",

>              "source":

>              {

>                  "direct": true, (optional)

>                  "group_membership: "--group-id--" (optional)

>              }

>          }

>      ]

>

> The "source" structure must have at least one of the values given above (and could have more than one, e.g. both domain_inherited and global_membership for a project where the role is due to a group role that is inherited from the domain).  If were even to support global roles across all domains, then we would extend the "source structure" accordingly.   I'm open to other options for the above format. however, so comments welcome.

>

> Does this sounds like a reasonable plan overall?

>

> Henry

>

>

>

> _______________________________________________

> OpenStack-dev mailing list

> OpenStack-dev at lists.openstack.org

> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

>



_______________________________________________

OpenStack-dev mailing list

OpenStack-dev at lists.openstack.org

http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstack.org/pipermail/openstack-dev/attachments/20130606/26f58b63/attachment.html>


More information about the OpenStack-dev mailing list