From 296f20f0a7e26784b6414ddbe12e0218087a9f51 Mon Sep 17 00:00:00 2001 From: Gage Hugo Date: Tue, 28 Aug 2018 20:35:50 -0500 Subject: [PATCH] Convert domains api to flask Convert domains api to flask native dispatching. Change-Id: I974ab112986e6c242a139f7d7dc14fd54a48ee42 Partial-Bug: #1776504 --- keystone/api/__init__.py | 3 + keystone/api/domains.py | 556 +++++++++++++++++++++++++++ keystone/assignment/core.py | 6 +- keystone/assignment/routers.py | 44 +-- keystone/notifications.py | 9 +- keystone/resource/controllers.py | 112 ------ keystone/resource/routers.py | 76 +--- keystone/server/flask/application.py | 1 + 8 files changed, 574 insertions(+), 233 deletions(-) create mode 100644 keystone/api/domains.py diff --git a/keystone/api/__init__.py b/keystone/api/__init__.py index 4fbf4e95ce..046f098cb6 100644 --- a/keystone/api/__init__.py +++ b/keystone/api/__init__.py @@ -12,6 +12,7 @@ from keystone.api import credentials from keystone.api import discovery +from keystone.api import domains from keystone.api import endpoints from keystone.api import groups from keystone.api import limits @@ -34,6 +35,7 @@ from keystone.api import trusts __all__ = ( 'discovery', 'credentials', + 'domains', 'endpoints', 'groups', 'limits', @@ -57,6 +59,7 @@ __all__ = ( __apis__ = ( discovery, credentials, + domains, endpoints, groups, limits, diff --git a/keystone/api/domains.py b/keystone/api/domains.py new file mode 100644 index 0000000000..6d7a1580fd --- /dev/null +++ b/keystone/api/domains.py @@ -0,0 +1,556 @@ +# 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/domains + +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.common import validation +import keystone.conf +from keystone import exception +from keystone.resource import schema +from keystone.server import flask as ks_flask + +CONF = keystone.conf.CONF +ENFORCER = rbac_enforcer.RBACEnforcer +PROVIDERS = provider_api.ProviderAPIs + + +def _build_enforcement_target(allow_non_existing=False): + target = {} + if flask.request.view_args: + domain_id = flask.request.view_args.get('domain_id', None) + if domain_id: + target['domain'] = PROVIDERS.resource_api.get_domain(domain_id) + + role_id = flask.request.view_args.get('role_id', None) + if role_id: + target['role'] = PROVIDERS.role_api.get_role(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 DomainResource(ks_flask.ResourceBase): + collection_key = 'domains' + member_key = 'domain' + get_member_from_driver = PROVIDERS.deferred_provider_lookup( + api='resource_api', method='get_domain') + + def get(self, domain_id=None): + """Get domain or list domains. + + GET/HEAD /v3/domains + GET/HEAD /v3/domains/{domain_id} + """ + if domain_id is not None: + return self._get_domain(domain_id) + return self._list_domains() + + def _get_domain(self, domain_id): + ENFORCER.enforce_call(action='identity:get_domain') + return self.wrap_member(PROVIDERS.resource_api.get_domain(domain_id)) + + def _list_domains(self): + filters = ['name', 'enabled'] + ENFORCER.enforce_call(action='identity:list_domains', + filters=filters) + hints = self.build_driver_hints(filters) + refs = PROVIDERS.resource_api.list_domains(hints=hints) + return self.wrap_collection(refs, hints=hints) + + def post(self): + """Create domain. + + POST /v3/domains + """ + ENFORCER.enforce_call(action='identity:create_domain') + domain = self.request_body_json.get('domain', {}) + validation.lazy_validate(schema.domain_create, domain) + domain = self._assign_unique_id(domain) + domain = self._normalize_dict(domain) + ref = PROVIDERS.resource_api.create_domain( + domain['id'], domain, initiator=self.audit_initiator) + return self.wrap_member(ref), http_client.CREATED + + def patch(self, domain_id): + """Update domain. + + PATCH /v3/domains/{domain_id} + """ + ENFORCER.enforce_call(action='identity:update_domain') + domain = self.request_body_json.get('domain', {}) + validation.lazy_validate(schema.domain_update, domain) + PROVIDERS.resource_api.get_domain(domain_id) + ref = PROVIDERS.resource_api.update_domain( + domain_id, domain, initiator=self.audit_initiator) + return self.wrap_member(ref) + + def delete(self, domain_id): + """Delete domain. + + DELETE /v3/domains/{domain_id} + """ + ENFORCER.enforce_call(action='identity:delete_domain') + PROVIDERS.resource_api.delete_domain( + domain_id, initiator=self.audit_initiator) + return None, http_client.NO_CONTENT + + +class DomainConfigResource(ks_flask.ResourceBase): + member_key = 'config' + collection_key = 'config' + + def get(self, domain_id=None): + """Get domain config. + + GET/HEAD /v3/domains/{domain_id}/config + """ + ENFORCER.enforce_call(action='identity:get_domain_config') + config = PROVIDERS.domain_config_api.get_config(domain_id) + return {self.member_key: config} + + def put(self, domain_id): + """Create domain config. + + POST /v3/domains/{domain_id}/config + """ + ENFORCER.enforce_call(action='identity:create_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + config = self.request_body_json.get('config', {}) + original_config = ( + PROVIDERS.domain_config_api.get_config_with_sensitive_info( + domain_id + ) + ) + ref = PROVIDERS.domain_config_api.create_config(domain_id, config) + if original_config: + return {self.member_key: ref} + else: + return {self.member_key: ref}, http_client.CREATED + + def patch(self, domain_id=None): + """Update domain config. + + PATCH /v3/domains/{domain_id}/config + """ + ENFORCER.enforce_call(action='identity:update_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + config = self.request_body_json.get('config', {}) + ref = PROVIDERS.domain_config_api.update_config(domain_id, config) + return {self.member_key: ref} + + def delete(self, domain_id=None): + """Delete domain config. + + DELETE /v3/domains/{domain_id}/config + """ + ENFORCER.enforce_call(action='identity:delete_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + PROVIDERS.domain_config_api.delete_config(domain_id) + return None, http_client.NO_CONTENT + + +class DomainConfigGroupResource(ks_flask.ResourceBase): + member_key = 'config' + collection_key = 'config' + + def get(self, domain_id=None, group=None): + """Get domain config. + + GET/HEAD /v3/domains/{domain_id}/config/{group} + """ + err = None + config = {} + try: + PROVIDERS.resource_api.get_domain(domain_id) + except Exception as e: # nosec + # We don't raise out here, we raise out after enforcement, this + # ensures we do not leak domain existance. + err = e + finally: + if group and group == 'security_compliance': + config = self._get_security_compliance_config( + domain_id, group) + else: + config = self._get_config(domain_id, group) + if err is not None: + raise err + return {self.member_key: config} + + def _get_config(self, domain_id, group): + ENFORCER.enforce_call(action='identity:get_domain_config') + return PROVIDERS.domain_config_api.get_config(domain_id, group) + + def _get_security_compliance_config(self, domain_id, group): + ENFORCER.enforce_call( + action='identity:get_security_compliance_domain_config') + return PROVIDERS.domain_config_api.get_security_compliance_config( + domain_id, group) + + def patch(self, domain_id=None, group=None): + """Update domain config. + + PATCH /v3/domains/{domain_id}/config/{group} + """ + ENFORCER.enforce_call(action='identity:update_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + config = self.request_body_json.get('config', {}) + ref = PROVIDERS.domain_config_api.update_config( + domain_id, config, group) + return {self.member_key: ref} + + def delete(self, domain_id=None, group=None): + """Delete domain config. + + DELETE /v3/domains/{domain_id}/config/{group} + """ + ENFORCER.enforce_call(action='identity:delete_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + PROVIDERS.domain_config_api.delete_config(domain_id, group) + return None, http_client.NO_CONTENT + + +class DomainConfigOptionResource(ks_flask.ResourceBase): + member_key = 'config' + collection_key = 'config' + + def get(self, domain_id=None, group=None, option=None): + """Check if config option exists. + + GET/HEAD /v3/domains/{domain_id}/config/{group}/{option} + """ + err = None + config = {} + try: + PROVIDERS.resource_api.get_domain(domain_id) + except Exception as e: # nosec + # We don't raise out here, we raise out after enforcement, this + # ensures we do not leak domain existance. + err = e + finally: + if group and group == 'security_compliance': + config = self._get_security_compliance_config( + domain_id, group, option) + else: + config = self._get_config(domain_id, group, option) + if err is not None: + raise err + return {self.member_key: config} + + def _get_config(self, domain_id, group, option): + ENFORCER.enforce_call(action='identity:get_domain_config') + return PROVIDERS.domain_config_api.get_config( + domain_id, group=group, option=option) + + def _get_security_compliance_config(self, domain_id, group, option): + ENFORCER.enforce_call( + action='identity:get_security_compliance_domain_config') + return PROVIDERS.domain_config_api.get_security_compliance_config( + domain_id, group, option=option) + + def patch(self, domain_id=None, group=None, option=None): + """Update domain config option. + + PATCH /v3/domains/{domain_id}/config/{group}/{option} + """ + ENFORCER.enforce_call(action='identity:update_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + config = self.request_body_json.get('config', {}) + ref = PROVIDERS.domain_config_api.update_config( + domain_id, config, group, option=option) + return {self.member_key: ref} + + def delete(self, domain_id=None, group=None, option=None): + """Delete domain config. + + DELETE /v3/domains/{domain_id}/config/{group}/{option} + """ + ENFORCER.enforce_call(action='identity:delete_domain_config') + PROVIDERS.resource_api.get_domain(domain_id) + PROVIDERS.domain_config_api.delete_config( + domain_id, group, option=option) + return None, http_client.NO_CONTENT + + +class DefaultConfigResource(flask_restful.Resource): + def get(self): + """Get default domain config. + + GET/HEAD /v3/domains/config/default + """ + ENFORCER.enforce_call(action='identity:get_domain_config_default') + ref = PROVIDERS.domain_config_api.get_config_default() + return {'config': ref} + + +class DefaultConfigGroupResource(flask_restful.Resource): + def get(self, group=None): + """Get default domain group config. + + GET/HEAD /v3/domains/config/{group}/default + """ + ENFORCER.enforce_call(action='identity:get_domain_config_default') + ref = PROVIDERS.domain_config_api.get_config_default(group=group) + return {'config': ref} + + +class DefaultConfigOptionResource(flask_restful.Resource): + def get(self, group=None, option=None): + """Get default domain group option config. + + GET/HEAD /v3/domains/config/{group}/{option}/default + """ + ENFORCER.enforce_call(action='identity:get_domain_config_default') + ref = PROVIDERS.domain_config_api.get_config_default( + group=group, option=option) + return {'config': ref} + + +class DomainUserListResource(flask_restful.Resource): + def get(self, domain_id=None, user_id=None): + """Get user grant. + + GET/HEAD /v3/domains/{domain_id}/users/{user_id}/roles + """ + ENFORCER.enforce_call( + action='identity:list_grants', + target_attr=_build_enforcement_target()) + refs = PROVIDERS.assignment_api.list_grants( + domain_id=domain_id, user_id=user_id, + inherited_to_projects=False) + return ks_flask.ResourceBase.wrap_collection( + refs, collection_name='roles') + + +class DomainUserResource(ks_flask.ResourceBase): + member_key = 'grant' + collection_key = 'grants' + + def get(self, domain_id=None, user_id=None, role_id=None): + """Check if a user has a specific role on the domain. + + GET/HEAD /v3/domains/{domain_id}/users/{user_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:check_grant', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.get_grant( + role_id, domain_id=domain_id, user_id=user_id, + inherited_to_projects=False) + return None, http_client.NO_CONTENT + + def put(self, domain_id=None, user_id=None, role_id=None): + """Create a role to a user on a domain. + + PUT /v3/domains/{domain_id}/users/{user_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:create_grant', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.create_grant( + role_id, domain_id=domain_id, user_id=user_id, + inherited_to_projects=False, initiator=self.audit_initiator) + return None, http_client.NO_CONTENT + + def delete(self, domain_id=None, user_id=None, role_id=None): + """Revoke a role from user on a domain. + + DELETE /v3/domains/{domain_id}/users/{user_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:revoke_grant', + target_attr=_build_enforcement_target(allow_non_existing=True)) + PROVIDERS.assignment_api.delete_grant( + role_id, domain_id=domain_id, user_id=user_id, + inherited_to_projects=False, initiator=self.audit_initiator) + return None, http_client.NO_CONTENT + + +class DomainGroupListResource(flask_restful.Resource): + def get(self, domain_id=None, group_id=None): + """List all domain grats for a specific group. + + GET/HEAD /v3/domains/{domain_id}/groups/{group_id}/roles + """ + ENFORCER.enforce_call( + action='identity:list_grants', + target_attr=_build_enforcement_target()) + refs = PROVIDERS.assignment_api.list_grants( + domain_id=domain_id, group_id=group_id, + inherited_to_projects=False) + return ks_flask.ResourceBase.wrap_collection( + refs, collection_name='roles') + + +class DomainGroupResource(ks_flask.ResourceBase): + member_key = 'grant' + collection_key = 'grants' + + def get(self, domain_id=None, group_id=None, role_id=None): + """Check if a group has a specific role on a domain. + + GET/HEAD /v3/domains/{domain_id}/groups/{group_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:check_grant', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.get_grant( + role_id, domain_id=domain_id, group_id=group_id, + inherited_to_projects=False) + return None, http_client.NO_CONTENT + + def put(self, domain_id=None, group_id=None, role_id=None): + """Grant a role to a group on a domain. + + PUT /v3/domains/{domain_id}/groups/{group_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:create_grant', + target_attr=_build_enforcement_target()) + PROVIDERS.assignment_api.create_grant( + role_id, domain_id=domain_id, group_id=group_id, + inherited_to_projects=False, initiator=self.audit_initiator) + return None, http_client.NO_CONTENT + + def delete(self, domain_id=None, group_id=None, role_id=None): + """Revoke a role from a group on a domain. + + DELETE /v3/domains/{domain_id}/groups/{group_id}/roles/{role_id} + """ + ENFORCER.enforce_call( + action='identity:revoke_grant', + target_attr=_build_enforcement_target(allow_non_existing=True)) + PROVIDERS.assignment_api.delete_grant( + role_id, domain_id=domain_id, group_id=group_id, + inherited_to_projects=False, initiator=self.audit_initiator) + return None, http_client.NO_CONTENT + + +class DomainAPI(ks_flask.APIBase): + CONFIG_GROUP = json_home.build_v3_parameter_relation('config_group') + CONFIG_OPTION = json_home.build_v3_parameter_relation('config_option') + _name = 'domains' + _import_name = __name__ + resources = [DomainResource] + resource_mapping = [ + ks_flask.construct_resource_map( + resource=DomainConfigResource, + url=('/domains//config'), + resource_kwargs={}, + rel='domain_config', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID}), + ks_flask.construct_resource_map( + resource=DomainConfigGroupResource, + url='/domains//config/', + resource_kwargs={}, + rel='domain_config_group', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID, + 'group': CONFIG_GROUP}), + ks_flask.construct_resource_map( + resource=DomainConfigOptionResource, + url=('/domains//config/' + '/'), + resource_kwargs={}, + rel='domain_config_option', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID, + 'group': CONFIG_GROUP, + 'option': CONFIG_OPTION}), + ks_flask.construct_resource_map( + resource=DefaultConfigResource, + url=('/domains/config/default'), + resource_kwargs={}, + rel='domain_config_default', + path_vars={}), + ks_flask.construct_resource_map( + resource=DefaultConfigGroupResource, + url='/domains/config//default', + resource_kwargs={}, + rel='domain_config_default_group', + path_vars={ + 'group': CONFIG_GROUP}), + ks_flask.construct_resource_map( + resource=DefaultConfigOptionResource, + url=('/domains/config/' + '//default'), + resource_kwargs={}, + rel='domain_config_default_option', + path_vars={ + 'group': CONFIG_GROUP, + 'option': CONFIG_OPTION}), + ks_flask.construct_resource_map( + resource=DomainUserListResource, + url=('/domains//users' + '//roles'), + resource_kwargs={}, + rel='domain_user_roles', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID, + 'user_id': json_home.Parameters.USER_ID, + }), + ks_flask.construct_resource_map( + resource=DomainUserResource, + url=('/domains//users' + '//roles/'), + resource_kwargs={}, + rel='domain_user_role', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID, + 'user_id': json_home.Parameters.USER_ID, + 'role_id': json_home.Parameters.ROLE_ID + }), + ks_flask.construct_resource_map( + resource=DomainGroupListResource, + url=('/domains//groups' + '//roles'), + resource_kwargs={}, + rel='domain_group_roles', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID, + 'group_id': json_home.Parameters.GROUP_ID, + }), + ks_flask.construct_resource_map( + resource=DomainGroupResource, + url=('/domains//groups' + '//roles/'), + resource_kwargs={}, + rel='domain_group_role', + path_vars={ + 'domain_id': json_home.Parameters.DOMAIN_ID, + 'group_id': json_home.Parameters.GROUP_ID, + 'role_id': json_home.Parameters.ROLE_ID + }) + ] + + +APIs = (DomainAPI,) diff --git a/keystone/assignment/core.py b/keystone/assignment/core.py index bc95746a63..c9f90de5ee 100644 --- a/keystone/assignment/core.py +++ b/keystone/assignment/core.py @@ -285,7 +285,8 @@ class Manager(manager.Manager): @notifications.role_assignment('created') def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, - inherited_to_projects=False, context=None): + inherited_to_projects=False, context=None, + initiator=None): role = PROVIDERS.role_api.get_role(role_id) if domain_id: PROVIDERS.resource_api.get_domain(domain_id) @@ -335,7 +336,8 @@ class Manager(manager.Manager): @notifications.role_assignment('deleted') def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, - inherited_to_projects=False, context=None): + inherited_to_projects=False, context=None, + initiator=None): # check if role exist before any processing PROVIDERS.role_api.get_role(role_id) diff --git a/keystone/assignment/routers.py b/keystone/assignment/routers.py index ee71173f79..2d447f3e4e 100644 --- a/keystone/assignment/routers.py +++ b/keystone/assignment/routers.py @@ -31,7 +31,7 @@ class Public(wsgi.ComposableRouter): class Routers(wsgi.RoutersBase): - _path_prefixes = ('users', 'projects', 'domains') + _path_prefixes = ('users', 'projects') def append_v3_routers(self, mapper, routers): @@ -88,45 +88,3 @@ class Routers(wsgi.RoutersBase): 'group_id': json_home.Parameters.GROUP_ID, 'project_id': json_home.Parameters.PROJECT_ID, }) - self._add_resource( - mapper, grant_controller, - path='/domains/{domain_id}/users/{user_id}/roles/{role_id}', - get_head_action='check_grant', - put_action='create_grant', - delete_action='revoke_grant', - rel=json_home.build_v3_resource_relation('domain_user_role'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID, - 'role_id': json_home.Parameters.ROLE_ID, - 'user_id': json_home.Parameters.USER_ID, - }) - self._add_resource( - mapper, grant_controller, - path='/domains/{domain_id}/groups/{group_id}/roles/{role_id}', - get_head_action='check_grant', - put_action='create_grant', - delete_action='revoke_grant', - rel=json_home.build_v3_resource_relation('domain_group_role'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID, - 'group_id': json_home.Parameters.GROUP_ID, - 'role_id': json_home.Parameters.ROLE_ID, - }) - self._add_resource( - mapper, grant_controller, - path='/domains/{domain_id}/users/{user_id}/roles', - get_head_action='list_grants', - rel=json_home.build_v3_resource_relation('domain_user_roles'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID, - 'user_id': json_home.Parameters.USER_ID, - }) - self._add_resource( - mapper, grant_controller, - path='/domains/{domain_id}/groups/{group_id}/roles', - get_head_action='list_grants', - rel=json_home.build_v3_resource_relation('domain_group_roles'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID, - 'group_id': json_home.Parameters.GROUP_ID, - }) diff --git a/keystone/notifications.py b/keystone/notifications.py index 5ec5f371ce..dfbac8593f 100644 --- a/keystone/notifications.py +++ b/keystone/notifications.py @@ -615,7 +615,14 @@ class CadfRoleAssignmentNotificationWrapper(object): inherited = call_args['inherited_to_projects'] context = call_args['context'] - initiator = _get_request_audit_info(context) + # TODO(gagehugo): Once all of the APIs for grant creation + # and deletion are moved over to flask, get rid of checking + # context here and only grab the initiator from the + # passed in value + if context: + initiator = _get_request_audit_info(context) + else: + initiator = call_args.get('initiator', None) target = resource.Resource(typeURI=taxonomy.ACCOUNT_USER) audit_kwargs = {} diff --git a/keystone/resource/controllers.py b/keystone/resource/controllers.py index 054cbc562a..476d5a4fda 100644 --- a/keystone/resource/controllers.py +++ b/keystone/resource/controllers.py @@ -39,118 +39,6 @@ class DomainV3(controller.V3Controller): super(DomainV3, self).__init__() self.get_member_from_driver = PROVIDERS.resource_api.get_domain - @controller.protected() - def create_domain(self, request, domain): - validation.lazy_validate(schema.domain_create, domain) - ref = self._assign_unique_id(self._normalize_dict(domain)) - ref = PROVIDERS.resource_api.create_domain( - ref['id'], ref, initiator=request.audit_initiator - ) - return DomainV3.wrap_member(request.context_dict, ref) - - @controller.filterprotected('enabled', 'name') - def list_domains(self, request, filters): - hints = DomainV3.build_driver_hints(request, filters) - refs = PROVIDERS.resource_api.list_domains(hints=hints) - return DomainV3.wrap_collection(request.context_dict, - refs, hints=hints) - - @controller.protected() - def get_domain(self, request, domain_id): - ref = PROVIDERS.resource_api.get_domain(domain_id) - return DomainV3.wrap_member(request.context_dict, ref) - - @controller.protected() - def update_domain(self, request, domain_id, domain): - validation.lazy_validate(schema.domain_update, domain) - self._require_matching_id(domain_id, domain) - ref = PROVIDERS.resource_api.update_domain( - domain_id, domain, initiator=request.audit_initiator - ) - return DomainV3.wrap_member(request.context_dict, ref) - - @controller.protected() - def delete_domain(self, request, domain_id): - return PROVIDERS.resource_api.delete_domain( - domain_id, initiator=request.audit_initiator - ) - - -class DomainConfigV3(controller.V3Controller): - member_name = 'config' - - @controller.protected() - def create_domain_config(self, request, domain_id, config): - PROVIDERS.resource_api.get_domain(domain_id) - original_config = ( - PROVIDERS.domain_config_api.get_config_with_sensitive_info( - domain_id - ) - ) - ref = PROVIDERS.domain_config_api.create_config(domain_id, config) - if original_config: - # Return status code 200, since config already existed - return wsgi.render_response(body={self.member_name: ref}) - else: - return wsgi.render_response( - body={self.member_name: ref}, - status=(http_client.CREATED, - http_client.responses[http_client.CREATED])) - - def get_domain_config_wrapper(self, request, domain_id, group=None, - option=None): - if group and group == 'security_compliance': - return self.get_security_compliance_domain_config( - request, domain_id, group=group, option=option - ) - else: - return self.get_domain_config( - request, domain_id, group=group, option=option - ) - - @controller.protected() - def get_security_compliance_domain_config(self, request, domain_id, - group=None, option=None): - ref = PROVIDERS.domain_config_api.get_security_compliance_config( - domain_id, group, option=option - ) - return {self.member_name: ref} - - @controller.protected() - def get_domain_config(self, request, domain_id, group=None, option=None): - PROVIDERS.resource_api.get_domain(domain_id) - ref = PROVIDERS.domain_config_api.get_config(domain_id, group, option) - return {self.member_name: ref} - - @controller.protected() - def update_domain_config( - self, request, domain_id, config, group, option): - PROVIDERS.resource_api.get_domain(domain_id) - ref = PROVIDERS.domain_config_api.update_config( - domain_id, config, group, option) - return wsgi.render_response(body={self.member_name: ref}) - - def update_domain_config_group(self, context, domain_id, group, config): - PROVIDERS.resource_api.get_domain(domain_id) - return self.update_domain_config( - context, domain_id, config, group, option=None) - - def update_domain_config_only(self, context, domain_id, config): - PROVIDERS.resource_api.get_domain(domain_id) - return self.update_domain_config( - context, domain_id, config, group=None, option=None) - - @controller.protected() - def delete_domain_config( - self, request, domain_id, group=None, option=None): - PROVIDERS.resource_api.get_domain(domain_id) - PROVIDERS.domain_config_api.delete_config(domain_id, group, option) - - @controller.protected() - def get_domain_config_default(self, request, group=None, option=None): - ref = PROVIDERS.domain_config_api.get_config_default(group, option) - return {self.member_name: ref} - class ProjectV3(controller.V3Controller): collection_name = 'projects' diff --git a/keystone/resource/routers.py b/keystone/resource/routers.py index 4ff65e37af..17a7a818a4 100644 --- a/keystone/resource/routers.py +++ b/keystone/resource/routers.py @@ -23,85 +23,11 @@ from keystone.resource import controllers class Routers(wsgi.RoutersBase): - _path_prefixes = ('domains', 'projects') + _path_prefixes = ('projects') def append_v3_routers(self, mapper, routers): - routers.append( - router.Router(controllers.DomainV3(), - 'domains', 'domain', - resource_descriptions=self.v3_resources)) - - config_controller = controllers.DomainConfigV3() tag_controller = controllers.ProjectTagV3() - self._add_resource( - mapper, config_controller, - path='/domains/{domain_id}/config', - get_head_action='get_domain_config', - put_action='create_domain_config', - patch_action='update_domain_config_only', - delete_action='delete_domain_config', - rel=json_home.build_v3_resource_relation('domain_config'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID - }) - - config_group_param = ( - json_home.build_v3_parameter_relation('config_group')) - self._add_resource( - mapper, config_controller, - path='/domains/{domain_id}/config/{group}', - get_head_action='get_domain_config_wrapper', - patch_action='update_domain_config_group', - delete_action='delete_domain_config', - rel=json_home.build_v3_resource_relation('domain_config_group'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID, - 'group': config_group_param - }) - - self._add_resource( - mapper, config_controller, - path='/domains/{domain_id}/config/{group}/{option}', - get_head_action='get_domain_config_wrapper', - patch_action='update_domain_config', - delete_action='delete_domain_config', - rel=json_home.build_v3_resource_relation('domain_config_option'), - path_vars={ - 'domain_id': json_home.Parameters.DOMAIN_ID, - 'group': config_group_param, - 'option': json_home.build_v3_parameter_relation( - 'config_option') - }) - - self._add_resource( - mapper, config_controller, - path='/domains/config/default', - get_head_action='get_domain_config_default', - rel=json_home.build_v3_resource_relation('domain_config_default')) - - self._add_resource( - mapper, config_controller, - path='/domains/config/{group}/default', - get_head_action='get_domain_config_default', - rel=json_home.build_v3_resource_relation( - 'domain_config_default_group'), - path_vars={ - 'group': config_group_param - }) - - self._add_resource( - mapper, config_controller, - path='/domains/config/{group}/{option}/default', - get_head_action='get_domain_config_default', - rel=json_home.build_v3_resource_relation( - 'domain_config_default_option'), - path_vars={ - 'group': config_group_param, - 'option': json_home.build_v3_parameter_relation( - 'config_option') - }) - routers.append( router.Router(controllers.ProjectV3(), 'projects', 'project', diff --git a/keystone/server/flask/application.py b/keystone/server/flask/application.py index ed39391229..3fed7b5763 100644 --- a/keystone/server/flask/application.py +++ b/keystone/server/flask/application.py @@ -39,6 +39,7 @@ from keystone.resource import routers as resource_routers # support is removed. _MOVED_API_PREFIXES = frozenset( ['credentials', + 'domains', 'endpoints', 'groups', 'OS-EP-FILTER',