aa78d70df2
The default rule is broken in the current implementation of ceilometer rbac, because ceilometer rbac.py does not leverage the support provided by oslo_policy . It instead tries to loop through all the rules in the policy.json to check if the rule corresponding to the requested REST api matches with the any in the policy.json. In this process, it completely ignores the existence of the default rule. Closes-Bug: 1435855 Change-Id: Icab626b28d14514b0f024df447a8e7f35c52257c
101 lines
3.2 KiB
Python
101 lines
3.2 KiB
Python
#
|
|
# Copyright 2012 New Dream Network, LLC (DreamHost)
|
|
# Copyright 2014 Hewlett-Packard Company
|
|
#
|
|
# 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.
|
|
|
|
"""Access Control Lists (ACL's) control access the API server."""
|
|
|
|
from oslo_config import cfg
|
|
from oslo_policy import policy
|
|
import pecan
|
|
|
|
_ENFORCER = None
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
def _has_rule(name):
|
|
return name in _ENFORCER.rules.keys()
|
|
|
|
|
|
def enforce(policy_name, request):
|
|
"""Return the user and project the request should be limited to.
|
|
|
|
:param request: HTTP request
|
|
:param policy_name: the policy name to validate authz against.
|
|
|
|
|
|
"""
|
|
global _ENFORCER
|
|
if not _ENFORCER:
|
|
_ENFORCER = policy.Enforcer(CONF)
|
|
_ENFORCER.load_rules()
|
|
|
|
rule_method = "telemetry:" + policy_name
|
|
headers = request.headers
|
|
|
|
policy_dict = dict()
|
|
policy_dict['roles'] = headers.get('X-Roles', "").split(",")
|
|
policy_dict['target.user_id'] = (headers.get('X-User-Id'))
|
|
policy_dict['target.project_id'] = (headers.get('X-Project-Id'))
|
|
|
|
# maintain backward compat with Juno and previous by allowing the action if
|
|
# there is no rule defined for it
|
|
if ((_has_rule('default') or _has_rule(rule_method)) and
|
|
not _ENFORCER.enforce(rule_method, {}, policy_dict)):
|
|
pecan.core.abort(status_code=403, detail='RBAC Authorization Failed')
|
|
|
|
|
|
# TODO(fabiog): these methods are still used because the scoping part is really
|
|
# convoluted and difficult to separate out.
|
|
|
|
def get_limited_to(headers):
|
|
"""Return the user and project the request should be limited to.
|
|
|
|
:param headers: HTTP headers dictionary
|
|
:return: A tuple of (user, project), set to None if there's no limit on
|
|
one of these.
|
|
|
|
"""
|
|
global _ENFORCER
|
|
if not _ENFORCER:
|
|
_ENFORCER = policy.Enforcer(CONF)
|
|
_ENFORCER.load_rules()
|
|
|
|
policy_dict = dict()
|
|
policy_dict['roles'] = headers.get('X-Roles', "").split(",")
|
|
policy_dict['target.user_id'] = (headers.get('X-User-Id'))
|
|
policy_dict['target.project_id'] = (headers.get('X-Project-Id'))
|
|
|
|
# maintain backward compat with Juno and previous by using context_is_admin
|
|
# rule if the segregation rule (added in Kilo) is not defined
|
|
rule_name = 'segregation' if _has_rule(
|
|
'segregation') else 'context_is_admin'
|
|
if not _ENFORCER.enforce(rule_name,
|
|
{},
|
|
policy_dict):
|
|
return headers.get('X-User-Id'), headers.get('X-Project-Id')
|
|
|
|
return None, None
|
|
|
|
|
|
def get_limited_to_project(headers):
|
|
"""Return the project the request should be limited to.
|
|
|
|
:param headers: HTTP headers dictionary
|
|
:return: A project, or None if there's no limit on it.
|
|
|
|
"""
|
|
return get_limited_to(headers)[1]
|