Nicholas Jones 7667a7b9af Fix pep8 errors
Fixes existing pep8 errors and reenables the corresponding tox rules

Change-Id: I4168a90c40173e4c35c9d75030cd592ace657508
2017-08-07 15:46:47 -05:00

183 lines
6.8 KiB
Python
Executable File

"""Policy Engine For ORM."""
import logging
from keystone_utils import tokens
from orm_common.utils import api_error_utils as err_utils
from orm_common.utils import dictator
import qolicy
from wsme.exc import ClientSideError
logger = logging.getLogger(__name__)
_ENFORCER = None
_POLICY_FILE = None
_TOKEN_CONF = None
def reset():
global _ENFORCER
if _ENFORCER:
_ENFORCER.clear()
_ENFORCER = None
global _POLICY_FILE
if _POLICY_FILE:
_POLICY_FILE = None
class EnforcerError(Exception):
"""An exception that receives *args and **kwargs, necessary for
Enforcer.enforce().
"""
def __init__(self, *args, **kwargs):
super(EnforcerError, self).__init__()
def _get_rules_from_file(path):
logger.debug('Reading policy file: {}'.format(path))
return qolicy.Rules.load_json(open(path, 'r').read(), 'default')
def init(policy_file, token_conf, default_rule=None):
"""Init an Enforcer class.
:param policy_file: Custom policy file to use.
:param default_rule: Default rule to use
:param token_conf: The Keystone utils token configuration
"""
logger.info('Initializing policy enforcer...')
global _ENFORCER
global _POLICY_FILE
global _TOKEN_CONF
if not _ENFORCER:
loaded_rules = _get_rules_from_file(policy_file)
_POLICY_FILE = policy_file
_TOKEN_CONF = token_conf
_ENFORCER = qolicy.Enforcer(None,
policy_file=None,
rules=loaded_rules,
default_rule=default_rule,
use_conf=False)
def reset_rules(overwrite=True, use_conf=False):
"""Reset rules based on the provided dict of rules.
:param rules: New rules to use. It should be an instance of dict.
:param overwrite: Whether to overwrite current rules or update them
with the new rules.
:param use_conf: Whether to reload rules from config file.
"""
if not _POLICY_FILE:
message = 'Policy file not set (did you call policy.init?)'
logger.error(message)
raise ValueError(message)
_ENFORCER.set_rules(_get_rules_from_file(_POLICY_FILE),
overwrite, use_conf)
def enforce(action, token, user, lcp_id=None, keystone_ep=None,
do_raise=True):
"""Verifies that the action is valid on the target in this 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 token: The token to validate
:param lcp_id: The ID of the LCP associated with the Keystone instance
with which the token was created
:param keystone_ep: The Keystone endpoint, in case we already have it
:param do_raise: if True (the default), raises Unauthorized (401);
if False, returns False
:raises EnforcerError 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.
"""
logger.debug('Enforcing policy - action: {}, token: {}, lcp_id: {}, '
'keystone_ep: {}'.format(action, token, lcp_id, keystone_ep))
# Re-read the rules, in case the policy file has changed
reset_rules()
# May raise EnforcerError, we'll let it propagate
result = _ENFORCER.enforce(action, {}, user, do_raise=do_raise,
exc=EnforcerError, action=action)
return result
def _is_authorization_enabled(app_conf):
return app_conf.authentication.enabled
def authorize(action, request, app_conf, keystone_ep=None):
"""Authorize a request.
:param action: The requested action, in the policy.json syntax
:param request: Pecan request object
:param app_conf: Application configuration
:param keystone_ep: Keystone endpoint, in case we already have it
:raises Unauthorized (401) in case anything fails in the authorization
process
"""
logger.info('Authorize...start')
token_to_validate = request.headers.get('X-Auth-Token')
lcp_id = request.headers.get('X-Auth-Region')
try:
if _is_authorization_enabled(app_conf):
try:
# Set the service name for Nagios codes
dictator.soft_set('service_name', app_conf.server.name.upper())
user = tokens.get_token_user(token_to_validate, _TOKEN_CONF,
lcp_id, keystone_ep)
request.headers['X-RANGER-Client'] = user.user['name']
request.headers['X-RANGER-Owner'] = user.tenant['id']
except Exception:
user = None
request.headers['X-RANGER-Client'] = 'NA'
logger.exception(
"policy - Failed to get_token_user, using user={}".format(
user))
if token_to_validate is not None and lcp_id is not None and str(token_to_validate).strip() != '' and str(lcp_id).strip() != '':
logger.debug('Authorization: enforcing policy on token=[{}], lcp_id=[{}]'.format(token_to_validate, lcp_id))
enforce(action, token_to_validate, user, lcp_id, keystone_ep)
is_permitted = True
logger.debug('Authorization: policy check passed')
else:
logger.debug('Token=[{}] and/or Region=[{}] are empty/none.'.format(token_to_validate, lcp_id))
logger.info(
'INFO|CON{}AUTH004|One or more of the authentication headers are missing'.format(
dictator.get('service_name', 'ORM')))
# Enforce anyway, in case the policy for this is to always
# allow any user to perform this operation
enforce(action, token_to_validate, user)
is_permitted = True
else:
logger.debug('The authentication service is disabled. No authentication is needed.')
is_permitted = True
except ClientSideError as e:
logger.error('Fail to validate request. due to {}.'.format(e.message))
raise err_utils.get_error('N/A', status_code=e.code)
except EnforcerError:
logger.error('The token is unauthorized according to the policy')
is_permitted = False
except Exception as e:
msg = 'Fail to validate request. due to {}.'.format(e.message)
logger.error(msg)
logger.exception(e)
is_permitted = False
logger.info('Authorize...end')
if not is_permitted:
raise err_utils.get_error('N/A', status_code=401)