Merge "Pass context objects to policy enforcement"

This commit is contained in:
Zuul 2018-11-27 20:52:50 +00:00 committed by Gerrit Code Review
commit abb811f6d2
5 changed files with 36 additions and 28 deletions

View File

@ -38,3 +38,30 @@ class RequestContext(oslo_context.RequestContext):
self.authenticated = kwargs.pop('authenticated', False)
super(RequestContext, self).__init__(**kwargs)
def to_policy_values(self):
"""Add keystone-specific policy values to policy representation.
This method converts generic policy values to a dictionary form using
the base implementation from oslo_context.context.RequestContext.
Afterwards, it is going to pull keystone-specific values off the
context and represent them as items in the policy values dictionary.
This is because keystone uses default policies that rely on these
values, so we need to guarantee they are present during policy
enforcement if they are present on the context object.
This method is automatically called in
oslo_policy.policy.Enforcer.enforce() if oslo.policy knows it's dealing
with a context object.
"""
# TODO(morgan): Rework this to not need an explicit token render as
# this is a generally poorly designed behavior. The enforcer should not
# rely on a contract of the token's rendered JSON form. This likely
# needs reworking of how we handle the context in oslo.policy. Until
# this is reworked, it is not possible to merge the token render
# function into keystone.api
values = super(RequestContext, self).to_policy_values()
values['token'] = self.token_reference['token']
values['domain_id'] = self.domain_id if self.domain_id else None
return values

View File

@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import functools
import flask
@ -22,7 +21,6 @@ from keystone.common import authorization
from keystone.common import context
from keystone.common import policies
from keystone.common import provider_api
from keystone.common import render_token
from keystone.common import utils
import keystone.conf
from keystone import exception
@ -79,26 +77,6 @@ class RBACEnforcer(object):
extra.update(exc=exception.ForbiddenAction, action=action,
do_raise=do_raise)
# NOTE(lbragstad): If there is a token in the credentials dictionary,
# it's going to be an instance of a TokenModel. We'll need to convert
# it to the a token response or dictionary before passing it to
# oslo.policy for enforcement. This is because oslo.policy shouldn't
# know how to deal with an internal object only used within keystone.
#
# TODO(morgan): Rework this to not need an explicit token render as
# this is a generally poorly designed behavior. The enforcer should not
# rely on a contract of the token's rendered JSON form. This likely
# needs reworking of how we handle the context in oslo.policy. Until
# this is reworked, it is not possible to merge the token render
# function into keystone.api
if 'token' in credentials:
token_ref = render_token.render_token_response_from_model(
credentials['token']
)
credentials_copy = copy.deepcopy(credentials)
credentials_copy['token'] = token_ref
credentials = credentials_copy
try:
return self._enforcer.enforce(
rule=action, target=target, creds=credentials, **extra)
@ -398,7 +376,8 @@ class RBACEnforcer(object):
policy_dict.update(cls._extract_filter_values(filters))
# Extract the cred data
creds = cls._extract_policy_check_credentials()
ctxt = cls._get_oslo_req_context()
creds = ctxt.to_policy_values()
flattened = utils.flatten_dict(policy_dict)
if LOG.logger.getEffectiveLevel() <= log.DEBUG:
# LOG the Args
@ -410,8 +389,7 @@ class RBACEnforcer(object):
{'action': action, 'args': args_str})
# LOG the Cred Data
cred_str = ', '.join(
['%s=%s' % (k, v) for k, v in creds.items()])
cred_str = ', '.join(['%s=%s' % (k, v) for k, v in creds.items()])
cred_str = strutils.mask_password(cred_str)
LOG.debug('RBAC: Policy Enforcement Cred Data '
'`%(action)s creds(%(cred_str)s)`',
@ -428,7 +406,7 @@ class RBACEnforcer(object):
# Instantiate the enforcer object if needed.
enforcer_obj = enforcer or cls()
enforcer_obj._enforce(
credentials=creds, action=action, target=flattened)
credentials=ctxt, action=action, target=flattened)
LOG.debug('RBAC: Authorization granted')
@classmethod

View File

@ -360,6 +360,9 @@ class AuthContextMiddleware(provider_api.ProviderAPIMixin,
self.fill_context(request)
def _keystone_specific_values(self, token, request_context):
request_context.token_reference = (
render_token.render_token_response_from_model(token)
)
if token.domain_scoped:
# Domain scoped tokens should never have is_admin_project set
# Even if KSA defaults it otherwise. The two mechanisms are

View File

@ -34,7 +34,7 @@ oslo.i18n==3.15.3
oslo.log==3.38.0
oslo.messaging==5.29.0
oslo.middleware==3.31.0
oslo.policy==1.33.0
oslo.policy==1.38.0
oslo.serialization==2.18.0
oslo.upgradecheck==0.1.0
oslo.utils==3.33.0

View File

@ -29,7 +29,7 @@ oslo.db>=4.27.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.log>=3.38.0 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
oslo.policy>=1.33.0 # Apache-2.0
oslo.policy>=1.38.0 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.upgradecheck>=0.1.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0