armada/armada/api/middleware.py

100 lines
3.4 KiB
Python

# Copyright 2017 The Armada Authors.
#
# 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.
import falcon
from keystoneauth1 import session
from keystoneauth1.identity import v3
from oslo_config import cfg
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
class AuthMiddleware(object):
def process_request(self, req, resp):
# Validate token and get user session
token = req.get_header('X-Auth-Token')
req.context['session'] = self._get_user_session(token)
# Add token roles to request context
req.context['roles'] = self._get_roles(req.context['session'])
def _get_roles(self, session):
# Get roles IDs associated with user
request_url = CONF.auth_url + '/role_assignments'
resp = self._session_request(session=session, request_url=request_url)
json_resp = resp.json()['role_assignments']
role_ids = [r['role']['id'].encode('utf-8') for r in json_resp]
# Get role names associated with role IDs
roles = []
for role_id in role_ids:
request_url = CONF.auth_url + '/roles/' + role_id
resp = self._session_request(session=session,
request_url=request_url)
role = resp.json()['role']['name'].encode('utf-8')
roles.append(role)
return roles
def _get_user_session(self, token):
# Get user session from token
auth = v3.Token(auth_url=CONF.auth_url,
project_name=CONF.project_name,
project_domain_name=CONF.project_domain_name,
token=token)
return session.Session(auth=auth)
def _session_request(self, session, request_url):
try:
return session.get(request_url)
except:
raise falcon.HTTPUnauthorized('Authentication required',
('Authentication token is invalid.'))
class RoleMiddleware(object):
def process_request(self, req, resp):
endpoint = req.path
roles = req.context['roles']
# Verify roles have sufficient permissions for request endpoint
if not (self._verify_roles(endpoint, roles)):
raise falcon.HTTPUnauthorized('Insufficient permissions',
('Token role insufficient.'))
def _verify_roles(self, endpoint, roles):
# Compare the verified roles listed in the config with the user's
# associated roles
if endpoint == '/armada/apply':
approved_roles = CONF.armada_apply_roles
elif endpoint == '/tiller/releases':
approved_roles = CONF.tiller_release_roles
elif endpoint == '/tiller/status':
approved_roles = CONF.tiller_status_roles
verified_roles = set(roles).intersection(approved_roles)
return bool(verified_roles)