diff --git a/glance/context.py b/glance/context.py index a62b301f85..510e55eb0a 100644 --- a/glance/context.py +++ b/glance/context.py @@ -15,10 +15,31 @@ import copy +from keystoneauth1 import session +from keystoneauth1 import token_endpoint +from oslo_config import cfg from oslo_context import context from glance.api import policy +CONF = cfg.CONF + + +def get_ksa_client(context): + """Returns a keystoneauth Adapter using token from context. + + This will return a simple keystoneauth adapter that can be used to + make requests against a remote service using the token provided + (and already authenticated) from the user and stored in a + RequestContext. + + :param context: User request context + :returns: keystoneauth1 Adapter object + """ + auth = token_endpoint.Token(CONF.keystone_authtoken.identity_uri, + context.auth_token) + return session.Session(auth=auth) + class RequestContext(context.RequestContext): """Stores information about the security context. diff --git a/glance/tests/unit/test_context.py b/glance/tests/unit/test_context.py index f3c2b2efbd..04a010e680 100644 --- a/glance/tests/unit/test_context.py +++ b/glance/tests/unit/test_context.py @@ -14,12 +14,17 @@ # under the License. # NOTE(jokke): simplified transition to py3, behaves like py2 xrange +from unittest import mock + +from oslo_config import cfg from six.moves import range from glance import context from glance.tests.unit import utils as unit_utils from glance.tests import utils +CONF = cfg.CONF + def _fake_image(owner, is_public): return { @@ -200,3 +205,22 @@ class TestContext(utils.BaseTestCase): sorted(admin.roles)) self.assertEqual(['foo'], admin.service_catalog) self.assertTrue(admin.is_admin) + + @mock.patch('keystoneauth1.token_endpoint.Token') + @mock.patch('keystoneauth1.session.Session') + def test_get_ksa_client(self, mock_session, mock_token): + # Make sure we can get a keystoneauth1 client from our context + # with the token auth as expected. + ctx = context.RequestContext(auth_token='token') + # NOTE(danms): The auth config group and options are + # dynamically registered. Tickling enough of the relevant + # code to make that happen would significantly inflate the + # amount of code here for no real gain, so we just mock the + # CONF object. + CONF.register_group(cfg.OptGroup('keystone_authtoken')) + with mock.patch.object(CONF, 'keystone_authtoken') as ksat: + ksat.identity_uri = 'http://keystone' + client = context.get_ksa_client(ctx) + self.assertEqual(mock_session.return_value, client) + mock_session.assert_called_once_with(auth=mock_token.return_value) + mock_token.assert_called_once_with('http://keystone', 'token')