Merge "Modify rules for domain specific role assignments"
This commit is contained in:
commit
695ea9a857
|
@ -101,13 +101,20 @@
|
||||||
"identity:list_role_inference_rules": "rule:cloud_admin",
|
"identity:list_role_inference_rules": "rule:cloud_admin",
|
||||||
"identity:check_implied_role": "rule:cloud_admin",
|
"identity:check_implied_role": "rule:cloud_admin",
|
||||||
|
|
||||||
"domain_admin_for_grants": "rule:admin_required and (domain_id:%(domain_id)s or domain_id:%(target.project.domain_id)s)",
|
|
||||||
"project_admin_for_grants": "rule:admin_required and project_id:%(project_id)s",
|
|
||||||
"identity:check_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
"identity:check_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
||||||
"identity:list_grants": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
"identity:list_grants": "rule:cloud_admin or rule:domain_admin_for_list_grants or rule:project_admin_for_list_grants",
|
||||||
"identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
"identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
||||||
"identity:revoke_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
"identity:revoke_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
|
||||||
|
"domain_admin_for_grants": "rule:domain_admin_for_global_role_grants or rule:domain_admin_for_domain_role_grants",
|
||||||
|
"domain_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and rule:domain_admin_grant_match",
|
||||||
|
"domain_admin_for_domain_role_grants": "rule:admin_required and domain_id:%(target.role.domain_id)s and rule:domain_admin_grant_match",
|
||||||
|
"domain_admin_grant_match": "domain_id:%(domain_id)s or domain_id:%(target.project.domain_id)s",
|
||||||
|
"project_admin_for_grants": "rule:project_admin_for_global_role_grants or rule:project_admin_for_domain_role_grants",
|
||||||
|
"project_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and project_id:%(project_id)s",
|
||||||
|
"project_admin_for_domain_role_grants": "rule:admin_required and project_domain_id:%(target.role.domain_id)s and project_id:%(project_id)s",
|
||||||
|
"domain_admin_for_list_grants": "rule:admin_required and rule:domain_admin_grant_match",
|
||||||
|
"project_admin_for_list_grants": "rule:admin_required and project_id:%(project_id)s",
|
||||||
|
|
||||||
"admin_on_domain_filter" : "rule:admin_required and domain_id:%(scope.domain.id)s",
|
"admin_on_domain_filter" : "rule:admin_required and domain_id:%(scope.domain.id)s",
|
||||||
"admin_on_project_filter" : "rule:admin_required and project_id:%(scope.project.id)s",
|
"admin_on_project_filter" : "rule:admin_required and project_id:%(scope.project.id)s",
|
||||||
"admin_on_domain_of_project_filter" : "rule:admin_required and domain_id:%(target.project.domain_id)s",
|
"admin_on_domain_of_project_filter" : "rule:admin_required and domain_id:%(target.project.domain_id)s",
|
||||||
|
|
|
@ -735,9 +735,10 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
|
||||||
self.post('/domains', auth=self.auth, body={'domain': domain_ref},
|
self.post('/domains', auth=self.auth, body={'domain': domain_ref},
|
||||||
expected_status=status_created)
|
expected_status=status_created)
|
||||||
|
|
||||||
def _test_grants(self, target, entity_id, expected=None):
|
def _test_grants(self, target, entity_id, role_domain_id=None,
|
||||||
|
list_status_OK=False, expected=None):
|
||||||
status_OK, status_created, status_no_data = self._stati(expected)
|
status_OK, status_created, status_no_data = self._stati(expected)
|
||||||
a_role = unit.new_role_ref()
|
a_role = unit.new_role_ref(domain_id=role_domain_id)
|
||||||
self.role_api.create_role(a_role['id'], a_role)
|
self.role_api.create_role(a_role['id'], a_role)
|
||||||
|
|
||||||
collection_url = (
|
collection_url = (
|
||||||
|
@ -753,8 +754,11 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
|
||||||
expected_status=status_no_data)
|
expected_status=status_no_data)
|
||||||
self.head(member_url, auth=self.auth,
|
self.head(member_url, auth=self.auth,
|
||||||
expected_status=status_no_data)
|
expected_status=status_no_data)
|
||||||
self.get(collection_url, auth=self.auth,
|
if list_status_OK:
|
||||||
expected_status=status_OK)
|
self.get(collection_url, auth=self.auth)
|
||||||
|
else:
|
||||||
|
self.get(collection_url, auth=self.auth,
|
||||||
|
expected_status=status_OK)
|
||||||
self.delete(member_url, auth=self.auth,
|
self.delete(member_url, auth=self.auth,
|
||||||
expected_status=status_no_data)
|
expected_status=status_no_data)
|
||||||
|
|
||||||
|
@ -983,6 +987,52 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
|
||||||
|
|
||||||
self._test_grants('domains', self.domainA['id'])
|
self._test_grants('domains', self.domainA['id'])
|
||||||
|
|
||||||
|
def test_domain_grants_by_cloud_admin_for_domain_specific_role(self):
|
||||||
|
# Test domain grants with a cloud admin. This user should be
|
||||||
|
# able to manage domain roles on any domain.
|
||||||
|
self.auth = self.build_authentication_request(
|
||||||
|
user_id=self.cloud_admin_user['id'],
|
||||||
|
password=self.cloud_admin_user['password'],
|
||||||
|
project_id=self.admin_project['id'])
|
||||||
|
|
||||||
|
self._test_grants('domains', self.domainA['id'],
|
||||||
|
role_domain_id=self.domainB['id'])
|
||||||
|
|
||||||
|
def test_domain_grants_by_non_admin_for_domain_specific_role(self):
|
||||||
|
# A non-admin shouldn't be able to do anything
|
||||||
|
self.auth = self.build_authentication_request(
|
||||||
|
user_id=self.just_a_user['id'],
|
||||||
|
password=self.just_a_user['password'],
|
||||||
|
domain_id=self.domainA['id'])
|
||||||
|
|
||||||
|
self._test_grants('domains', self.domainA['id'],
|
||||||
|
role_domain_id=self.domainA['id'],
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
self._test_grants('domains', self.domainA['id'],
|
||||||
|
role_domain_id=self.domainB['id'],
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
|
||||||
|
def test_domain_grants_by_domain_admin_for_domain_specific_role(self):
|
||||||
|
# Authenticate with a user that does have the domain admin role,
|
||||||
|
# should not be able to assign a domain_specific role from another
|
||||||
|
# domain
|
||||||
|
self.auth = self.build_authentication_request(
|
||||||
|
user_id=self.domain_admin_user['id'],
|
||||||
|
password=self.domain_admin_user['password'],
|
||||||
|
domain_id=self.domainA['id'])
|
||||||
|
|
||||||
|
self._test_grants('domains', self.domainA['id'],
|
||||||
|
role_domain_id=self.domainB['id'],
|
||||||
|
# List status will always be OK, since we are not
|
||||||
|
# granting/checking/deleting assignments
|
||||||
|
list_status_OK=True,
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
|
||||||
|
# They should be able to assign a domain specific role from the same
|
||||||
|
# domain
|
||||||
|
self._test_grants('domains', self.domainA['id'],
|
||||||
|
role_domain_id=self.domainA['id'])
|
||||||
|
|
||||||
def test_project_grants(self):
|
def test_project_grants(self):
|
||||||
self.auth = self.build_authentication_request(
|
self.auth = self.build_authentication_request(
|
||||||
user_id=self.just_a_user['id'],
|
user_id=self.just_a_user['id'],
|
||||||
|
@ -1011,6 +1061,62 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
|
||||||
|
|
||||||
self._test_grants('projects', self.project['id'])
|
self._test_grants('projects', self.project['id'])
|
||||||
|
|
||||||
|
def test_project_grants_by_non_admin_for_domain_specific_role(self):
|
||||||
|
# A non-admin shouldn't be able to do anything
|
||||||
|
self.auth = self.build_authentication_request(
|
||||||
|
user_id=self.just_a_user['id'],
|
||||||
|
password=self.just_a_user['password'],
|
||||||
|
project_id=self.project['id'])
|
||||||
|
|
||||||
|
self._test_grants('projects', self.project['id'],
|
||||||
|
role_domain_id=self.domainA['id'],
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
self._test_grants('projects', self.project['id'],
|
||||||
|
role_domain_id=self.domainB['id'],
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
|
||||||
|
def test_project_grants_by_project_admin_for_domain_specific_role(self):
|
||||||
|
# Authenticate with a user that does have the project admin role,
|
||||||
|
# should not be able to assign a domain_specific role from another
|
||||||
|
# domain
|
||||||
|
self.auth = self.build_authentication_request(
|
||||||
|
user_id=self.project_admin_user['id'],
|
||||||
|
password=self.project_admin_user['password'],
|
||||||
|
project_id=self.project['id'])
|
||||||
|
|
||||||
|
self._test_grants('projects', self.project['id'],
|
||||||
|
role_domain_id=self.domainB['id'],
|
||||||
|
# List status will always be OK, since we are not
|
||||||
|
# granting/checking/deleting assignments
|
||||||
|
list_status_OK=True,
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
|
||||||
|
# They should be able to assign a domain specific role from the same
|
||||||
|
# domain
|
||||||
|
self._test_grants('projects', self.project['id'],
|
||||||
|
role_domain_id=self.domainA['id'])
|
||||||
|
|
||||||
|
def test_project_grants_by_domain_admin_for_domain_specific_role(self):
|
||||||
|
# Authenticate with a user that does have the domain admin role,
|
||||||
|
# should not be able to assign a domain_specific role from another
|
||||||
|
# domain
|
||||||
|
self.auth = self.build_authentication_request(
|
||||||
|
user_id=self.domain_admin_user['id'],
|
||||||
|
password=self.domain_admin_user['password'],
|
||||||
|
domain_id=self.domainA['id'])
|
||||||
|
|
||||||
|
self._test_grants('projects', self.project['id'],
|
||||||
|
role_domain_id=self.domainB['id'],
|
||||||
|
# List status will always be OK, since we are not
|
||||||
|
# granting/checking/deleting assignments
|
||||||
|
list_status_OK=True,
|
||||||
|
expected=exception.ForbiddenAction.code)
|
||||||
|
|
||||||
|
# They should be able to assign a domain specific role from the same
|
||||||
|
# domain
|
||||||
|
self._test_grants('projects', self.project['id'],
|
||||||
|
role_domain_id=self.domainA['id'])
|
||||||
|
|
||||||
def test_cloud_admin_list_assignments_of_domain(self):
|
def test_cloud_admin_list_assignments_of_domain(self):
|
||||||
self.auth = self.build_authentication_request(
|
self.auth = self.build_authentication_request(
|
||||||
user_id=self.cloud_admin_user['id'],
|
user_id=self.cloud_admin_user['id'],
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- >
|
||||||
|
[`blueprint domain-specific-roles <https://blueprints.launchpad.net/keystone/+spec/domain-specific-roles>`_]
|
||||||
|
Roles can now be optionally defined as domain specific. Domain specific
|
||||||
|
roles are not references in policy files, rather they can be used to allow
|
||||||
|
a domain to build their own private inference rules with implies roles. A
|
||||||
|
domain specific role can be assigned to a domain or project within its
|
||||||
|
domain, and any subset of global roles it implies will appear in a token
|
||||||
|
scoped to the respective domain or project. The domain specific role
|
||||||
|
itself, however, will not appear in the token.
|
Loading…
Reference in New Issue