mixmatch/mixmatch/auth.py

123 lines
4.0 KiB
Python

# Copyright 2016 Massachusetts Open Cloud
#
# 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.
from keystoneauth1 import identity
from keystoneauth1 import session
from keystoneclient import v3
from keystoneauth1.exceptions import http
import json
from flask import abort
from mixmatch import config
CONF = config.CONF
LOG = config.LOG
MEMOIZE_SESSION = config.auth.MEMOIZE
@MEMOIZE_SESSION
def get_admin_session(sp=None):
"""Return a Keystone session using admin service credentials."""
LOG.info("Getting Admin Session")
service_auth = identity.Password(
auth_url=CONF.auth.auth_url,
username=CONF.auth.username,
password=CONF.auth.password,
project_name=CONF.auth.project_name,
project_domain_id=CONF.auth.project_domain_id,
user_domain_id=CONF.auth.user_domain_id
)
sess = session.Session(auth=service_auth)
if sp is None:
return sess
else:
token = sess.get_token()
project_id = get_projects_at_sp(sp, token)[0]
remote_admin_sess = get_sp_auth(sp, token, project_id)
return remote_admin_sess
@MEMOIZE_SESSION
def get_client(session):
"""Return a client object given a session object."""
LOG.debug("Getting client for %s" % session)
return v3.client.Client(session=session)
@MEMOIZE_SESSION
def get_local_auth(user_token):
"""Return a Keystone session for the local cluster."""
LOG.debug("Getting session for %s" % user_token)
admin_session = get_admin_session()
client = get_client(admin_session)
token = v3.tokens.TokenManager(client)
try:
token_data = token.validate(token=user_token, include_catalog=False)
except http.NotFound:
abort(401)
project_id = token_data['project']['id']
local_auth = identity.v3.Token(auth_url=CONF.auth.auth_url,
token=user_token,
project_id=project_id)
return session.Session(auth=local_auth)
@MEMOIZE_SESSION
def get_unscoped_sp_auth(service_provider, user_token):
"""Perform K2K auth, and return an unscoped session."""
conf = config.service_providers.get(CONF, service_provider)
local_auth = get_local_auth(user_token).auth
LOG.debug("Getting unscoped session for (%s, %s)" % (service_provider,
user_token))
remote_auth = identity.v3.Keystone2Keystone(
local_auth,
conf.sp_name
)
return session.Session(auth=remote_auth)
def get_projects_at_sp(service_provider, user_token):
"""Perform K2K auth, and return the projects that can be scoped to."""
conf = config.service_providers.get(CONF, service_provider)
unscoped_session = get_unscoped_sp_auth(service_provider, user_token)
r = json.loads(str(unscoped_session.get(
conf.auth_url + "/OS-FEDERATION/projects").text))
return [project[u'id'] for project in r[u'projects']]
@MEMOIZE_SESSION
def get_sp_auth(service_provider, user_token, remote_project_id):
"""Perform K2K auth, and return a session for a remote cluster."""
conf = config.service_providers.get(CONF, service_provider)
local_auth = get_local_auth(user_token).auth
LOG.debug("Getting session for (%s, %s, %s)" % (service_provider,
user_token,
remote_project_id))
remote_auth = identity.v3.Keystone2Keystone(
local_auth,
conf.sp_name,
project_id=remote_project_id
)
return session.Session(auth=remote_auth)