Normalize policy checks for domain-scoped tokens

This patch fixes an inconsistency in the policies for role_assignment
where the target object used for policy enforcement was being created
with different properties depending on the request query string.

This required policies to be written in two differnt ways to validate
domain IDs for domain-scoped requests.  e.g. checking for domain reader
was using both:

    role:reader and domain_id:%(target.domain_id)s

and

    role:reader and domain_id:%(target.project.domain_id)s

With the former only being populated for GET /v3/role_assignments and
the latter only being populated for GET
/v3/role_assignments?scope.project.id=SOME_ID

This patch fixes the target object so that only target.domain_id needs
to be checked for domain-scoped tokens.

Change-Id: Iffbe11c57c61bbd1b045a6567a9249c12dff403c
This commit is contained in:
Douglas Mendizábal 2024-02-08 14:36:38 -06:00
parent db0ff10476
commit 7dc175a41f

View File

@ -51,6 +51,12 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
]
target = None
if self.oslo_context.domain_id:
# NOTE(dmendiza): Normally we want the target dict to contain
# information about the target entity, not information from the
# context. In this case, however, we are going to filter the
# response to only contain information about the domain in scope
# so we reflect the domain_id from the context into the target
# to validate domain-scoped tokens.
target = {'domain_id': self.oslo_context.domain_id}
ENFORCER.enforce_call(action='identity:list_role_assignments',
filters=filters,
@ -80,15 +86,18 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
'group.id', 'role.id', 'scope.domain.id', 'scope.project.id',
'scope.OS-INHERIT:inherited_to', 'user.id'
]
project_id = flask.request.args.get('scope.project.id')
target = None
if 'scope.project.id' in flask.request.args:
project_id = flask.request.args['scope.project.id']
if project_id:
target = {'project': PROVIDERS.resource_api.get_project(
project_id)}
if project_id:
target = {
'project': PROVIDERS.resource_api.get_project(project_id)
}
# Add target.domain_id to validate domain-scoped tokens
target['domain_id'] = target['project']['domain_id']
ENFORCER.enforce_call(action='identity:list_role_assignments_for_tree',
filters=filters, target_attr=target)
if not flask.request.args.get('scope.project.id'):
if not project_id:
msg = _('scope.project.id must be specified if include_subtree '
'is also specified')
raise exception.ValidationError(message=msg)