Allow identity plugins to discover relative version urls
When using a reverse proxy or TLS terminator it can be really hard to correctly specify a URL in version discovery that is correct for all situations. Make it so that a relative URL in a discovery document is joined to the queried URL to always return a fully qualified URL to the identity plugins. Change-Id: Ia08538ccf00c9063dc0d284c5ece9a969c15500a Closes-Bug: #1614304
This commit is contained in:
parent
7f13a4f570
commit
fe7ea40ea5
|
@ -18,6 +18,7 @@ import threading
|
|||
|
||||
from positional import positional
|
||||
import six
|
||||
from six.moves import urllib
|
||||
|
||||
from keystoneauth1 import _utils as utils
|
||||
from keystoneauth1 import access
|
||||
|
@ -239,7 +240,14 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin):
|
|||
'Fallback to using that endpoint as the base url.',
|
||||
url)
|
||||
else:
|
||||
url = disc.url_for(version, **allow)
|
||||
# NOTE(jamielennox): urljoin allows the url to be relative or even
|
||||
# protocol-less. The additional trailing '/' make urljoin respect
|
||||
# the current path as canonical even if the url doesn't include it.
|
||||
# for example a "v2" path from http://host/admin should resolve as
|
||||
# http://host/admin/v2 where it would otherwise be host/v2.
|
||||
# This has no effect on absolute urls returned from url_for.
|
||||
url_for = disc.url_for(version, **allow)
|
||||
url = urllib.parse.urljoin(hacked_url.rstrip('/') + '/', url_for)
|
||||
|
||||
return url
|
||||
|
||||
|
|
|
@ -31,9 +31,10 @@ class CommonIdentityTests(object):
|
|||
TEST_ROOT_URL = 'http://127.0.0.1:5000/'
|
||||
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
|
||||
|
||||
TEST_COMPUTE_PUBLIC = 'http://nova/novapi/public'
|
||||
TEST_COMPUTE_INTERNAL = 'http://nova/novapi/internal'
|
||||
TEST_COMPUTE_ADMIN = 'http://nova/novapi/admin'
|
||||
TEST_COMPUTE_BASE = 'http://nova'
|
||||
TEST_COMPUTE_PUBLIC = TEST_COMPUTE_BASE + '/novapi/public'
|
||||
TEST_COMPUTE_INTERNAL = TEST_COMPUTE_BASE + '/novapi/internal'
|
||||
TEST_COMPUTE_ADMIN = TEST_COMPUTE_BASE + '/novapi/admin'
|
||||
|
||||
TEST_PASS = uuid.uuid4().hex
|
||||
|
||||
|
@ -181,6 +182,77 @@ class CommonIdentityTests(object):
|
|||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(body, resp.text)
|
||||
|
||||
def test_discovering_with_relative_link(self):
|
||||
# need to construct list this way for relative
|
||||
disc = fixture.DiscoveryList(v2=False, v3=False)
|
||||
disc.add_v2('v2.0')
|
||||
disc.add_v3('v3')
|
||||
|
||||
self.stub_url('GET', [], base_url=self.TEST_COMPUTE_ADMIN, json=disc)
|
||||
|
||||
a = self.create_auth_plugin()
|
||||
s = session.Session(auth=a)
|
||||
|
||||
endpoint_v2 = s.get_endpoint(service_type='compute',
|
||||
interface='admin',
|
||||
version=(2, 0))
|
||||
|
||||
endpoint_v3 = s.get_endpoint(service_type='compute',
|
||||
interface='admin',
|
||||
version=(3, 0))
|
||||
|
||||
self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v2.0', endpoint_v2)
|
||||
self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v3', endpoint_v3)
|
||||
|
||||
def test_discovering_with_relative_anchored_link(self):
|
||||
# need to construct list this way for relative
|
||||
disc = fixture.DiscoveryList(v2=False, v3=False)
|
||||
disc.add_v2('/v2.0')
|
||||
disc.add_v3('/v3')
|
||||
|
||||
self.stub_url('GET', [], base_url=self.TEST_COMPUTE_ADMIN, json=disc)
|
||||
|
||||
a = self.create_auth_plugin()
|
||||
s = session.Session(auth=a)
|
||||
|
||||
endpoint_v2 = s.get_endpoint(service_type='compute',
|
||||
interface='admin',
|
||||
version=(2, 0))
|
||||
|
||||
endpoint_v3 = s.get_endpoint(service_type='compute',
|
||||
interface='admin',
|
||||
version=(3, 0))
|
||||
|
||||
# by the nature of urljoin a relative link with a /path gets joined
|
||||
# back to the root.
|
||||
self.assertEqual(self.TEST_COMPUTE_BASE + '/v2.0', endpoint_v2)
|
||||
self.assertEqual(self.TEST_COMPUTE_BASE + '/v3', endpoint_v3)
|
||||
|
||||
def test_discovering_with_protocol_relative(self):
|
||||
# strip up to and including the : leaving //host/path
|
||||
path = self.TEST_COMPUTE_ADMIN[self.TEST_COMPUTE_ADMIN.find(':') + 1:]
|
||||
|
||||
disc = fixture.DiscoveryList(v2=False, v3=False)
|
||||
disc.add_v2(path + '/v2.0')
|
||||
disc.add_v3(path + '/v3')
|
||||
|
||||
self.stub_url('GET', [], base_url=self.TEST_COMPUTE_ADMIN, json=disc)
|
||||
|
||||
a = self.create_auth_plugin()
|
||||
s = session.Session(auth=a)
|
||||
|
||||
endpoint_v2 = s.get_endpoint(service_type='compute',
|
||||
interface='admin',
|
||||
version=(2, 0))
|
||||
|
||||
endpoint_v3 = s.get_endpoint(service_type='compute',
|
||||
interface='admin',
|
||||
version=(3, 0))
|
||||
|
||||
# ensures that the http is carried over from the lookup url
|
||||
self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v2.0', endpoint_v2)
|
||||
self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v3', endpoint_v3)
|
||||
|
||||
def test_asking_for_auth_endpoint_ignores_checks(self):
|
||||
a = self.create_auth_plugin()
|
||||
s = session.Session(auth=a)
|
||||
|
|
Loading…
Reference in New Issue