Merge "Replace admin check with policy check in placement API"
This commit is contained in:
@@ -36,6 +36,7 @@ from nova.api.openstack.placement.handlers import usage
|
||||
from nova.api.openstack.placement import util
|
||||
from nova import exception
|
||||
from nova.i18n import _, _LE
|
||||
from nova.api.openstack.placement import policy
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@@ -155,12 +156,8 @@ class PlacementHandler(object):
|
||||
context = environ['placement.context']
|
||||
# TODO(cdent): Using is_admin everywhere (except /) is
|
||||
# insufficiently flexible for future use case but is
|
||||
# convenient for initial exploration. We will need to
|
||||
# determine how to manage authorization/policy and
|
||||
# implement that, probably per handler. Also this is
|
||||
# just the wrong way to do things, but policy not
|
||||
# integrated yet.
|
||||
if 'admin' not in context.to_policy_values()['roles']:
|
||||
# convenient for initial exploration.
|
||||
if not policy.placement_authorize(context, 'placement'):
|
||||
raise webob.exc.HTTPForbidden(
|
||||
_('admin required'),
|
||||
json_formatter=util.json_error_formatter)
|
||||
|
||||
76
nova/api/openstack/placement/policy.py
Normal file
76
nova/api/openstack/placement/policy.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""Policy Enforcement for placement API."""
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_policy import policy
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ENFORCER_PLACEMENT = None
|
||||
|
||||
|
||||
def placement_init():
|
||||
"""Init an Enforcer class for placement policy.
|
||||
|
||||
This method uses a different list of policies than other parts of Nova.
|
||||
This is done to facilitate a split out of the placement service later.
|
||||
"""
|
||||
global _ENFORCER_PLACEMENT
|
||||
if not _ENFORCER_PLACEMENT:
|
||||
# TODO(cdent): Using is_admin everywhere (except /) is
|
||||
# insufficiently flexible for future use case but is
|
||||
# convenient for initial exploration. We will need to
|
||||
# determine how to manage authorization/policy and
|
||||
# implement that, probably per handler.
|
||||
rules = policy.Rules.load_json(
|
||||
jsonutils.dumps({'placement': 'role:admin'}))
|
||||
# Enforcer is initialized so that the above rule is loaded in and no
|
||||
# policy file is read.
|
||||
# TODO(alaski): Register a default rule rather than loading it in like
|
||||
# this. That requires that a policy file is specified to be read. When
|
||||
# this is split out such that a placement policy file makes sense then
|
||||
# change to rule registration.
|
||||
_ENFORCER_PLACEMENT = policy.Enforcer(CONF, rules=rules,
|
||||
use_conf=False)
|
||||
|
||||
|
||||
def placement_authorize(context, action, target=None):
|
||||
"""Verifies that the action is valid on the target in this context.
|
||||
|
||||
:param context: RequestContext object
|
||||
:param action: string representing the action to be checked
|
||||
: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}``
|
||||
|
||||
:return: returns a non-False value (not necessarily "True") if
|
||||
authorized, and the exact value False if not authorized.
|
||||
"""
|
||||
placement_init()
|
||||
if target is None:
|
||||
target = {'project_id': context.tenant,
|
||||
'user_id': context.user}
|
||||
credentials = context.to_policy_values()
|
||||
# TODO(alaski): Change this to use authorize() when rules are registered.
|
||||
# noqa the following line because a hacking check disallows using enforce.
|
||||
result = _ENFORCER_PLACEMENT.enforce(action, target, credentials,
|
||||
do_raise=False, exc=None,
|
||||
action=action)
|
||||
if result is False:
|
||||
LOG.debug('Policy check for %(action)s failed with credentials '
|
||||
'%(credentials)s',
|
||||
{'action': action, 'credentials': credentials})
|
||||
return result
|
||||
Reference in New Issue
Block a user