Adding trust delegation and removal for proxy users

Changes
* adding a generic keystone client creation function
* adding a function to create proxy user clients
* renaming admin client functions for clarity
* adding token delegation/removal during proxy user creation/deletion
* adding a configuration option for proxy user trust roles

Change-Id: I362a27c1b1d0c5b81d6fbbb91fc0689e339f0076
Partial-implements: blueprint edp-swift-trust-authentication
This commit is contained in:
Michael McCune 2014-08-23 14:10:32 -04:00
parent a539bcfdc9
commit c332e4f96d
4 changed files with 56 additions and 13 deletions

View File

@ -480,6 +480,10 @@
# Swift object access. (string value) # Swift object access. (string value)
#proxy_user_domain_name=<None> #proxy_user_domain_name=<None>
# A list of the role names that the proxy user should assume
# through trust for Swift object access. (list value)
#proxy_user_role_names=Member
# #
# Options defined in sahara.utils.remote # Options defined in sahara.utils.remote

View File

@ -113,7 +113,8 @@ def delete_trust_from_cluster(cluster):
''' '''
if cluster.trust_id: if cluster.trust_id:
keystone_client = keystone.client_for_trusts(cluster.trust_id) keystone_client = keystone.client_for_admin_from_trust(
cluster.trust_id)
delete_trust(keystone_client, cluster.trust_id) delete_trust(keystone_client, cluster.trust_id)
ctx = context.current() ctx = context.current()
conductor.cluster_update(ctx, conductor.cluster_update(ctx,
@ -136,7 +137,7 @@ def use_os_admin_auth_token(cluster):
ctx = context.current() ctx = context.current()
ctx.username = CONF.keystone_authtoken.admin_user ctx.username = CONF.keystone_authtoken.admin_user
ctx.tenant_id = cluster.tenant_id ctx.tenant_id = cluster.tenant_id
client = keystone.client_for_trusts(cluster.trust_id) client = keystone.client_for_admin_from_trust(cluster.trust_id)
ctx.token = client.auth_token ctx.token = client.auth_token
ctx.service_catalog = json.dumps( ctx.service_catalog = json.dumps(
client.service_catalog.catalog['catalog']) client.service_catalog.catalog['catalog'])

View File

@ -28,12 +28,14 @@ opts = [
default=True, default=True,
help='Enables Sahara to use Keystone API v3. ' help='Enables Sahara to use Keystone API v3. '
'If that flag is disabled, ' 'If that flag is disabled, '
'per-job clusters will not be terminated automatically.') 'per-job clusters will not be terminated '
'automatically.')
] ]
CONF.register_opts(opts) CONF.register_opts(opts)
def client(): def client():
'''Return the current context client.'''
ctx = context.current() ctx = context.current()
auth_url = base.retrieve_auth_url() auth_url = base.retrieve_auth_url()
@ -52,27 +54,47 @@ def client():
return keystone return keystone
def _admin_client(project_name=None, trust_id=None): def _client(username, password, project_name=None, trust_id=None,
domain_name=None):
if not CONF.use_identity_api_v3: if not CONF.use_identity_api_v3:
raise Exception('Trusts aren\'t implemented in keystone api' raise Exception('Trusts aren\'t implemented in keystone api'
' less than v3') ' less than v3')
auth_url = base.retrieve_auth_url() auth_url = base.retrieve_auth_url()
username = CONF.keystone_authtoken.admin_user
password = CONF.keystone_authtoken.admin_password
keystone = keystone_client_v3.Client(username=username, keystone = keystone_client_v3.Client(username=username,
password=password, password=password,
project_name=project_name, project_name=project_name,
user_domain_name=domain_name,
auth_url=auth_url, auth_url=auth_url,
trust_id=trust_id) trust_id=trust_id)
keystone.management_url = auth_url keystone.management_url = auth_url
return keystone return keystone
def _admin_client(project_name=None, trust_id=None):
username = CONF.keystone_authtoken.admin_user
password = CONF.keystone_authtoken.admin_password
keystone = _client(username=username,
password=password,
project_name=project_name,
trust_id=trust_id)
return keystone
def client_for_admin(): def client_for_admin():
project_name = CONF.keystone_authtoken.admin_tenant_name '''Return the Sahara admin user client.'''
return _admin_client(project_name=project_name) return _admin_client(
project_name=CONF.keystone_authtoken.admin_tenant_name)
def client_for_trusts(trust_id): def client_for_admin_from_trust(trust_id):
'''Return the Sahara admin user client scoped to a trust.'''
return _admin_client(trust_id=trust_id) return _admin_client(trust_id=trust_id)
def client_for_proxy_user(username, password, trust_id=None):
'''Return a client for the proxy user specified.'''
return _client(username=username,
password=password,
domain_name=CONF.proxy_user_domain_name,
trust_id=trust_id)

View File

@ -23,6 +23,7 @@ from sahara import context
from sahara import exceptions as ex from sahara import exceptions as ex
from sahara.i18n import _ from sahara.i18n import _
from sahara.openstack.common import log as logging from sahara.openstack.common import log as logging
from sahara.service import trusts as t
from sahara.swift import utils as su from sahara.swift import utils as su
from sahara.utils.openstack import keystone as k from sahara.utils.openstack import keystone as k
@ -41,7 +42,11 @@ opts = [
cfg.StrOpt('proxy_user_domain_name', cfg.StrOpt('proxy_user_domain_name',
default=None, default=None,
help='The domain Sahara will use to create new proxy users ' help='The domain Sahara will use to create new proxy users '
'for Swift object access.') 'for Swift object access.'),
cfg.ListOpt('proxy_user_role_names',
default=['Member'],
help='A list of the role names that the proxy user should '
'assume through trust for Swift object access.')
] ]
CONF.register_opts(opts) CONF.register_opts(opts)
@ -54,10 +59,16 @@ def create_proxy_user_for_job_execution(job_execution):
''' '''
username = 'job_{0}'.format(job_execution.id) username = 'job_{0}'.format(job_execution.id)
password = proxy_user_create(username) password = proxy_user_create(username)
current_user = k.client()
proxy_user = k.client_for_proxy_user(username, password)
trust_id = t.create_trust(trustor=current_user,
trustee=proxy_user,
role_names=CONF.proxy_user_role_names)
update = {'job_configs': job_execution.job_configs.to_dict()} update = {'job_configs': job_execution.job_configs.to_dict()}
update['job_configs']['proxy_configs'] = { update['job_configs']['proxy_configs'] = {
'proxy_username': username, 'proxy_username': username,
'proxy_password': password 'proxy_password': password,
'proxy_trust_id': trust_id
} }
conductor.job_execution_update(context.ctx(), job_execution, update) conductor.job_execution_update(context.ctx(), job_execution, update)
@ -72,8 +83,13 @@ def delete_proxy_user_for_job_execution(job_execution):
proxy_configs = job_execution.job_configs.get('proxy_configs') proxy_configs = job_execution.job_configs.get('proxy_configs')
if proxy_configs is not None: if proxy_configs is not None:
proxy_username = proxy_configs.get('proxy_username') proxy_username = proxy_configs.get('proxy_username')
if proxy_username is not None: proxy_password = proxy_configs.get('proxy_password')
proxy_user_delete(proxy_username) proxy_trust_id = proxy_configs.get('proxy_trust_id')
proxy_user = k.client_for_proxy_user(proxy_username,
proxy_password,
proxy_trust_id)
t.delete_trust(proxy_user, proxy_trust_id)
proxy_user_delete(proxy_username)
update = {'job_configs': job_execution.job_configs.to_dict()} update = {'job_configs': job_execution.job_configs.to_dict()}
del update['job_configs']['proxy_configs'] del update['job_configs']['proxy_configs']
return update return update