Calls to federated service providers using Keystone-to-Keystone

Allow users to direct calls using the OpenStackClient to a remote
federated service provider using Keystone 2 Keystone federation.

Change-Id: Icbdb286f840ecd3a57c64ef69b9e55925439b2f1
This commit is contained in:
Kristi Nikolla 2016-09-16 12:47:04 -04:00
parent 5482f52612
commit 572eddc142
4 changed files with 78 additions and 8 deletions

View File

@ -15,6 +15,7 @@
import argparse
from keystoneauth1.identity.v3 import k2k
from keystoneauth1.loading import base
from osc_lib import exceptions as exc
@ -190,3 +191,25 @@ def build_auth_plugins_option_parser(parser):
help=argparse.SUPPRESS,
)
return parser
def get_keystone2keystone_auth(local_auth, service_provider,
project_id=None, project_name=None,
project_domain_id=None,
project_domain_name=None):
"""Return Keystone 2 Keystone authentication for service provider.
:param local_auth: authentication to use with the local Keystone
:param service_provider: service provider id as registered in Keystone
:param project_id: project id to scope to in the service provider
:param project_name: project name to scope to in the service provider
:param project_domain_id: id of domain in the service provider
:param project_domain_name: name of domain to in the service provider
:return: Keystone2Keystone auth object for service provider
"""
return k2k.Keystone2Keystone(local_auth,
service_provider,
project_id=project_id,
project_name=project_name,
project_domain_id=project_domain_id,
project_domain_name=project_domain_name)

View File

@ -169,6 +169,17 @@ class ClientManager(object):
LOG.debug('Using parameters %s',
strutils.mask_password(self._cli_options.auth))
self.auth = self._cli_options.get_auth()
if self._cli_options.service_provider:
self.auth = auth.get_keystone2keystone_auth(
self.auth,
self._cli_options.service_provider,
self._cli_options.remote_project_id,
self._cli_options.remote_project_name,
self._cli_options.remote_project_domain_id,
self._cli_options.remote_project_domain_name
)
self.session = osc_session.TimingSession(
auth=self.auth,
verify=self.verify,

View File

@ -25,10 +25,13 @@ AUTH_URL = "http://0.0.0.0"
USERNAME = "itchy"
PASSWORD = "scratchy"
PROJECT_NAME = "poochie"
PROJECT_ID = "30c3da29-61f5-4b7b-8eb2-3d18287428c7"
REGION_NAME = "richie"
INTERFACE = "catchy"
VERSION = "3"
SERVICE_PROVIDER_ID = "bob"
TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN,
user_name=USERNAME)
_s = TEST_RESPONSE_DICT.add_service('identity', name='keystone')

View File

@ -19,6 +19,7 @@ import mock
from keystoneauth1.access import service_catalog
from keystoneauth1 import exceptions as ksa_exceptions
from keystoneauth1.identity import generic as generic_plugin
from keystoneauth1.identity.v3 import k2k
from keystoneauth1 import loading
from os_client_config import cloud_config
@ -32,6 +33,13 @@ AUTH_REF = {'version': 'v2.0'}
AUTH_REF.update(fakes.TEST_RESPONSE_DICT['access'])
SERVICE_CATALOG = service_catalog.ServiceCatalogV2(AUTH_REF)
AUTH_DICT = {
'auth_url': fakes.AUTH_URL,
'username': fakes.USERNAME,
'password': fakes.PASSWORD,
'project_name': fakes.PROJECT_NAME
}
# This is deferred in api.auth but we need it here...
auth.get_options_list()
@ -257,21 +265,15 @@ class TestClientManager(utils.TestClientManager):
@mock.patch('osc_lib.api.auth.check_valid_authentication_options')
def test_client_manager_auth_setup_once(self, check_authn_options_func):
auth_dict = {
'auth_url': fakes.AUTH_URL,
'username': fakes.USERNAME,
'password': fakes.PASSWORD,
'project_name': fakes.PROJECT_NAME,
}
loader = loading.get_plugin_loader('password')
auth_plugin = loader.load_from_options(**auth_dict)
auth_plugin = loader.load_from_options(**AUTH_DICT)
client_manager = self._clientmanager_class()(
cli_options=cloud_config.CloudConfig(
name='t1',
region='1',
config=dict(
auth_type='password',
auth=auth_dict,
auth=AUTH_DICT,
interface=fakes.INTERFACE,
region_name=fakes.REGION_NAME,
),
@ -306,3 +308,34 @@ class TestClientManager(utils.TestClientManager):
)
self.assertFalse(client_manager.is_service_available('network'))
def test_client_manager_k2k_auth_setup(self):
loader = loading.get_plugin_loader('password')
auth_plugin = loader.load_from_options(**AUTH_DICT)
client_manager = self._clientmanager_class()(
cli_options=cloud_config.CloudConfig(
name='t1',
region='1',
config=dict(
auth_type='password',
auth=AUTH_DICT,
interface=fakes.INTERFACE,
region_name=fakes.REGION_NAME,
service_provider=fakes.SERVICE_PROVIDER_ID,
remote_project_id=fakes.PROJECT_ID
),
auth_plugin=auth_plugin,
),
api_version={
'identity': '3',
},
)
self.assertFalse(client_manager._auth_setup_completed)
client_manager.setup_auth()
# Note(knikolla): Make sure that the auth object is of the correct
# type and that the service_provider is correctly set.
self.assertIsInstance(client_manager.auth, k2k.Keystone2Keystone)
self.assertEqual(client_manager.auth._sp_id, fakes.SERVICE_PROVIDER_ID)
self.assertEqual(client_manager.auth.project_id, fakes.PROJECT_ID)
self.assertTrue(client_manager._auth_setup_completed)