diff options
-rw-r--r-- | doc/source/policy_mapping.rst | 4 | ||||
-rw-r--r-- | etc/policy.json | 3 | ||||
-rw-r--r-- | etc/policy.v3cloudsample.json | 3 | ||||
-rw-r--r-- | keystone/resource/controllers.py | 5 | ||||
-rw-r--r-- | keystone/resource/core.py | 53 | ||||
-rw-r--r-- | keystone/resource/routers.py | 31 | ||||
-rw-r--r-- | keystone/tests/unit/test_v3_domain_config.py | 56 | ||||
-rw-r--r-- | keystone/tests/unit/test_versions.py | 14 | ||||
-rw-r--r-- | releasenotes/notes/bp-domain-config-default-82e42d946ee7cb43.yaml | 7 |
9 files changed, 173 insertions, 3 deletions
diff --git a/doc/source/policy_mapping.rst b/doc/source/policy_mapping.rst index d596f71ef..238934ed4 100644 --- a/doc/source/policy_mapping.rst +++ b/doc/source/policy_mapping.rst @@ -186,7 +186,9 @@ identity:update_domain_config - PATCH /v3/domains/{ identity:delete_domain_config - DELETE /v3/domains/{domain_id}/config - DELETE /v3/domains/{domain_id}/config/{group} - DELETE /v3/domains/{domain_id}/config/{group}/{option} - +identity:get_domain_config_default - GET /v3/domains/config/default + - GET /v3/domains/config/{group}/default + - GET /v3/domains/config/{group}/{option}/default ========================================================= === .. _grant_resources: diff --git a/etc/policy.json b/etc/policy.json index c3ad786f0..47aa9efd8 100644 --- a/etc/policy.json +++ b/etc/policy.json @@ -181,5 +181,6 @@ "identity:create_domain_config": "rule:admin_required", "identity:get_domain_config": "rule:admin_required", "identity:update_domain_config": "rule:admin_required", - "identity:delete_domain_config": "rule:admin_required" + "identity:delete_domain_config": "rule:admin_required", + "identity:get_domain_config_default": "rule:admin_required" } diff --git a/etc/policy.v3cloudsample.json b/etc/policy.v3cloudsample.json index 6b466904c..b903f1729 100644 --- a/etc/policy.v3cloudsample.json +++ b/etc/policy.v3cloudsample.json @@ -193,5 +193,6 @@ "identity:create_domain_config": "rule:cloud_admin", "identity:get_domain_config": "rule:cloud_admin", "identity:update_domain_config": "rule:cloud_admin", - "identity:delete_domain_config": "rule:cloud_admin" + "identity:delete_domain_config": "rule:cloud_admin", + "identity:get_domain_config_default": "rule:cloud_admin" } diff --git a/keystone/resource/controllers.py b/keystone/resource/controllers.py index ef28085cb..d748fe54c 100644 --- a/keystone/resource/controllers.py +++ b/keystone/resource/controllers.py @@ -206,6 +206,11 @@ class DomainConfigV3(controller.V3Controller): self.resource_api.get_domain(domain_id) self.domain_config_api.delete_config(domain_id, group, option) + @controller.protected() + def get_domain_config_default(self, context, group=None, option=None): + ref = self.domain_config_api.get_config_default(group, option) + return {self.member_name: ref} + @dependency.requires('resource_api') class ProjectV3(controller.V3Controller): diff --git a/keystone/resource/core.py b/keystone/resource/core.py index 02eb204a3..f1230d29d 100644 --- a/keystone/resource/core.py +++ b/keystone/resource/core.py @@ -1519,6 +1519,59 @@ class DomainConfigManager(manager.Manager): """ return self._get_config_with_sensitive_info(domain_id) + def get_config_default(self, group=None, option=None): + """Get default config, or partial default config + + :param group: an optional specific group of options + :param option: an optional specific option within the group + + :returns: a dict of group dicts containing the default options, + filtered by group and option if specified + :raises keystone.exception.InvalidDomainConfig: when the config + and group/option parameters specify an option we do not + support (or one that is not whitelisted). + + An example response:: + + { + 'ldap': { + 'url': 'myurl', + 'user_tree_dn': 'OU=myou', + ....}, + 'identity': { + 'driver': 'ldap'} + + } + + """ + def _option_dict(group, option): + group_attr = getattr(CONF, group) + if group_attr is None: + msg = _('Group %s not found in config') % group + raise exception.UnexpectedError(msg) + return {'group': group, 'option': option, + 'value': getattr(group_attr, option)} + + self._assert_valid_group_and_option(group, option) + config_list = [] + if group: + if option: + if option not in self.whitelisted_options[group]: + msg = _('Reading the default for option %(option)s in ' + 'group %(group)s is not supported') % { + 'option': option, 'group': group} + raise exception.InvalidDomainConfig(reason=msg) + config_list.append(_option_dict(group, option)) + else: + for each_option in self.whitelisted_options[group]: + config_list.append(_option_dict(group, each_option)) + else: + for each_group in self.whitelisted_options: + for each_option in self.whitelisted_options[each_group]: + config_list.append(_option_dict(each_group, each_option)) + + return self._list_to_config(config_list, req_option=option) + @six.add_metaclass(abc.ABCMeta) class DomainConfigDriverV8(object): diff --git a/keystone/resource/routers.py b/keystone/resource/routers.py index 8ccd10aaa..d58474e22 100644 --- a/keystone/resource/routers.py +++ b/keystone/resource/routers.py @@ -88,6 +88,37 @@ class Routers(wsgi.RoutersBase): 'config_option') }) + self._add_resource( + mapper, config_controller, + path='/domains/config/default', + get_action='get_domain_config_default', + rel=json_home.build_v3_resource_relation('domain_config_default'), + status=json_home.Status.EXPERIMENTAL) + + self._add_resource( + mapper, config_controller, + path='/domains/config/{group}/default', + get_action='get_domain_config_default', + rel=json_home.build_v3_resource_relation( + 'domain_config_default_group'), + status=json_home.Status.EXPERIMENTAL, + path_vars={ + 'group': config_group_param + }) + + self._add_resource( + mapper, config_controller, + path='/domains/config/{group}/{option}/default', + get_action='get_domain_config_default', + rel=json_home.build_v3_resource_relation( + 'domain_config_default_option'), + status=json_home.Status.EXPERIMENTAL, + 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/tests/unit/test_v3_domain_config.py b/keystone/tests/unit/test_v3_domain_config.py index b185455ed..ee716081b 100644 --- a/keystone/tests/unit/test_v3_domain_config.py +++ b/keystone/tests/unit/test_v3_domain_config.py @@ -401,3 +401,59 @@ class DomainConfigTestCase(test_v3.RestfulTestCase): 'invalid_option': invalid_option}, body={'config': new_config}, expected_status=exception.DomainNotFound.code) + + def test_get_config_default(self): + """Call ``GET /domains/config/default``.""" + # Create a config that overrides a few of the options so that we can + # check that only the defaults are returned. + self.domain_config_api.create_config(self.domain['id'], self.config) + url = '/domains/config/default' + r = self.get(url) + default_config = r.result['config'] + for group in default_config: + for option in default_config[group]: + self.assertEqual(getattr(getattr(CONF, group), option), + default_config[group][option]) + + def test_get_config_default_by_group(self): + """Call ``GET /domains/config/{group}/default``.""" + # Create a config that overrides a few of the options so that we can + # check that only the defaults are returned. + self.domain_config_api.create_config(self.domain['id'], self.config) + url = '/domains/config/ldap/default' + r = self.get(url) + default_config = r.result['config'] + for option in default_config['ldap']: + self.assertEqual(getattr(CONF.ldap, option), + default_config['ldap'][option]) + + def test_get_config_default_by_option(self): + """Call ``GET /domains/config/{group}/{option}/default``.""" + # Create a config that overrides a few of the options so that we can + # check that only the defaults are returned. + self.domain_config_api.create_config(self.domain['id'], self.config) + url = '/domains/config/ldap/url/default' + r = self.get(url) + default_config = r.result['config'] + self.assertEqual(CONF.ldap.url, default_config['url']) + + def test_get_config_default_by_invalid_group(self): + """Call ``GET for /domains/config/{bad-group}/default``.""" + # First try a valid group, but one we don't support for domain config + self.get('/domains/config/resouce/default', + expected_status=http_client.FORBIDDEN) + + # Now try a totally invalid group + url = '/domains/config/%s/default' % uuid.uuid4().hex + self.get(url, expected_status=http_client.FORBIDDEN) + + def test_get_config_default_by_invalid_option(self): + """Call ``GET for /domains/config/{group}/{bad-option}/default``.""" + # First try a valid option, but one we don't support for domain config, + # i.e. one that is in the sensitive options list + self.get('/domains/config/ldap/password/default', + expected_status=http_client.FORBIDDEN) + + # Now try a totally invalid option + url = '/domains/config/ldap/%s/default' % uuid.uuid4().hex + self.get(url, expected_status=http_client.FORBIDDEN) diff --git a/keystone/tests/unit/test_versions.py b/keystone/tests/unit/test_versions.py index 340b0139e..b8ed41606 100644 --- a/keystone/tests/unit/test_versions.py +++ b/keystone/tests/unit/test_versions.py @@ -584,6 +584,20 @@ V3_JSON_HOME_RESOURCES = { 'group': json_home.build_v3_parameter_relation('config_group'), 'option': json_home.build_v3_parameter_relation('config_option')}, 'hints': {'status': 'experimental'}}, + json_home.build_v3_resource_relation('domain_config_default'): { + 'href': '/domains/config/default', + 'hints': {'status': 'experimental'}}, + json_home.build_v3_resource_relation('domain_config_default_group'): { + 'href-template': '/domains/config/{group}/default', + 'href-vars': { + 'group': json_home.build_v3_parameter_relation('config_group')}, + 'hints': {'status': 'experimental'}}, + json_home.build_v3_resource_relation('domain_config_default_option'): { + 'href-template': '/domains/config/{group}/{option}/default', + 'href-vars': { + 'group': json_home.build_v3_parameter_relation('config_group'), + 'option': json_home.build_v3_parameter_relation('config_option')}, + 'hints': {'status': 'experimental'}}, } diff --git a/releasenotes/notes/bp-domain-config-default-82e42d946ee7cb43.yaml b/releasenotes/notes/bp-domain-config-default-82e42d946ee7cb43.yaml new file mode 100644 index 000000000..a78f831fa --- /dev/null +++ b/releasenotes/notes/bp-domain-config-default-82e42d946ee7cb43.yaml @@ -0,0 +1,7 @@ +--- +features: + - > + [`blueprint domain-config-default <https://blueprints.launchpad.net/keystone/+spec/domain-config-default>`_] + The Identity API now supports retrieving the default values for the + configuration options that can be overriden via the domain specific + configuration API. |