diff --git a/keystone/api/__init__.py b/keystone/api/__init__.py index 351d914dad..b340fae754 100644 --- a/keystone/api/__init__.py +++ b/keystone/api/__init__.py @@ -24,6 +24,7 @@ from keystone.api import role_assignments from keystone.api import role_inferences from keystone.api import roles from keystone.api import services +from keystone.api import system from keystone.api import trusts __all__ = ( @@ -41,6 +42,7 @@ __all__ = ( 'role_inferences', 'roles', 'services', + 'system', 'trusts', ) @@ -59,5 +61,6 @@ __apis__ = ( role_inferences, roles, services, + system, trusts, ) diff --git a/keystone/api/system.py b/keystone/api/system.py new file mode 100644 index 0000000000..d04086991a --- /dev/null +++ b/keystone/api/system.py @@ -0,0 +1,184 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +# This file handles all flask-restful resources for /v3/system + +import flask +import flask_restful +from six.moves import http_client + +from keystone.common import json_home +from keystone.common import provider_api +from keystone.common import rbac_enforcer +from keystone import exception +from keystone.server import flask as ks_flask + + +ENFORCER = rbac_enforcer.RBACEnforcer +PROVIDERS = provider_api.ProviderAPIs + + +def _build_enforcement_target(allow_non_existing=False): + target = {} + if flask.request.view_args: + if flask.request.view_args.get('role_id'): + target['role'] = PROVIDERS.role_api.get_role( + flask.request.view_args['role_id']) + if flask.request.view_args.get('user_id'): + try: + target['user'] = PROVIDERS.identity_api.get_user( + flask.request.view_args['user_id']) + except exception.UserNotFound: + if not allow_non_existing: + raise + else: + try: + target['group'] = PROVIDERS.identity_api.get_group( + flask.request.view_args.get('group_id')) + except exception.GroupNotFound: + if not allow_non_existing: + raise + return target + + +class SystemUsersListResource(flask_restful.Resource): + def get(self, user_id): + """List all system grants for a specific user. + + GET/HEAD /system/users/{user_id}/roles + """ + ENFORCER.enforce_call(action='identity:list_system_grants_for_user', + target_attr=_build_enforcement_target()) + refs = PROVIDERS.assignment_api.list_system_grants_for_user(user_id) + return ks_flask.ResourceBase.wrap_collection( + refs, collection_name='roles') + + +class SystemUsersResource(flask_restful.Resource): + def get(self, user_id, role_id): + """Check if a user has a specific role on the system. + + GET/HEAD /system/users/{user_id}/roles/{role_id} + """ + ENFORCER.enforce_call(action='identity:check_system_grant_for_user', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.check_system_grant_for_user(user_id, role_id) + return None, http_client.NO_CONTENT + + def put(self, user_id, role_id): + """Grant a role to a user on the system. + + PUT /system/users/{user_id}/roles/{role_id} + """ + ENFORCER.enforce_call(action='identity:create_system_grant_for_user', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.create_system_grant_for_user(user_id, role_id) + return None, http_client.NO_CONTENT + + def delete(self, user_id, role_id): + """Revoke a role from user on the system. + + DELETE /system/users/{user_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:revoke_system_grant_for_user', + target_attr=_build_enforcement_target(allow_non_existing=True)) + PROVIDERS.assignment_api.delete_system_grant_for_user(user_id, role_id) + return None, http_client.NO_CONTENT + + +class SystemGroupsRolesListResource(flask_restful.Resource): + def get(self, group_id): + """List all system grants for a specific group. + + GET/HEAD /system/groups/{group_id}/roles + """ + ENFORCER.enforce_call(action='identity:list_system_grants_for_group', + target_attr=_build_enforcement_target()) + refs = PROVIDERS.assignment_api.list_system_grants_for_group(group_id) + return ks_flask.ResourceBase.wrap_collection( + refs, collection_name='roles') + + +class SystemGroupsRolestResource(flask_restful.Resource): + def get(self, group_id, role_id): + """Check if a group has a specific role on the system. + + GET/HEAD /system/groups/{group_id}/roles/{role_id} + """ + ENFORCER.enforce_call(action='identity:check_system_grant_for_group', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.check_system_grant_for_group( + group_id, role_id) + return None, http_client.NO_CONTENT + + def put(self, group_id, role_id): + """Grant a role to a group on the system. + + PUT /system/groups/{group_id}/roles/{role_id} + """ + ENFORCER.enforce_call(action='identity:create_system_grant_for_group', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.create_system_grant_for_group( + group_id, role_id) + return None, http_client.NO_CONTENT + + def delete(self, group_id, role_id): + """Revoke a role from the group on the system. + + DELETE /system/groups/{group_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:revoke_system_grant_for_group', + target_attr=_build_enforcement_target(allow_non_existing=True)) + PROVIDERS.assignment_api.delete_system_grant_for_group( + group_id, role_id) + return None, http_client.NO_CONTENT + + +class SystemAPI(ks_flask.APIBase): + _name = 'system' + _import_name = __name__ + resources = [] + resource_mapping = [ + ks_flask.construct_resource_map( + resource=SystemUsersListResource, + url='/system/users//roles', + resource_kwargs={}, + rel='system_user_roles', + path_vars={'user_id': json_home.Parameters.USER_ID}), + ks_flask.construct_resource_map( + resource=SystemUsersResource, + url='/system/users//roles/', + resource_kwargs={}, + rel='system_user_role', + path_vars={ + 'role_id': json_home.Parameters.ROLE_ID, + 'user_id': json_home.Parameters.USER_ID}), + ks_flask.construct_resource_map( + resource=SystemGroupsRolesListResource, + url='/system/groups//roles', + resource_kwargs={}, + rel='system_group_roles', + path_vars={'group_id': json_home.Parameters.GROUP_ID}), + ks_flask.construct_resource_map( + resource=SystemGroupsRolestResource, + url='/system/groups//roles/', + resource_kwargs={}, + rel='system_group_role', + path_vars={ + 'role_id': json_home.Parameters.ROLE_ID, + 'group_id': json_home.Parameters.GROUP_ID}) + ] + + +APIs = (SystemAPI,) diff --git a/keystone/assignment/controllers.py b/keystone/assignment/controllers.py index d46fd8544a..8ff0f13b26 100644 --- a/keystone/assignment/controllers.py +++ b/keystone/assignment/controllers.py @@ -172,100 +172,3 @@ class GrantAssignmentV3(controller.V3Controller): role_id, user_id=user_id, group_id=group_id, domain_id=domain_id, project_id=project_id, inherited_to_projects=inherited_to_projects, context=request.context_dict) - - @controller.protected(callback=_check_grant_protection) - def list_system_grants_for_user(self, request, user_id): - """List all system grants for a specific user. - - :param request: the request object - :param user_id: ID of the user - :returns: a list of grants the user has on the system - - """ - refs = PROVIDERS.assignment_api.list_system_grants_for_user(user_id) - return GrantAssignmentV3.wrap_collection(request.context_dict, refs) - - @controller.protected(callback=_check_grant_protection) - def check_system_grant_for_user(self, request, role_id, user_id): - """Check if a user has a specific role on the system. - - :param request: the request object - :param role_id: the ID of the role to check - :param user_id: the ID of the user to check - - """ - PROVIDERS.assignment_api.check_system_grant_for_user(user_id, role_id) - - @controller.protected(callback=_check_grant_protection) - def create_system_grant_for_user(self, request, role_id, user_id): - """Grant a role to a user on the system. - - :param request: the request object - :param role_id: the ID of the role to grant to the user - :param user_id: the ID of the user - - """ - PROVIDERS.assignment_api.create_system_grant_for_user(user_id, role_id) - - @controller.protected(callback=functools.partial( - _check_grant_protection, allow_non_existing=True)) - def revoke_system_grant_for_user(self, request, role_id, user_id): - """Revoke a role from user on the system. - - :param request: the request object - :param role_id: the ID of the role to remove - :param user_id: the ID of the user - - """ - PROVIDERS.assignment_api.delete_system_grant_for_user(user_id, role_id) - - @controller.protected(callback=_check_grant_protection) - def list_system_grants_for_group(self, request, group_id): - """List all system grants for a specific group. - - :param request: the request object - :param group_id: ID of the group - :returns: a list of grants the group has on the system - - """ - refs = PROVIDERS.assignment_api.list_system_grants_for_group(group_id) - return GrantAssignmentV3.wrap_collection(request.context_dict, refs) - - @controller.protected(callback=_check_grant_protection) - def check_system_grant_for_group(self, request, role_id, group_id): - """Check if a group has a specific role on the system. - - :param request: the request object - :param role_id: the ID of the role to check - :param group_id: the ID of the group to check - - """ - PROVIDERS.assignment_api.check_system_grant_for_group( - group_id, role_id - ) - - @controller.protected(callback=_check_grant_protection) - def create_system_grant_for_group(self, request, role_id, group_id): - """Grant a role to a group on the system. - - :param request: the request object - :param role_id: the ID of the role to grant to the group - :param group_id: the ID of the group - - """ - PROVIDERS.assignment_api.create_system_grant_for_group( - group_id, role_id - ) - - @controller.protected(callback=functools.partial(_check_grant_protection)) - def revoke_system_grant_for_group(self, request, role_id, group_id): - """Revoke a role from the group on the system. - - :param request: the request object - :param role_id: the ID of the role to remove - :param user_id: the ID of the user - - """ - PROVIDERS.assignment_api.delete_system_grant_for_group( - group_id, role_id - ) diff --git a/keystone/assignment/routers.py b/keystone/assignment/routers.py index ee021ddfb6..2a4a694b2c 100644 --- a/keystone/assignment/routers.py +++ b/keystone/assignment/routers.py @@ -38,7 +38,7 @@ class Public(wsgi.ComposableRouter): class Routers(wsgi.RoutersBase): - _path_prefixes = ('users', 'projects', 'domains', 'system', 'OS-INHERIT') + _path_prefixes = ('users', 'projects', 'domains', 'OS-INHERIT') def append_v3_routers(self, mapper, routers): @@ -137,45 +137,6 @@ class Routers(wsgi.RoutersBase): 'domain_id': json_home.Parameters.DOMAIN_ID, 'group_id': json_home.Parameters.GROUP_ID, }) - self._add_resource( - mapper, grant_controller, - path='/system/users/{user_id}/roles', - get_head_action='list_system_grants_for_user', - rel=json_home.build_v3_resource_relation('system_user_roles'), - path_vars={ - 'user_id': json_home.Parameters.USER_ID - }) - self._add_resource( - mapper, grant_controller, - path='/system/users/{user_id}/roles/{role_id}', - get_head_action='check_system_grant_for_user', - put_action='create_system_grant_for_user', - delete_action='revoke_system_grant_for_user', - rel=json_home.build_v3_resource_relation('system_user_role'), - path_vars={ - 'role_id': json_home.Parameters.ROLE_ID, - 'user_id': json_home.Parameters.USER_ID - }) - self._add_resource( - mapper, grant_controller, - path='/system/groups/{group_id}/roles', - get_head_action='list_system_grants_for_group', - rel=json_home.build_v3_resource_relation('system_group_roles'), - path_vars={ - 'group_id': json_home.Parameters.GROUP_ID - }) - self._add_resource( - mapper, grant_controller, - path='/system/groups/{group_id}/roles/{role_id}', - get_head_action='check_system_grant_for_group', - put_action='create_system_grant_for_group', - delete_action='revoke_system_grant_for_group', - rel=json_home.build_v3_resource_relation('system_group_role'), - path_vars={ - 'role_id': json_home.Parameters.ROLE_ID, - 'group_id': json_home.Parameters.GROUP_ID - }) - self._add_resource( mapper, grant_controller, path='/OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/' diff --git a/keystone/server/flask/application.py b/keystone/server/flask/application.py index e0b63a2233..754a2d80c2 100644 --- a/keystone/server/flask/application.py +++ b/keystone/server/flask/application.py @@ -54,6 +54,7 @@ _MOVED_API_PREFIXES = frozenset( 'role_inferences', 'roles', 'services', + 'system', ] )