diff options
author | Jenkins <jenkins@review.openstack.org> | 2013-05-30 05:05:48 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2013-05-30 05:05:48 +0000 |
commit | 6d33805d0fe7fd7bd75765ee4167eb64fbdd324b (patch) | |
tree | 109952b6569d4aa3e7db02af3eb60f7de2516713 | |
parent | d67e31b70ca648c8ca0a3cb76f421b3be257d4c5 (diff) | |
parent | 3c3f5dc8973a28fcded50bdb65b7cd77cd772cc6 (diff) | |
download | keystone-6d33805d0fe7fd7bd75765ee4167eb64fbdd324b.tar.gz keystone-6d33805d0fe7fd7bd75765ee4167eb64fbdd324b.tar.xz keystone-6d33805d0fe7fd7bd75765ee4167eb64fbdd324b.zip |
Merge "Move auth_token middleware from admin user to an RBAC policy"
-rw-r--r-- | etc/policy.json | 7 | ||||
-rw-r--r-- | keystone/common/controller.py | 4 | ||||
-rw-r--r-- | keystone/token/controllers.py | 8 | ||||
-rw-r--r-- | tests/default_fixtures.py | 10 | ||||
-rw-r--r-- | tests/test_backend.py | 2 | ||||
-rw-r--r-- | tests/test_content_types.py | 18 |
6 files changed, 37 insertions, 12 deletions
diff --git a/etc/policy.json b/etc/policy.json index f53161ef..fcad7a93 100644 --- a/etc/policy.json +++ b/etc/policy.json @@ -1,5 +1,7 @@ { "admin_required": [["role:admin"], ["is_admin:1"]], + "service_role": [["role:service"]], + "service_or_admin": [["rule:admin_required"], ["rule:service_role"]], "owner" : [["user_id:%(user_id)s"]], "admin_or_owner": [["rule:admin_required"], ["rule:owner"]], @@ -71,8 +73,9 @@ "identity:delete_policy": [["rule:admin_required"]], "identity:check_token": [["rule:admin_required"]], - "identity:validate_token": [["rule:admin_required"]], - "identity:revocation_list": [["rule:admin_required"]], + "identity:validate_token": [["rule:service_or_admin"]], + "identity:validate_token_head": [["rule:service_or_admin"]], + "identity:revocation_list": [["rule:service_or_admin"]], "identity:revoke_token": [["rule:admin_required"], ["user_id:%(user_id)s"]], diff --git a/keystone/common/controller.py b/keystone/common/controller.py index 9c28f081..3452f85e 100644 --- a/keystone/common/controller.py +++ b/keystone/common/controller.py @@ -87,7 +87,7 @@ def flatten(d, parent_key=''): def protected(f): """Wraps API calls with role based access controls (RBAC).""" @functools.wraps(f) - def wrapper(self, context, **kwargs): + def wrapper(self, context, *args, **kwargs): if 'is_admin' in context and context['is_admin']: LOG.warning(_('RBAC: Bypassing authorization')) else: @@ -100,7 +100,7 @@ def protected(f): self.policy_api.enforce(context, creds, action, flatten(kwargs)) LOG.debug(_('RBAC: Authorization granted')) - return f(self, context, **kwargs) + return f(self, context, *args, **kwargs) return wrapper diff --git a/keystone/token/controllers.py b/keystone/token/controllers.py index a7fcbb2c..2d429742 100644 --- a/keystone/token/controllers.py +++ b/keystone/token/controllers.py @@ -457,8 +457,6 @@ class Auth(controller.V2Controller): Optionally, limited to a token owned by a specific tenant. """ - # TODO(termie): this stuff should probably be moved to middleware - self.assert_admin(context) data = self.token_api.get_token(context=context, token_id=token_id) if belongs_to: @@ -510,7 +508,7 @@ class Auth(controller.V2Controller): if project_ref['domain_id'] != DEFAULT_DOMAIN_ID: raise exception.Unauthorized(msg) - # admin only + @controller.protected def validate_token_head(self, context, token_id): """Check that a token is valid. @@ -524,7 +522,7 @@ class Auth(controller.V2Controller): assert token_ref self._assert_default_domain(context, token_ref) - # admin only + @controller.protected def validate_token(self, context, token_id): """Check that a token is valid. @@ -562,8 +560,8 @@ class Auth(controller.V2Controller): self.assert_admin(context) self.token_api.delete_token(context=context, token_id=token_id) + @controller.protected def revocation_list(self, context, auth=None): - self.assert_admin(context) tokens = self.token_api.list_revoked_tokens(context) for t in tokens: diff --git a/tests/default_fixtures.py b/tests/default_fixtures.py index 3a1379ed..256bb4b7 100644 --- a/tests/default_fixtures.py +++ b/tests/default_fixtures.py @@ -45,6 +45,12 @@ TENANTS = [ 'description': 'description', 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID + }, { + 'id': 'service', + 'name': 'service', + 'description': 'description', + 'enabled': True, + 'domain_id': DEFAULT_DOMAIN_ID } ] @@ -115,8 +121,12 @@ ROLES = [ }, { 'id': 'writer', 'name': 'Writer', + }, { + 'id': 'service', + 'name': 'Service', } + ] DOMAINS = [ diff --git a/tests/test_backend.py b/tests/test_backend.py index 5665fa54..717535c7 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1619,7 +1619,7 @@ class IdentityTests(object): def test_list_projects(self): projects = self.identity_api.list_projects() - self.assertEquals(len(projects), 3) + self.assertEquals(len(projects), 4) project_ids = [] for project in projects: project_ids.append(project.get('id')) diff --git a/tests/test_content_types.py b/tests/test_content_types.py index 95a78ab0..e5bdc56a 100644 --- a/tests/test_content_types.py +++ b/tests/test_content_types.py @@ -214,8 +214,10 @@ class RestfulTestCase(test.TestCase): def admin_request(self, **kwargs): return self._request(app=self.admin_app, **kwargs) - def get_scoped_token(self): + def get_scoped_token(self, tenant_id=None): """Convenience method so that we can test authenticated requests.""" + if not tenant_id: + tenant_id = self.tenant_bar['id'] r = self.public_request( method='POST', path='/v2.0/tokens', @@ -225,7 +227,7 @@ class RestfulTestCase(test.TestCase): 'username': self.user_foo['name'], 'password': self.user_foo['password'], }, - 'tenantId': self.tenant_bar['id'], + 'tenantId': tenant_id, }, }) return self._get_token_id(r) @@ -387,6 +389,18 @@ class CoreApiTests(object): token=token) self.assertValidAuthenticationResponse(r) + def test_validate_token_service_role(self): + self.metadata_foobar = self.identity_api.update_metadata( + self.user_foo['id'], + self.tenant_service['id'], + dict(roles=[self.role_service['id']])) + + token = self.get_scoped_token(tenant_id='service') + r = self.admin_request( + path='/v2.0/tokens/%s' % token, + token=token) + self.assertValidAuthenticationResponse(r) + def test_validate_token_belongs_to(self): token = self.get_scoped_token() path = ('/v2.0/tokens/%s?belongsTo=%s' % (token, |