diff --git a/keystone/common/policies/policy.py b/keystone/common/policies/policy.py index e3dffbc50f..b5163f975a 100644 --- a/keystone/common/policies/policy.py +++ b/keystone/common/policies/policy.py @@ -25,6 +25,20 @@ deprecated_list_policies = policy.DeprecatedRule( check_str=base.RULE_ADMIN_REQUIRED, ) +deprecated_update_policy = policy.DeprecatedRule( + name=base.IDENTITY % 'update_policy', + check_str=base.RULE_ADMIN_REQUIRED, +) + +deprecated_create_policy = policy.DeprecatedRule( + name=base.IDENTITY % 'create_policy', + check_str=base.RULE_ADMIN_REQUIRED, +) + +deprecated_delete_policy = policy.DeprecatedRule( + name=base.IDENTITY % 'delete_policy', + check_str=base.RULE_ADMIN_REQUIRED, +) DEPRECATED_REASON = """ As of the Train release, the policy API now understands default roles and @@ -60,25 +74,34 @@ policy_policies = [ deprecated_since=versionutils.deprecated.TRAIN), policy.DocumentedRuleDefault( name=base.IDENTITY % 'create_policy', - check_str=base.RULE_ADMIN_REQUIRED, + check_str=base.SYSTEM_ADMIN, scope_types=['system'], description='Create policy.', operations=[{'path': '/v3/policies', - 'method': 'POST'}]), + 'method': 'POST'}], + deprecated_rule=deprecated_create_policy, + deprecated_reason=DEPRECATED_REASON, + deprecated_since=versionutils.deprecated.TRAIN), policy.DocumentedRuleDefault( name=base.IDENTITY % 'update_policy', - check_str=base.RULE_ADMIN_REQUIRED, + check_str=base.SYSTEM_ADMIN, scope_types=['system'], description='Update policy.', operations=[{'path': '/v3/policies/{policy_id}', - 'method': 'PATCH'}]), + 'method': 'PATCH'}], + deprecated_rule=deprecated_update_policy, + deprecated_reason=DEPRECATED_REASON, + deprecated_since=versionutils.deprecated.TRAIN), policy.DocumentedRuleDefault( name=base.IDENTITY % 'delete_policy', - check_str=base.RULE_ADMIN_REQUIRED, + check_str=base.SYSTEM_ADMIN, scope_types=['system'], description='Delete policy.', operations=[{'path': '/v3/policies/{policy_id}', - 'method': 'DELETE'}]) + 'method': 'DELETE'}], + deprecated_rule=deprecated_delete_policy, + deprecated_reason=DEPRECATED_REASON, + deprecated_since=versionutils.deprecated.TRAIN) ] diff --git a/keystone/tests/unit/protection/v3/test_policy.py b/keystone/tests/unit/protection/v3/test_policy.py index da3620f6e4..1479941237 100644 --- a/keystone/tests/unit/protection/v3/test_policy.py +++ b/keystone/tests/unit/protection/v3/test_policy.py @@ -159,3 +159,68 @@ class SystemMemberTests(base_classes.TestCaseWithBootstrap, r = c.post('/v3/auth/tokens', json=auth) self.token_id = r.headers['X-Subject-Token'] self.headers = {'X-Auth-Token': self.token_id} + + +class SystemAdminTests(base_classes.TestCaseWithBootstrap, + common_auth.AuthTestMixin, + _SystemUserPoliciesTests): + + def setUp(self): + super(SystemAdminTests, self).setUp() + self.loadapp() + self.useFixture(ksfixtures.Policy(self.config_fixture)) + self.config_fixture.config(group='oslo_policy', enforce_scope=True) + + # Reuse the system administrator account created during + # ``keystone-manage bootstrap`` + self.user_id = self.bootstrapper.admin_user_id + auth = self.build_authentication_request( + user_id=self.user_id, + password=self.bootstrapper.admin_password, + system=True + ) + + # Grab a token using the persona we're testing and prepare headers + # for requests we'll be making in the tests. + with self.test_client() as c: + r = c.post('/v3/auth/tokens', json=auth) + self.token_id = r.headers['X-Subject-Token'] + self.headers = {'X-Auth-Token': self.token_id} + + def test_user_can_create_policy(self): + create = { + 'policy': { + 'id': uuid.uuid4().hex, + 'name': uuid.uuid4().hex, + 'description': uuid.uuid4().hex, + 'enabled': True, + # Store serialized JSON data as the blob to mimic real world usage. + 'blob': json.dumps({'data': uuid.uuid4().hex, }), + 'type': uuid.uuid4().hex + } + } + with self.test_client() as c: + c.post( + '/v3/policies', json=create, headers=self.headers + ) + + def test_user_can_update_policy(self): + policy = unit.new_policy_ref() + policy = PROVIDERS.policy_api.create_policy(policy['id'], policy) + + update = {'policy': {'name': uuid.uuid4().hex}} + + with self.test_client() as c: + c.patch( + '/v3/policies/%s' % policy['id'], json=update, + headers=self.headers + ) + + def test_user_can_delete_policy(self): + policy = unit.new_policy_ref() + policy = PROVIDERS.policy_api.create_policy(policy['id'], policy) + + with self.test_client() as c: + c.delete( + '/v3/policies/%s' % policy['id'], headers=self.headers + )