100 lines
3.4 KiB
Python
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)
|