Makes policy.check aware of domain scoped token
This allows Domain Admin to also have a role on a Project(s). Supersedes: 196068 Partially Implements: blueprint domain-scoped-tokens Change-Id: Ia81e15a465117acf173c6459cec92838c825c460
This commit is contained in:
parent
dab1c9fdea
commit
b699a53867
@ -21,6 +21,7 @@ from oslo_config import cfg
|
||||
from oslo_policy import opts as policy_opts
|
||||
from oslo_policy import policy
|
||||
|
||||
from openstack_auth import user as auth_user
|
||||
from openstack_auth import utils as auth_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -123,37 +124,63 @@ def check(actions, request, target=None):
|
||||
# same for user_id
|
||||
if target.get('user_id') is None:
|
||||
target['user_id'] = user.id
|
||||
# same for domain_id
|
||||
if target.get('domain_id') is None:
|
||||
target['domain_id'] = user.domain_id
|
||||
|
||||
credentials = _user_to_credentials(request, user)
|
||||
domain_id_keys = [
|
||||
'domain_id',
|
||||
'project.domain_id',
|
||||
'user.domain_id',
|
||||
'group.domain_id'
|
||||
]
|
||||
# populates domain id keys with user's current domain id
|
||||
for key in domain_id_keys:
|
||||
if target.get(key) is None:
|
||||
target[key] = user.user_domain_id
|
||||
|
||||
credentials = _user_to_credentials(user)
|
||||
domain_credentials = _domain_to_credentials(request, user)
|
||||
# if there is a domain token use the domain_id instead of the user's domain
|
||||
if domain_credentials:
|
||||
credentials['domain_id'] = domain_credentials.get('domain_id')
|
||||
|
||||
enforcer = _get_enforcer()
|
||||
|
||||
for action in actions:
|
||||
scope, action = action[0], action[1]
|
||||
if scope in enforcer:
|
||||
# if any check fails return failure
|
||||
if not enforcer[scope].enforce(action, target, credentials):
|
||||
# to match service implementations, if a rule is not found,
|
||||
# use the default rule for that service policy
|
||||
#
|
||||
# waiting to make the check because the first call to
|
||||
# enforce loads the rules
|
||||
if action not in enforcer[scope].rules:
|
||||
if not enforcer[scope].enforce('default',
|
||||
target, credentials):
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
# this is for handling the v3 policy file and will only be
|
||||
# needed when a domain scoped token is present
|
||||
if scope == 'identity' and domain_credentials:
|
||||
# use domain credentials
|
||||
return _check_credentials(
|
||||
enforcer[scope], action, target, domain_credentials)
|
||||
|
||||
# use project credentials
|
||||
return _check_credentials(
|
||||
enforcer[scope], action, target, credentials)
|
||||
|
||||
# if no policy for scope, allow action, underlying API will
|
||||
# ultimately block the action if not permitted, treat as though
|
||||
# allowed
|
||||
return True
|
||||
|
||||
|
||||
def _user_to_credentials(request, user):
|
||||
def _check_credentials(enforcer_scope, action, target, credentials):
|
||||
is_valid = True
|
||||
if not enforcer_scope.enforce(action, target, credentials):
|
||||
# to match service implementations, if a rule is not found,
|
||||
# use the default rule for that service policy
|
||||
#
|
||||
# waiting to make the check because the first call to
|
||||
# enforce loads the rules
|
||||
if action not in enforcer_scope.rules:
|
||||
if not enforcer_scope.enforce('default', target, credentials):
|
||||
is_valid = False
|
||||
else:
|
||||
is_valid = False
|
||||
return is_valid
|
||||
|
||||
|
||||
def _user_to_credentials(user):
|
||||
if not hasattr(user, "_credentials"):
|
||||
roles = [role['name'] for role in user.roles]
|
||||
user._credentials = {'user_id': user.id,
|
||||
@ -165,3 +192,25 @@ def _user_to_credentials(request, user):
|
||||
'is_admin': user.is_superuser,
|
||||
'roles': roles}
|
||||
return user._credentials
|
||||
|
||||
|
||||
def _domain_to_credentials(request, user):
|
||||
if not hasattr(user, "_domain_credentials"):
|
||||
try:
|
||||
domain_auth_ref = request.session.get('domain_token')
|
||||
|
||||
# no domain role or not running on V3
|
||||
if not domain_auth_ref:
|
||||
return None
|
||||
domain_user = auth_user.create_user_from_token(
|
||||
request, auth_user.Token(domain_auth_ref),
|
||||
domain_auth_ref.service_catalog.url_for(endpoint_type=None))
|
||||
user._domain_credentials = _user_to_credentials(domain_user)
|
||||
|
||||
# uses the domain_id associated with the domain_user
|
||||
user._domain_credentials['domain_id'] = domain_user.domain_id
|
||||
|
||||
except Exception:
|
||||
LOG.error("Failed to create user from domain scoped token.")
|
||||
return None
|
||||
return user._domain_credentials
|
||||
|
195
openstack_auth/tests/conf/policy.v3cloudsample.json
Normal file
195
openstack_auth/tests/conf/policy.v3cloudsample.json
Normal file
@ -0,0 +1,195 @@
|
||||
{
|
||||
"admin_required": "role:admin",
|
||||
"cloud_admin": "rule:admin_required and domain_id:admin_domain_id",
|
||||
"service_role": "role:service",
|
||||
"service_or_admin": "rule:admin_required or rule:service_role",
|
||||
"owner" : "user_id:%(user_id)s or user_id:%(target.token.user_id)s",
|
||||
"admin_or_owner": "(rule:admin_required and domain_id:%(target.token.user.domain.id)s) or rule:owner",
|
||||
"admin_or_cloud_admin": "rule:admin_required or rule:cloud_admin",
|
||||
"admin_and_matching_domain_id": "rule:admin_required and domain_id:%(domain_id)s",
|
||||
"service_admin_or_owner": "rule:service_or_admin or rule:owner",
|
||||
|
||||
"default": "rule:admin_required",
|
||||
|
||||
"identity:get_region": "",
|
||||
"identity:list_regions": "",
|
||||
"identity:create_region": "rule:cloud_admin",
|
||||
"identity:update_region": "rule:cloud_admin",
|
||||
"identity:delete_region": "rule:cloud_admin",
|
||||
|
||||
"identity:get_service": "rule:admin_or_cloud_admin",
|
||||
"identity:list_services": "rule:admin_or_cloud_admin",
|
||||
"identity:create_service": "rule:cloud_admin",
|
||||
"identity:update_service": "rule:cloud_admin",
|
||||
"identity:delete_service": "rule:cloud_admin",
|
||||
|
||||
"identity:get_endpoint": "rule:admin_or_cloud_admin",
|
||||
"identity:list_endpoints": "rule:admin_or_cloud_admin",
|
||||
"identity:create_endpoint": "rule:cloud_admin",
|
||||
"identity:update_endpoint": "rule:cloud_admin",
|
||||
"identity:delete_endpoint": "rule:cloud_admin",
|
||||
|
||||
"identity:get_domain": "rule:cloud_admin or rule:admin_and_matching_domain_id",
|
||||
"identity:list_domains": "rule:cloud_admin",
|
||||
"identity:create_domain": "rule:cloud_admin",
|
||||
"identity:update_domain": "rule:cloud_admin",
|
||||
"identity:delete_domain": "rule:cloud_admin",
|
||||
|
||||
"admin_and_matching_target_project_domain_id": "rule:admin_required and domain_id:%(target.project.domain_id)s",
|
||||
"admin_and_matching_project_domain_id": "rule:admin_required and domain_id:%(project.domain_id)s",
|
||||
"identity:get_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
|
||||
"identity:list_projects": "rule:cloud_admin or rule:admin_and_matching_domain_id",
|
||||
"identity:list_user_projects": "rule:owner or rule:admin_and_matching_domain_id",
|
||||
"identity:create_project": "rule:cloud_admin or rule:admin_and_matching_project_domain_id",
|
||||
"identity:update_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
|
||||
"identity:delete_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
|
||||
|
||||
"admin_and_matching_target_user_domain_id": "rule:admin_required and domain_id:%(target.user.domain_id)s",
|
||||
"admin_and_matching_user_domain_id": "rule:admin_required and domain_id:%(user.domain_id)s",
|
||||
"identity:get_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
|
||||
"identity:list_users": "rule:cloud_admin or rule:admin_and_matching_domain_id",
|
||||
"identity:create_user": "rule:cloud_admin or rule:admin_and_matching_user_domain_id",
|
||||
"identity:update_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
|
||||
"identity:delete_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
|
||||
|
||||
"admin_and_matching_target_group_domain_id": "rule:admin_required and domain_id:%(target.group.domain_id)s",
|
||||
"admin_and_matching_group_domain_id": "rule:admin_required and domain_id:%(group.domain_id)s",
|
||||
"identity:get_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
"identity:list_groups": "rule:cloud_admin or rule:admin_and_matching_domain_id",
|
||||
"identity:list_groups_for_user": "rule:owner or rule:admin_and_matching_domain_id",
|
||||
"identity:create_group": "rule:cloud_admin or rule:admin_and_matching_group_domain_id",
|
||||
"identity:update_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
"identity:delete_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
"identity:list_users_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
"identity:remove_user_from_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
"identity:check_user_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
"identity:add_user_to_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
|
||||
|
||||
"identity:get_credential": "rule:admin_required",
|
||||
"identity:list_credentials": "rule:admin_required or user_id:%(user_id)s",
|
||||
"identity:create_credential": "rule:admin_required",
|
||||
"identity:update_credential": "rule:admin_required",
|
||||
"identity:delete_credential": "rule:admin_required",
|
||||
|
||||
"identity:ec2_get_credential": "rule:admin_or_cloud_admin or (rule:owner and user_id:%(target.credential.user_id)s)",
|
||||
"identity:ec2_list_credentials": "rule:admin_or_cloud_admin or rule:owner",
|
||||
"identity:ec2_create_credential": "rule:admin_or_cloud_admin or rule:owner",
|
||||
"identity:ec2_delete_credential": "rule:admin_or_cloud_admin or (rule:owner and user_id:%(target.credential.user_id)s)",
|
||||
|
||||
"identity:get_role": "rule:admin_or_cloud_admin",
|
||||
"identity:list_roles": "rule:admin_or_cloud_admin",
|
||||
"identity:create_role": "rule:cloud_admin",
|
||||
"identity:update_role": "rule:cloud_admin",
|
||||
"identity:delete_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:list_grants": "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",
|
||||
|
||||
"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",
|
||||
"identity:list_role_assignments": "rule:cloud_admin or rule:admin_on_domain_filter or rule:admin_on_project_filter",
|
||||
|
||||
"identity:get_policy": "rule:cloud_admin",
|
||||
"identity:list_policies": "rule:cloud_admin",
|
||||
"identity:create_policy": "rule:cloud_admin",
|
||||
"identity:update_policy": "rule:cloud_admin",
|
||||
"identity:delete_policy": "rule:cloud_admin",
|
||||
|
||||
"identity:change_password": "rule:owner",
|
||||
"identity:check_token": "rule:admin_or_owner",
|
||||
"identity:validate_token": "rule:service_admin_or_owner",
|
||||
"identity:validate_token_head": "rule:service_or_admin",
|
||||
"identity:revocation_list": "rule:service_or_admin",
|
||||
"identity:revoke_token": "rule:admin_or_owner",
|
||||
|
||||
"identity:create_trust": "user_id:%(trust.trustor_user_id)s",
|
||||
"identity:list_trusts": "",
|
||||
"identity:list_roles_for_trust": "",
|
||||
"identity:get_role_for_trust": "",
|
||||
"identity:delete_trust": "",
|
||||
|
||||
"identity:create_consumer": "rule:admin_required",
|
||||
"identity:get_consumer": "rule:admin_required",
|
||||
"identity:list_consumers": "rule:admin_required",
|
||||
"identity:delete_consumer": "rule:admin_required",
|
||||
"identity:update_consumer": "rule:admin_required",
|
||||
|
||||
"identity:authorize_request_token": "rule:admin_required",
|
||||
"identity:list_access_token_roles": "rule:admin_required",
|
||||
"identity:get_access_token_role": "rule:admin_required",
|
||||
"identity:list_access_tokens": "rule:admin_required",
|
||||
"identity:get_access_token": "rule:admin_required",
|
||||
"identity:delete_access_token": "rule:admin_required",
|
||||
|
||||
"identity:list_projects_for_endpoint": "rule:admin_required",
|
||||
"identity:add_endpoint_to_project": "rule:admin_required",
|
||||
"identity:check_endpoint_in_project": "rule:admin_required",
|
||||
"identity:list_endpoints_for_project": "rule:admin_required",
|
||||
"identity:remove_endpoint_from_project": "rule:admin_required",
|
||||
|
||||
"identity:create_endpoint_group": "rule:admin_required",
|
||||
"identity:list_endpoint_groups": "rule:admin_required",
|
||||
"identity:get_endpoint_group": "rule:admin_required",
|
||||
"identity:update_endpoint_group": "rule:admin_required",
|
||||
"identity:delete_endpoint_group": "rule:admin_required",
|
||||
"identity:list_projects_associated_with_endpoint_group": "rule:admin_required",
|
||||
"identity:list_endpoints_associated_with_endpoint_group": "rule:admin_required",
|
||||
"identity:get_endpoint_group_in_project": "rule:admin_required",
|
||||
"identity:list_endpoint_groups_for_project": "rule:admin_required",
|
||||
"identity:add_endpoint_group_to_project": "rule:admin_required",
|
||||
"identity:remove_endpoint_group_from_project": "rule:admin_required",
|
||||
|
||||
"identity:create_identity_provider": "rule:cloud_admin",
|
||||
"identity:list_identity_providers": "rule:cloud_admin",
|
||||
"identity:get_identity_providers": "rule:cloud_admin",
|
||||
"identity:update_identity_provider": "rule:cloud_admin",
|
||||
"identity:delete_identity_provider": "rule:cloud_admin",
|
||||
|
||||
"identity:create_protocol": "rule:cloud_admin",
|
||||
"identity:update_protocol": "rule:cloud_admin",
|
||||
"identity:get_protocol": "rule:cloud_admin",
|
||||
"identity:list_protocols": "rule:cloud_admin",
|
||||
"identity:delete_protocol": "rule:cloud_admin",
|
||||
|
||||
"identity:create_mapping": "rule:cloud_admin",
|
||||
"identity:get_mapping": "rule:cloud_admin",
|
||||
"identity:list_mappings": "rule:cloud_admin",
|
||||
"identity:delete_mapping": "rule:cloud_admin",
|
||||
"identity:update_mapping": "rule:cloud_admin",
|
||||
|
||||
"identity:create_service_provider": "rule:cloud_admin",
|
||||
"identity:list_service_providers": "rule:cloud_admin",
|
||||
"identity:get_service_provider": "rule:cloud_admin",
|
||||
"identity:update_service_provider": "rule:cloud_admin",
|
||||
"identity:delete_service_provider": "rule:cloud_admin",
|
||||
|
||||
"identity:get_auth_catalog": "",
|
||||
"identity:get_auth_projects": "",
|
||||
"identity:get_auth_domains": "",
|
||||
|
||||
"identity:list_projects_for_groups": "",
|
||||
"identity:list_domains_for_groups": "",
|
||||
|
||||
"identity:list_revoke_events": "",
|
||||
|
||||
"identity:create_policy_association_for_endpoint": "rule:cloud_admin",
|
||||
"identity:check_policy_association_for_endpoint": "rule:cloud_admin",
|
||||
"identity:delete_policy_association_for_endpoint": "rule:cloud_admin",
|
||||
"identity:create_policy_association_for_service": "rule:cloud_admin",
|
||||
"identity:check_policy_association_for_service": "rule:cloud_admin",
|
||||
"identity:delete_policy_association_for_service": "rule:cloud_admin",
|
||||
"identity:create_policy_association_for_region_and_service": "rule:cloud_admin",
|
||||
"identity:check_policy_association_for_region_and_service": "rule:cloud_admin",
|
||||
"identity:delete_policy_association_for_region_and_service": "rule:cloud_admin",
|
||||
"identity:get_policy_for_endpoint": "rule:cloud_admin",
|
||||
"identity:list_endpoints_for_policy": "rule:cloud_admin",
|
||||
|
||||
"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"
|
||||
}
|
@ -1094,3 +1094,43 @@ class PolicyTestCaseAdmin(PolicyTestCase):
|
||||
value = policy.check((("compute", "context_is_admin"),),
|
||||
request=self.request)
|
||||
self.assertTrue(value)
|
||||
|
||||
|
||||
class PolicyTestCaseV3Admin(PolicyTestCase):
|
||||
_roles = [{'id': '1', 'name': 'admin'}]
|
||||
|
||||
def setUp(self):
|
||||
policy_files = {
|
||||
'identity': 'policy.v3cloudsample.json',
|
||||
'compute': 'nova_policy.json'}
|
||||
|
||||
override = self.settings(POLICY_FILES=policy_files)
|
||||
override.enable()
|
||||
self.addCleanup(override.disable)
|
||||
|
||||
mock_user = user.User(id=1, roles=self._roles,
|
||||
user_domain_id='admin_domain_id')
|
||||
patcher = mock.patch('openstack_auth.utils.get_user',
|
||||
return_value=mock_user)
|
||||
self.MockClass = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
self.request = http.HttpRequest()
|
||||
|
||||
def test_check_cloud_admin_required_true(self):
|
||||
policy.reset()
|
||||
value = policy.check((("identity", "cloud_admin"),),
|
||||
request=self.request)
|
||||
self.assertTrue(value)
|
||||
|
||||
def test_check_domain_admin_required_true(self):
|
||||
policy.reset()
|
||||
value = policy.check((
|
||||
("identity", "admin_and_matching_domain_id"),),
|
||||
request=self.request)
|
||||
self.assertTrue(value)
|
||||
|
||||
def test_check_any_admin_required_true(self):
|
||||
policy.reset()
|
||||
value = policy.check((("identity", "admin_or_cloud_admin"),),
|
||||
request=self.request)
|
||||
self.assertTrue(value)
|
||||
|
Loading…
Reference in New Issue
Block a user