From c734b5858189ede6969cc1f0d386196c551b4292 Mon Sep 17 00:00:00 2001 From: Anthony Washington Date: Fri, 17 Feb 2017 21:07:54 +0000 Subject: [PATCH] Policy in code Adding the beginning implementation for registering and using default policy rules in code. Rules are defined in the new policies module and added to the return list __init__.py. Default policies can now be maintained in code and registered via listing mechanisms in the policies module. As we go, we can remove the duplicated default policies from our policy.json file. This commit specifically: - Creates a new module called `policies` to hold our in code defaults. - Ensure we pass our in code policy list to our policy ENFORCER. - Add base policy module for common policy rules. - Add service default policy module for policy rules. - Add endpoint default policy module for policy rules. - Add regions default policy module for policy rules. partially-implements blueprint policy-in-code Co-Authored-By: Richard Avelar csravelar@gmail.com Change-Id: Ic47b1e8b0d479032d8a7b9891ed9800be7036d94 --- etc/policy.json | 29 ---------- keystone/common/controller.py | 13 ++--- keystone/common/policies/__init__.py | 27 ++++++++++ keystone/common/policies/base.py | 52 ++++++++++++++++++ keystone/common/policies/endpoint.py | 37 +++++++++++++ keystone/common/policies/region.py | 37 +++++++++++++ keystone/common/policies/service.py | 37 +++++++++++++ keystone/common/policy.py | 67 +++++++++++++++++++++++ keystone/common/wsgi.py | 3 +- keystone/policy/backends/rules.py | 46 +--------------- keystone/tests/unit/ksfixtures/policy.py | 6 +-- keystone/tests/unit/test_policy.py | 69 ++++++++++++++---------- keystone/tests/unit/test_v3_auth.py | 8 +-- 13 files changed, 314 insertions(+), 117 deletions(-) create mode 100644 keystone/common/policies/__init__.py create mode 100644 keystone/common/policies/base.py create mode 100644 keystone/common/policies/endpoint.py create mode 100644 keystone/common/policies/region.py create mode 100644 keystone/common/policies/service.py create mode 100644 keystone/common/policy.py diff --git a/etc/policy.json b/etc/policy.json index ddf2396272..fa7fe584fa 100644 --- a/etc/policy.json +++ b/etc/policy.json @@ -1,33 +1,4 @@ { - "admin_required": "role:admin or is_admin:1", - "service_role": "role:service", - "service_or_admin": "rule:admin_required or rule:service_role", - "owner" : "user_id:%(user_id)s", - "admin_or_owner": "rule:admin_required or rule:owner", - "token_subject": "user_id:%(target.token.user_id)s", - "admin_or_token_subject": "rule:admin_required or rule:token_subject", - "service_admin_or_token_subject": "rule:service_or_admin or rule:token_subject", - - "default": "rule:admin_required", - - "identity:get_region": "", - "identity:list_regions": "", - "identity:create_region": "rule:admin_required", - "identity:update_region": "rule:admin_required", - "identity:delete_region": "rule:admin_required", - - "identity:get_service": "rule:admin_required", - "identity:list_services": "rule:admin_required", - "identity:create_service": "rule:admin_required", - "identity:update_service": "rule:admin_required", - "identity:delete_service": "rule:admin_required", - - "identity:get_endpoint": "rule:admin_required", - "identity:list_endpoints": "rule:admin_required", - "identity:create_endpoint": "rule:admin_required", - "identity:update_endpoint": "rule:admin_required", - "identity:delete_endpoint": "rule:admin_required", - "identity:get_domain": "rule:admin_required or token.project.domain.id:%(target.domain.id)s", "identity:list_domains": "rule:admin_required", "identity:create_domain": "rule:admin_required", diff --git a/keystone/common/controller.py b/keystone/common/controller.py index b248eb755d..eeec11732e 100644 --- a/keystone/common/controller.py +++ b/keystone/common/controller.py @@ -23,6 +23,7 @@ import six from keystone.common import authorization from keystone.common import dependency from keystone.common import driver_hints +from keystone.common import policy from keystone.common import utils from keystone.common import wsgi import keystone.conf @@ -157,9 +158,7 @@ def protected(callback=None): # Add in the kwargs, which means that any entity provided as a # parameter for calls like create and update will be included. policy_dict.update(kwargs) - self.policy_api.enforce(creds, - action, - utils.flatten_dict(policy_dict)) + policy.enforce(creds, action, utils.flatten_dict(policy_dict)) LOG.debug('RBAC: Authorization granted') return f(self, request, *args, **kwargs) return inner @@ -225,9 +224,7 @@ def filterprotected(*filters, **callback): for key in kwargs: target[key] = kwargs[key] - self.policy_api.enforce(creds, - action, - utils.flatten_dict(target)) + policy.enforce(creds, action, utils.flatten_dict(target)) LOG.debug('RBAC: Authorization granted') else: @@ -772,9 +769,7 @@ class V3Controller(wsgi.Application): policy_dict.update(prep_info['input_attr']) if 'filter_attr' in prep_info: policy_dict.update(prep_info['filter_attr']) - self.policy_api.enforce(creds, - action, - utils.flatten_dict(policy_dict)) + policy.enforce(creds, action, utils.flatten_dict(policy_dict)) LOG.debug('RBAC: Authorization granted') @classmethod diff --git a/keystone/common/policies/__init__.py b/keystone/common/policies/__init__.py new file mode 100644 index 0000000000..f44baf69e0 --- /dev/null +++ b/keystone/common/policies/__init__.py @@ -0,0 +1,27 @@ +# 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. + +import itertools + +from keystone.common.policies import base +from keystone.common.policies import endpoint +from keystone.common.policies import region +from keystone.common.policies import service + + +def list_rules(): + return itertools.chain( + base.list_rules(), + endpoint.list_rules(), + region.list_rules(), + service.list_rules() + ) diff --git a/keystone/common/policies/base.py b/keystone/common/policies/base.py new file mode 100644 index 0000000000..e317d80b7f --- /dev/null +++ b/keystone/common/policies/base.py @@ -0,0 +1,52 @@ +# 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. + +from oslo_policy import policy + +IDENTITY = 'identity:%s' +RULE_ADMIN_REQUIRED = 'rule:admin_required' +RULE_ADMIN_OR_OWNER = 'rule:admin_or_owner' + + +rules = [ + policy.RuleDefault( + name='admin_required', + check_str='role:admin or is_admin:1'), + policy.RuleDefault( + name='service_role', + check_str='role:service'), + policy.RuleDefault( + name='service_or_admin', + check_str='rule:admin_required or rule:service_role'), + policy.RuleDefault( + name='owner', + check_str='user_id:%(user_id)s'), + policy.RuleDefault( + name='admin_or_owner', + check_str='rule:admin_required or rule:owner'), + policy.RuleDefault( + name='token_subject', + check_str='user_id:%(target.token.user_id)s'), + policy.RuleDefault( + name='admin_or_token_subject', + check_str='rule:admin_required or rule:token_subject'), + policy.RuleDefault( + name='service_admin_or_token_subject', + check_str='rule:service_or_admin or rule:token_subject'), + policy.RuleDefault( + name='default', + check_str='rule:admin_required') +] + + +def list_rules(): + return rules diff --git a/keystone/common/policies/endpoint.py b/keystone/common/policies/endpoint.py new file mode 100644 index 0000000000..d58e8ca440 --- /dev/null +++ b/keystone/common/policies/endpoint.py @@ -0,0 +1,37 @@ +# 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. + +from oslo_policy import policy + +from keystone.common.policies import base + +endpoint_policies = [ + policy.RuleDefault( + name=base.IDENTITY % 'get_endpoint', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'list_endpoints', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'create_endpoint', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'update_endpoint', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'delete_endpoint', + check_str=base.RULE_ADMIN_REQUIRED) +] + + +def list_rules(): + return endpoint_policies diff --git a/keystone/common/policies/region.py b/keystone/common/policies/region.py new file mode 100644 index 0000000000..f600b1083e --- /dev/null +++ b/keystone/common/policies/region.py @@ -0,0 +1,37 @@ +# 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. + +from oslo_policy import policy + +from keystone.common.policies import base + +region_policies = [ + policy.RuleDefault( + name=base.IDENTITY % 'get_region', + check_str=''), + policy.RuleDefault( + name=base.IDENTITY % 'list_regions', + check_str=''), + policy.RuleDefault( + name=base.IDENTITY % 'create_region', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'update_region', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'delete_region', + check_str=base.RULE_ADMIN_REQUIRED), +] + + +def list_rules(): + return region_policies diff --git a/keystone/common/policies/service.py b/keystone/common/policies/service.py new file mode 100644 index 0000000000..4ddbd877ad --- /dev/null +++ b/keystone/common/policies/service.py @@ -0,0 +1,37 @@ +# 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. + +from oslo_policy import policy + +from keystone.common.policies import base + +service_policies = [ + policy.RuleDefault( + name=base.IDENTITY % 'get_service', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'list_services', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'create_service', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'update_service', + check_str=base.RULE_ADMIN_REQUIRED), + policy.RuleDefault( + name=base.IDENTITY % 'delete_service', + check_str=base.RULE_ADMIN_REQUIRED) +] + + +def list_rules(): + return service_policies diff --git a/keystone/common/policy.py b/keystone/common/policy.py new file mode 100644 index 0000000000..4ec0a0f996 --- /dev/null +++ b/keystone/common/policy.py @@ -0,0 +1,67 @@ +# 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. + +from oslo_policy import policy as common_policy + +from keystone.common import policies +import keystone.conf +from keystone import exception + + +CONF = keystone.conf.CONF + + +_ENFORCER = None + + +def reset(): + global _ENFORCER + _ENFORCER = None + + +def init(): + global _ENFORCER + if not _ENFORCER: + _ENFORCER = common_policy.Enforcer(CONF) + register_rules(_ENFORCER) + + +def enforce(credentials, action, target, do_raise=True): + """Verify that the action is valid on the target in this context. + + :param credentials: user credentials + :param action: string representing the action to be checked, which should + be colon separated for clarity. + :param target: dictionary representing the object of the action for object + creation this should be a dictionary representing the + location of the object e.g. {'project_id': + object.project_id} + :raises keystone.exception.Forbidden: If verification fails. + + Actions should be colon separated for clarity. For example: + + * identity:list_users + + """ + init() + + # Add the exception arguments if asked to do a raise + extra = {} + if do_raise: + extra.update(exc=exception.ForbiddenAction, action=action, + do_raise=do_raise) + + return _ENFORCER.enforce(action, target, credentials, **extra) + + +def register_rules(enforcer): + enforcer.register_defaults(policies.list_rules()) diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py index c15de646aa..d60c411e99 100644 --- a/keystone/common/wsgi.py +++ b/keystone/common/wsgi.py @@ -37,6 +37,7 @@ import webob.exc from keystone.common import dependency from keystone.common import json_home +from keystone.common import policy from keystone.common import request as request_mod from keystone.common import utils import keystone.conf @@ -312,7 +313,7 @@ class Application(BaseApplication): creds['roles'] = user_token_ref.role_names # Accept either is_admin or the admin role - self.policy_api.enforce(creds, 'admin_required', {}) + policy.enforce(creds, 'admin_required', {}) def _attribute_is_empty(self, ref, attribute): """Determine if the attribute in ref is empty or None.""" diff --git a/keystone/policy/backends/rules.py b/keystone/policy/backends/rules.py index 36693f7a53..abf452caf4 100644 --- a/keystone/policy/backends/rules.py +++ b/keystone/policy/backends/rules.py @@ -16,8 +16,8 @@ """Policy engine for keystone.""" from oslo_log import log -from oslo_policy import policy as common_policy +from keystone.common import policy import keystone.conf from keystone import exception from keystone.policy.backends import base @@ -27,55 +27,13 @@ CONF = keystone.conf.CONF LOG = log.getLogger(__name__) -_ENFORCER = None - - -def reset(): - global _ENFORCER - _ENFORCER = None - - -def init(): - global _ENFORCER - if not _ENFORCER: - _ENFORCER = common_policy.Enforcer(CONF) - - -def enforce(credentials, action, target, do_raise=True): - """Verify that the action is valid on the target in this context. - - :param credentials: user credentials - :param action: string representing the action to be checked, which should - be colon separated for clarity. - :param target: dictionary representing the object of the action for object - creation this should be a dictionary representing the - location of the object e.g. {'project_id': - object.project_id} - :raises keystone.exception.Forbidden: If verification fails. - - Actions should be colon separated for clarity. For example: - - * identity:list_users - - """ - init() - - # Add the exception arguments if asked to do a raise - extra = {} - if do_raise: - extra.update(exc=exception.ForbiddenAction, action=action, - do_raise=do_raise) - - return _ENFORCER.enforce(action, target, credentials, **extra) - - class Policy(base.PolicyDriverBase): def enforce(self, credentials, action, target): msg = 'enforce %(action)s: %(credentials)s' LOG.debug(msg, { 'action': action, 'credentials': credentials}) - enforce(credentials, action, target) + policy.enforce(credentials, action, target) def create_policy(self, policy_id, policy): raise exception.NotImplemented() diff --git a/keystone/tests/unit/ksfixtures/policy.py b/keystone/tests/unit/ksfixtures/policy.py index b883f9805c..16aa0b77cb 100644 --- a/keystone/tests/unit/ksfixtures/policy.py +++ b/keystone/tests/unit/ksfixtures/policy.py @@ -14,7 +14,7 @@ import fixtures from oslo_policy import opts -from keystone.policy.backends import rules +from keystone.common import policy class Policy(fixtures.Fixture): @@ -29,5 +29,5 @@ class Policy(fixtures.Fixture): opts.set_defaults(self._config_fixture.conf) self._config_fixture.config(group='oslo_policy', policy_file=self._policy_file) - rules.init() - self.addCleanup(rules.reset) + policy.init() + self.addCleanup(policy.reset) diff --git a/keystone/tests/unit/test_policy.py b/keystone/tests/unit/test_policy.py index 435c972516..21b3dc3835 100644 --- a/keystone/tests/unit/test_policy.py +++ b/keystone/tests/unit/test_policy.py @@ -21,9 +21,10 @@ from oslo_policy import policy as common_policy import six from testtools import matchers +from keystone.common import policies +from keystone.common import policy import keystone.conf from keystone import exception -from keystone.policy.backends import rules from keystone.tests import unit from keystone.tests.unit import ksfixtures from keystone.tests.unit.ksfixtures import temporaryfile @@ -50,11 +51,11 @@ class PolicyFileTestCase(unit.TestCase): empty_credentials = {} with open(self.tmpfilename, "w") as policyfile: policyfile.write("""{"example:test": []}""") - rules.enforce(empty_credentials, action, self.target) + policy.enforce(empty_credentials, action, self.target) with open(self.tmpfilename, "w") as policyfile: policyfile.write("""{"example:test": ["false:false"]}""") - rules._ENFORCER.clear() - self.assertRaises(exception.ForbiddenAction, rules.enforce, + policy._ENFORCER.clear() + self.assertRaises(exception.ForbiddenAction, policy.enforce, empty_credentials, action, self.target) @@ -81,39 +82,39 @@ class PolicyTestCase(unit.TestCase): def _set_rules(self): these_rules = common_policy.Rules.from_dict(self.rules) - rules._ENFORCER.set_rules(these_rules) + policy._ENFORCER.set_rules(these_rules) def test_enforce_nonexistent_action_throws(self): action = "example:noexist" - self.assertRaises(exception.ForbiddenAction, rules.enforce, + self.assertRaises(exception.ForbiddenAction, policy.enforce, self.credentials, action, self.target) def test_enforce_bad_action_throws(self): action = "example:denied" - self.assertRaises(exception.ForbiddenAction, rules.enforce, + self.assertRaises(exception.ForbiddenAction, policy.enforce, self.credentials, action, self.target) def test_enforce_good_action(self): action = "example:allowed" - rules.enforce(self.credentials, action, self.target) + policy.enforce(self.credentials, action, self.target) def test_templatized_enforcement(self): target_mine = {'project_id': 'fake'} target_not_mine = {'project_id': 'another'} credentials = {'project_id': 'fake', 'roles': []} action = "example:my_file" - rules.enforce(credentials, action, target_mine) - self.assertRaises(exception.ForbiddenAction, rules.enforce, + policy.enforce(credentials, action, target_mine) + self.assertRaises(exception.ForbiddenAction, policy.enforce, credentials, action, target_not_mine) def test_early_AND_enforcement(self): action = "example:early_and_fail" - self.assertRaises(exception.ForbiddenAction, rules.enforce, + self.assertRaises(exception.ForbiddenAction, policy.enforce, self.credentials, action, self.target) def test_early_OR_enforcement(self): action = "example:early_or_success" - rules.enforce(self.credentials, action, self.target) + policy.enforce(self.credentials, action, self.target) def test_ignore_case_role_check(self): lowercase_action = "example:lowercase_admin" @@ -121,8 +122,8 @@ class PolicyTestCase(unit.TestCase): # NOTE(dprince): We mix case in the Admin role here to ensure # case is ignored admin_credentials = {'roles': ['AdMiN']} - rules.enforce(admin_credentials, lowercase_action, self.target) - rules.enforce(admin_credentials, uppercase_action, self.target) + policy.enforce(admin_credentials, lowercase_action, self.target) + policy.enforce(admin_credentials, uppercase_action, self.target) class DefaultPolicyTestCase(unit.TestCase): @@ -142,21 +143,21 @@ class DefaultPolicyTestCase(unit.TestCase): # monkeypatch load_roles() so it does nothing. This seem like a bug in # Oslo policy as we shouldn't have to reload the rules if they have # already been set using set_rules(). - self._old_load_rules = rules._ENFORCER.load_rules - self.addCleanup(setattr, rules._ENFORCER, 'load_rules', + self._old_load_rules = policy._ENFORCER.load_rules + self.addCleanup(setattr, policy._ENFORCER, 'load_rules', self._old_load_rules) - rules._ENFORCER.load_rules = lambda *args, **kwargs: None + policy._ENFORCER.load_rules = lambda *args, **kwargs: None def _set_rules(self, default_rule): these_rules = common_policy.Rules.from_dict(self.rules, default_rule) - rules._ENFORCER.set_rules(these_rules) + policy._ENFORCER.set_rules(these_rules) def test_policy_called(self): - self.assertRaises(exception.ForbiddenAction, rules.enforce, + self.assertRaises(exception.ForbiddenAction, policy.enforce, self.credentials, "example:exist", {}) def test_not_found_policy_calls_default(self): - rules.enforce(self.credentials, "example:noexist", {}) + policy.enforce(self.credentials, "example:noexist", {}) def test_default_not_found(self): new_default_rule = "default_noexist" @@ -164,9 +165,9 @@ class DefaultPolicyTestCase(unit.TestCase): # as it is recreating the rules with its own default_rule instead # of the default_rule passed in from set_rules(). I think this is a # bug in Oslo policy. - rules._ENFORCER.default_rule = new_default_rule + policy._ENFORCER.default_rule = new_default_rule self._set_rules(new_default_rule) - self.assertRaises(exception.ForbiddenAction, rules.enforce, + self.assertRaises(exception.ForbiddenAction, policy.enforce, self.credentials, "example:noexist", {}) @@ -175,6 +176,18 @@ class PolicyJsonTestCase(unit.TestCase): def _load_entries(self, filename): return set(json.load(open(filename))) + def _add_missing_default_rules(self, rules): + """Add default rules and their values to the given rules dict. + + The given rules dict may have an incomplete set of policy rules. + This method will add the default policy rules and their values to the + dict. It will not override the existing rules. This method is temporary + and is only needed until we move all policy.json rules into code. + """ + for rule in policies.list_rules(): + if rule.name not in rules: + rules[rule.name] = rule.check_str + def test_json_examples_have_matching_entries(self): policy_keys = self._load_entries(unit.dirs.etc('policy.json')) cloud_policy_keys = self._load_entries( @@ -202,9 +215,11 @@ class PolicyJsonTestCase(unit.TestCase): 'is_admin_project': True, 'project_id': None, 'domain_id': uuid.uuid4().hex} - standard_policy = unit.dirs.etc('policy.json') - enforcer = common_policy.Enforcer(CONF, policy_file=standard_policy) - result = enforcer.enforce(action, target, credentials) + # Since we are moving policy.json defaults to code, we instead call + # `policy.init()` which does the enforce setup for us with the added + # bonus of registering the in code default policies. + policy.init() + result = policy._ENFORCER.enforce(action, target, credentials) self.assertTrue(result) domain_policy = unit.dirs.etc('policy.v3cloudsample.json') @@ -215,8 +230,8 @@ class PolicyJsonTestCase(unit.TestCase): def test_all_targets_documented(self): # All the targets in the sample policy file must be documented in # doc/source/policy_mapping.rst. - - policy_keys = self._load_entries(unit.dirs.etc('policy.json')) + policy_keys = json.load(open((unit.dirs.etc('policy.json')))) + self._add_missing_default_rules(policy_keys) # These keys are in the policy.json but aren't targets. policy_rule_keys = [ diff --git a/keystone/tests/unit/test_v3_auth.py b/keystone/tests/unit/test_v3_auth.py index 0cd4492298..08bbfdf876 100644 --- a/keystone/tests/unit/test_v3_auth.py +++ b/keystone/tests/unit/test_v3_auth.py @@ -33,12 +33,12 @@ from testtools import testcase from keystone import auth from keystone.auth.plugins import totp +from keystone.common import policy from keystone.common import utils import keystone.conf from keystone.credential.providers import fernet as credential_fernet from keystone import exception from keystone.identity.backends import resource_options as ro -from keystone.policy.backends import rules from keystone.tests.common import auth as common_auth from keystone.tests import unit from keystone.tests.unit import ksfixtures @@ -4276,7 +4276,7 @@ class TrustAPIBehavior(test_v3.RestfulTestCase): self.chained_trust_ref['roles'] = [{'id': role['id']}] # Bypass policy enforcement - with mock.patch.object(rules, 'enforce', return_value=True): + with mock.patch.object(policy, 'enforce', return_value=True): self.post('/OS-TRUST/trusts', body={'trust': self.chained_trust_ref}, token=trust_token, @@ -4969,7 +4969,7 @@ class TestTrustChain(test_v3.RestfulTestCase): self.identity_api.update_user(disabled['id'], disabled) # Bypass policy enforcement - with mock.patch.object(rules, 'enforce', return_value=True): + with mock.patch.object(policy, 'enforce', return_value=True): headers = {'X-Subject-Token': self.last_token} self.head('/auth/tokens', headers=headers, expected_status=http_client.FORBIDDEN) @@ -4981,7 +4981,7 @@ class TestTrustChain(test_v3.RestfulTestCase): # Bypass policy enforcement # Delete trustee will invalidate the trust. - with mock.patch.object(rules, 'enforce', return_value=True): + with mock.patch.object(policy, 'enforce', return_value=True): headers = {'X-Subject-Token': self.last_token} self.head('/auth/tokens', headers=headers, expected_status=http_client.NOT_FOUND)