Clean up some policy code
oslo policy handles the mapping of
credentials from a context object to values
that oslo policy cares about. This mapping
includes some deprecations and compatibility
handling code that we must take advantage of [1].
So, stop mapping context to policy values
on our end, and rely on oslo.policy handling
this for us.
enforce and authorize methods in policy.py
do the same thing, but with a subtle
difference. The "enforce" method doesn't
raise errors when unregistered policies are
invoked - this shouldn't ever be the case
for any policies written/maintained within
manila - however, we support API extensions
and don't dictate what must be done there. So
add docstrings to clarify that we shouldn't
invoke enforce, ever.
Also handle InvalidPolicyScope exceptions
and raise the oslo.policy library version
since some test enhancements have been
committed in the latest version.
[1] d3185debdb/oslo_policy/policy.py (L1077-L1096)
Change-Id: I069bf7143d6ff66b3dcdc34c9b52d48f5808481b
Signed-off-by: Goutham Pacha Ravi <gouthampravi@gmail.com>
This commit is contained in:
parent
00133f93ae
commit
8553962997
|
@ -64,7 +64,7 @@ oslo.i18n==5.0.1
|
||||||
oslo.log==4.4.0
|
oslo.log==4.4.0
|
||||||
oslo.messaging==12.5.0
|
oslo.messaging==12.5.0
|
||||||
oslo.middleware==4.1.1
|
oslo.middleware==4.1.1
|
||||||
oslo.policy==3.6.0
|
oslo.policy==3.6.2
|
||||||
oslo.reports==2.2.0
|
oslo.reports==2.2.0
|
||||||
oslo.rootwrap==6.2.0
|
oslo.rootwrap==6.2.0
|
||||||
oslo.serialization==4.0.1
|
oslo.serialization==4.0.1
|
||||||
|
|
|
@ -22,10 +22,9 @@ from oslo_utils import importutils
|
||||||
import webob.dec
|
import webob.dec
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
import manila.api.openstack
|
|
||||||
from manila.api.openstack import wsgi
|
from manila.api.openstack import wsgi
|
||||||
from manila import exception
|
from manila import exception
|
||||||
import manila.policy
|
from manila import policy
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
@ -332,12 +331,10 @@ def load_standard_extensions(ext_mgr, logger, path, package, ext_list=None):
|
||||||
|
|
||||||
def extension_authorizer(api_name, extension_name):
|
def extension_authorizer(api_name, extension_name):
|
||||||
def authorize(context, target=None, action=None):
|
def authorize(context, target=None, action=None):
|
||||||
if target is None:
|
target = target or policy.default_target(context)
|
||||||
target = {'project_id': context.project_id,
|
|
||||||
'user_id': context.user_id}
|
|
||||||
if action is None:
|
if action is None:
|
||||||
act = '%s_extension:%s' % (api_name, extension_name)
|
act = '%s_extension:%s' % (api_name, extension_name)
|
||||||
else:
|
else:
|
||||||
act = '%s_extension:%s:%s' % (api_name, extension_name, action)
|
act = '%s_extension:%s:%s' % (api_name, extension_name, action)
|
||||||
manila.policy.enforce(context, act, target)
|
policy.enforce(context, act, target)
|
||||||
return authorize
|
return authorize
|
||||||
|
|
|
@ -69,6 +69,10 @@ def init(rules=None, use_conf=True):
|
||||||
def enforce(context, action, target, do_raise=True):
|
def enforce(context, action, target, do_raise=True):
|
||||||
"""Verifies that the action is valid on the target in this context.
|
"""Verifies that the action is valid on the target in this context.
|
||||||
|
|
||||||
|
**IMPORTANT** ONLY for use in API extensions. This method ignores
|
||||||
|
unregistered rules and applies a default rule on them; there should
|
||||||
|
be no unregistered rules in first party manila APIs.
|
||||||
|
|
||||||
:param context: manila context
|
:param context: manila context
|
||||||
:param action: string representing the action to be checked,
|
:param action: string representing the action to be checked,
|
||||||
this should be colon separated for clarity.
|
this should be colon separated for clarity.
|
||||||
|
@ -88,12 +92,15 @@ def enforce(context, action, target, do_raise=True):
|
||||||
"""
|
"""
|
||||||
init()
|
init()
|
||||||
|
|
||||||
return _ENFORCER.enforce(action,
|
try:
|
||||||
target,
|
return _ENFORCER.enforce(action,
|
||||||
context.to_policy_values(),
|
target,
|
||||||
do_raise=do_raise,
|
context,
|
||||||
exc=exception.PolicyNotAuthorized,
|
do_raise=do_raise,
|
||||||
action=action)
|
exc=exception.PolicyNotAuthorized,
|
||||||
|
action=action)
|
||||||
|
except policy.InvalidScope:
|
||||||
|
raise exception.PolicyNotAuthorized(action=action)
|
||||||
|
|
||||||
|
|
||||||
def set_rules(rules, overwrite=True, use_conf=False):
|
def set_rules(rules, overwrite=True, use_conf=False):
|
||||||
|
@ -165,32 +172,41 @@ def authorize(context, action, target, do_raise=True, exc=None):
|
||||||
do_raise is False.
|
do_raise is False.
|
||||||
"""
|
"""
|
||||||
init()
|
init()
|
||||||
credentials = context.to_policy_values()
|
|
||||||
if not exc:
|
if not exc:
|
||||||
exc = exception.PolicyNotAuthorized
|
exc = exception.PolicyNotAuthorized
|
||||||
|
target = target or default_target(context)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = _ENFORCER.authorize(action, target, credentials,
|
result = _ENFORCER.authorize(action, target, context,
|
||||||
do_raise=do_raise, exc=exc, action=action)
|
do_raise=do_raise, exc=exc, action=action)
|
||||||
except policy.PolicyNotRegistered:
|
except policy.PolicyNotRegistered:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.exception('Policy not registered')
|
LOG.exception('Policy not registered')
|
||||||
|
except policy.InvalidScope:
|
||||||
|
raise exception.PolicyNotAuthorized(action=action)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
|
msg_args = {
|
||||||
|
'action': action,
|
||||||
|
'credentials': context.to_policy_values(),
|
||||||
|
}
|
||||||
LOG.debug('Policy check for %(action)s failed with credentials '
|
LOG.debug('Policy check for %(action)s failed with credentials '
|
||||||
'%(credentials)s',
|
'%(credentials)s', msg_args)
|
||||||
{'action': action, 'credentials': credentials})
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def default_target(context):
|
||||||
|
return {'project_id': context.project_id, 'user_id': context.user_id}
|
||||||
|
|
||||||
|
|
||||||
def check_is_admin(context):
|
def check_is_admin(context):
|
||||||
"""Whether or not user is admin according to policy setting.
|
"""Whether or not user is admin according to policy setting.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
init()
|
init()
|
||||||
|
# the target is user-self
|
||||||
credentials = context.to_policy_values()
|
target = default_target(context)
|
||||||
target = credentials
|
return _ENFORCER.authorize('context_is_admin', target, context)
|
||||||
return _ENFORCER.authorize('context_is_admin', target, credentials)
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_check_policy(resource):
|
def wrap_check_policy(resource):
|
||||||
|
@ -206,10 +222,6 @@ def wrap_check_policy(resource):
|
||||||
|
|
||||||
|
|
||||||
def check_policy(context, resource, action, target_obj=None, do_raise=True):
|
def check_policy(context, resource, action, target_obj=None, do_raise=True):
|
||||||
target = {
|
target = target_obj or default_target(context)
|
||||||
'project_id': context.project_id,
|
|
||||||
'user_id': context.user_id,
|
|
||||||
}
|
|
||||||
target.update(target_obj or {})
|
|
||||||
_action = '%s:%s' % (resource, action)
|
_action = '%s:%s' % (resource, action)
|
||||||
return authorize(context, _action, target, do_raise=do_raise)
|
return authorize(context, _action, target, do_raise=do_raise)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
"""Test of Policy Engine For Manila."""
|
"""Test of Policy Engine For Manila."""
|
||||||
|
|
||||||
|
import ddt
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_policy import policy as common_policy
|
from oslo_policy import policy as common_policy
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ from manila import test
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
class PolicyTestCase(test.TestCase):
|
class PolicyTestCase(test.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(PolicyTestCase, self).setUp()
|
super(PolicyTestCase, self).setUp()
|
||||||
|
@ -97,8 +99,41 @@ class PolicyTestCase(test.TestCase):
|
||||||
policy.authorize(admin_context, lowercase_action, self.target)
|
policy.authorize(admin_context, lowercase_action, self.target)
|
||||||
policy.authorize(admin_context, uppercase_action, self.target)
|
policy.authorize(admin_context, uppercase_action, self.target)
|
||||||
|
|
||||||
|
@ddt.data('enforce', 'authorize')
|
||||||
|
def test_authorize_properly_handles_invalid_scope_exception(self, method):
|
||||||
|
self.fixture.config(enforce_scope=True, group='oslo_policy')
|
||||||
|
project_context = context.RequestContext(project_id='fake-project-id',
|
||||||
|
roles=['bar'])
|
||||||
|
policy.reset()
|
||||||
|
policy.init()
|
||||||
|
rule = common_policy.RuleDefault('foo', 'role:bar',
|
||||||
|
scope_types=['system'])
|
||||||
|
policy._ENFORCER.register_defaults([rule])
|
||||||
|
|
||||||
|
self.assertRaises(exception.PolicyNotAuthorized,
|
||||||
|
getattr(policy, method),
|
||||||
|
project_context, 'foo', {})
|
||||||
|
|
||||||
|
@ddt.data('enforce', 'authorize')
|
||||||
|
def test_authorize_does_not_raise_forbidden(self, method):
|
||||||
|
self.fixture.config(enforce_scope=False, group='oslo_policy')
|
||||||
|
project_context = context.RequestContext(project_id='fake-project-id',
|
||||||
|
roles=['bar'])
|
||||||
|
policy.reset()
|
||||||
|
policy.init()
|
||||||
|
rule = common_policy.RuleDefault('foo', 'role:bar',
|
||||||
|
scope_types=['system'])
|
||||||
|
policy._ENFORCER.register_defaults([rule])
|
||||||
|
|
||||||
|
self.assertTrue(getattr(policy, method)(project_context, 'foo', {}))
|
||||||
|
|
||||||
|
|
||||||
class DefaultPolicyTestCase(test.TestCase):
|
class DefaultPolicyTestCase(test.TestCase):
|
||||||
|
"""This test case calls into the "enforce" method in policy
|
||||||
|
|
||||||
|
enforce() in contrast with authorize() allows "default" rules to apply
|
||||||
|
to policies that have not been registered.
|
||||||
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(DefaultPolicyTestCase, self).setUp()
|
super(DefaultPolicyTestCase, self).setUp()
|
||||||
|
|
|
@ -17,7 +17,7 @@ oslo.i18n>=5.0.1 # Apache-2.0
|
||||||
oslo.log>=4.4.0 # Apache-2.0
|
oslo.log>=4.4.0 # Apache-2.0
|
||||||
oslo.messaging>=12.5.0 # Apache-2.0
|
oslo.messaging>=12.5.0 # Apache-2.0
|
||||||
oslo.middleware>=4.1.1 # Apache-2.0
|
oslo.middleware>=4.1.1 # Apache-2.0
|
||||||
oslo.policy>=3.6.0 # Apache-2.0
|
oslo.policy>=3.6.2 # Apache-2.0
|
||||||
oslo.reports>=2.2.0 # Apache-2.0
|
oslo.reports>=2.2.0 # Apache-2.0
|
||||||
oslo.rootwrap>=6.2.0 # Apache-2.0
|
oslo.rootwrap>=6.2.0 # Apache-2.0
|
||||||
oslo.serialization>=4.0.1 # Apache-2.0
|
oslo.serialization>=4.0.1 # Apache-2.0
|
||||||
|
|
Loading…
Reference in New Issue