Merge "Fix policies"
This commit is contained in:
commit
d6739867ab
@ -1,6 +1,5 @@
|
||||
{
|
||||
"admin": "role:admin or role:administrator",
|
||||
"admin_api": "is_admin:True",
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
|
||||
"is_admin": "role:admin or role:administrator",
|
||||
"default": "rule:admin_or_owner",
|
||||
"default": "rule:admin_api"
|
||||
}
|
||||
|
@ -20,11 +20,8 @@
|
||||
|
||||
from keystoneclient.middleware import auth_token as keystone_auth_token
|
||||
from oslo.config import cfg
|
||||
from pecan import hooks
|
||||
from webob import exc
|
||||
|
||||
from ironic.api.middleware import auth_token
|
||||
from ironic.common import policy
|
||||
|
||||
|
||||
OPT_GROUP_NAME = 'keystone_authtoken'
|
||||
@ -56,17 +53,3 @@ def install(app, conf, public_routes):
|
||||
return auth_token.AuthTokenMiddleware(app,
|
||||
conf=keystone_config,
|
||||
public_api_routes=public_routes)
|
||||
|
||||
|
||||
class AdminAuthHook(hooks.PecanHook):
|
||||
"""Verify that the user has admin rights.
|
||||
|
||||
Checks whether the request context is an admin context and
|
||||
rejects the request otherwise.
|
||||
|
||||
"""
|
||||
def before(self, state):
|
||||
ctx = state.request.context
|
||||
|
||||
if not policy.check_is_admin(ctx) and not ctx.is_public_api:
|
||||
raise exc.HTTPForbidden()
|
||||
|
@ -23,6 +23,7 @@ from ironic.api import acl
|
||||
from ironic.api import config
|
||||
from ironic.api import hooks
|
||||
from ironic.api import middleware
|
||||
from ironic.common import policy
|
||||
|
||||
auth_opts = [
|
||||
cfg.StrOpt('auth_strategy',
|
||||
@ -41,6 +42,8 @@ def get_pecan_config():
|
||||
|
||||
|
||||
def setup_app(pecan_config=None, extra_hooks=None):
|
||||
policy.init()
|
||||
|
||||
app_hooks = [hooks.ConfigHook(),
|
||||
hooks.DBHook(),
|
||||
hooks.ContextHook(pecan_config.app.acl_public_routes),
|
||||
@ -52,7 +55,7 @@ def setup_app(pecan_config=None, extra_hooks=None):
|
||||
pecan_config = get_pecan_config()
|
||||
|
||||
if pecan_config.app.enable_acl:
|
||||
app_hooks.append(acl.AdminAuthHook())
|
||||
app_hooks.append(hooks.AdminAuthHook())
|
||||
|
||||
pecan.configuration.set_config(dict(pecan_config), overwrite=True)
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
from oslo.config import cfg
|
||||
from pecan import hooks
|
||||
from webob import exc
|
||||
|
||||
from ironic.common import context
|
||||
from ironic.common import utils
|
||||
@ -74,7 +75,7 @@ class ContextHook(hooks.PecanHook):
|
||||
auth_token = state.request.headers.get('X-Auth-Token', None)
|
||||
creds = {'roles': state.request.headers.get('X-Roles', '').split(',')}
|
||||
|
||||
is_admin = policy.check('is_admin', state.request.headers, creds)
|
||||
is_admin = policy.check('admin', state.request.headers, creds)
|
||||
|
||||
path = utils.safe_rstrip(state.request.path, '/')
|
||||
is_public_api = path in self.public_api_routes
|
||||
@ -94,3 +95,18 @@ class RPCHook(hooks.PecanHook):
|
||||
|
||||
def before(self, state):
|
||||
state.request.rpcapi = rpcapi.ConductorAPI()
|
||||
|
||||
|
||||
class AdminAuthHook(hooks.PecanHook):
|
||||
"""Verify that the user has admin rights.
|
||||
|
||||
Checks whether the request context is an admin context and
|
||||
rejects the request otherwise.
|
||||
|
||||
"""
|
||||
def before(self, state):
|
||||
ctx = state.request.context
|
||||
is_admin_api = policy.check('admin_api', {}, ctx.to_dict())
|
||||
|
||||
if not is_admin_api and not ctx.is_public_api:
|
||||
raise exc.HTTPForbidden()
|
||||
|
@ -66,66 +66,3 @@ def init():
|
||||
def _set_rules(data):
|
||||
default_rule = CONF.policy_default_rule
|
||||
policy.set_rules(policy.Rules.load_json(data, default_rule))
|
||||
|
||||
|
||||
def enforce(context, action, target, do_raise=True):
|
||||
"""Verifies that the action is valid on the target in this context.
|
||||
|
||||
:param context: ironic context
|
||||
:param action: string representing the action to be checked
|
||||
this should be colon separated for clarity.
|
||||
i.e. ``compute:create_instance``,
|
||||
``compute:attach_volume``,
|
||||
``volume:attach_volume``
|
||||
:param target: dictionary representing the object of the action
|
||||
for object creation this should be a dictionary representing the
|
||||
location of the object e.g. ``{'project_id': context.project_id}``
|
||||
:param do_raise: if True (the default), raises PolicyNotAuthorized;
|
||||
if False, returns False
|
||||
|
||||
:raises ironic.exception.PolicyNotAuthorized: if verification fails
|
||||
and do_raise is True.
|
||||
|
||||
:return: returns a non-False value (not necessarily "True") if
|
||||
authorized, and the exact value False if not authorized and
|
||||
do_raise is False.
|
||||
"""
|
||||
init()
|
||||
|
||||
credentials = context.to_dict()
|
||||
|
||||
# Add the exception arguments if asked to do a raise
|
||||
extra = {}
|
||||
if do_raise:
|
||||
extra.update(exc=exception.PolicyNotAuthorized, action=action)
|
||||
|
||||
return policy.check(action, target, credentials, **extra)
|
||||
|
||||
|
||||
def check_is_admin(context):
|
||||
"""Whether or not role contains 'admin' role according to policy setting.
|
||||
|
||||
"""
|
||||
init()
|
||||
|
||||
credentials = context.to_dict()
|
||||
target = credentials
|
||||
|
||||
return policy.check('context_is_admin', target, credentials)
|
||||
|
||||
|
||||
@policy.register('context_is_admin')
|
||||
class IsAdminCheck(policy.Check):
|
||||
"""An explicit check for is_admin."""
|
||||
|
||||
def __init__(self, kind, match):
|
||||
"""Initialize the check."""
|
||||
|
||||
self.expected = (match.lower() == 'true')
|
||||
|
||||
super(IsAdminCheck, self).__init__(kind, str(self.expected))
|
||||
|
||||
def __call__(self, target, creds):
|
||||
"""Determine whether is_admin matches the requested value."""
|
||||
|
||||
return creds['is_admin'] == self.expected
|
||||
|
@ -42,8 +42,6 @@ class FunctionalTest(base.DbTestCase):
|
||||
def setUp(self):
|
||||
super(FunctionalTest, self).setUp()
|
||||
cfg.CONF.set_override("auth_version", "v2.0", group=acl.OPT_GROUP_NAME)
|
||||
cfg.CONF.set_override("policy_file",
|
||||
self.path_get('tests/policy.json'))
|
||||
self.app = self._make_app()
|
||||
self.dbapi = dbapi.get_instance()
|
||||
|
||||
|
@ -17,9 +17,8 @@
|
||||
|
||||
policy_data = """
|
||||
{
|
||||
"admin_api": "role:admin",
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
|
||||
"is_admin": "role:admin or role:administrator",
|
||||
"default": "rule:admin_or_owner"
|
||||
"admin": "role:admin or role:administrator",
|
||||
"admin_api": "is_admin:True",
|
||||
"default": "rule:admin_api"
|
||||
}
|
||||
"""
|
||||
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"admin_api": "is_admin:True",
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
|
||||
"is_admin": "role:admin or role:administrator",
|
||||
"default": "rule:admin_or_owner",
|
||||
}
|
Loading…
Reference in New Issue
Block a user