Merge "Handle SSL termination proxies for version list"
This commit is contained in:
commit
500fb35e69
|
@ -139,7 +139,13 @@ FILE_OPTIONS = {
|
||||||
'exceeds the maximum length, the operation will fail '
|
'exceeds the maximum length, the operation will fail '
|
||||||
'with an HTTP 403 Forbidden error. If set to false, '
|
'with an HTTP 403 Forbidden error. If set to false, '
|
||||||
'passwords are automatically truncated to the '
|
'passwords are automatically truncated to the '
|
||||||
'maximum length.')],
|
'maximum length.'),
|
||||||
|
cfg.StrOpt('secure_proxy_ssl_header',
|
||||||
|
help='The HTTP header used to determine the scheme for the '
|
||||||
|
'original request, even if it was removed by an SSL '
|
||||||
|
'terminating proxy. Typical value is '
|
||||||
|
'"HTTP_X_FORWARDED_PROTO".'),
|
||||||
|
],
|
||||||
'identity': [
|
'identity': [
|
||||||
cfg.StrOpt('default_domain_id', default='default',
|
cfg.StrOpt('default_domain_id', default='default',
|
||||||
help='This references the domain to use for all '
|
help='This references the domain to use for all '
|
||||||
|
|
|
@ -196,6 +196,16 @@ class Application(BaseApplication):
|
||||||
context['query_string'] = dict(six.iteritems(req.params))
|
context['query_string'] = dict(six.iteritems(req.params))
|
||||||
context['headers'] = dict(six.iteritems(req.headers))
|
context['headers'] = dict(six.iteritems(req.headers))
|
||||||
context['path'] = req.environ['PATH_INFO']
|
context['path'] = req.environ['PATH_INFO']
|
||||||
|
scheme = (None if not CONF.secure_proxy_ssl_header
|
||||||
|
else req.environ.get(CONF.secure_proxy_ssl_header))
|
||||||
|
if scheme:
|
||||||
|
# NOTE(andrey-mp): "wsgi.url_scheme" contains the protocol used
|
||||||
|
# before the proxy removed it ('https' usually). So if
|
||||||
|
# the webob.Request instance is modified in order to use this
|
||||||
|
# scheme instead of the one defined by API, the call to
|
||||||
|
# webob.Request.relative_url() will return a URL with the correct
|
||||||
|
# scheme.
|
||||||
|
req.environ['wsgi.url_scheme'] = scheme
|
||||||
context['host_url'] = req.host_url
|
context['host_url'] = req.host_url
|
||||||
params = req.environ.get(PARAMS_ENV, {})
|
params = req.environ.get(PARAMS_ENV, {})
|
||||||
# authentication and authorization attributes are set as environment
|
# authentication and authorization attributes are set as environment
|
||||||
|
|
|
@ -741,3 +741,52 @@ class VersionInheritEnabledTestCase(tests.TestCase):
|
||||||
|
|
||||||
self.assertThat(jsonutils.loads(resp.body),
|
self.assertThat(jsonutils.loads(resp.body),
|
||||||
tt_matchers.Equals(exp_json_home_data))
|
tt_matchers.Equals(exp_json_home_data))
|
||||||
|
|
||||||
|
|
||||||
|
class VersionBehindSslTestCase(tests.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(VersionBehindSslTestCase, self).setUp()
|
||||||
|
self.load_backends()
|
||||||
|
self.public_app = self.loadapp('keystone', 'main')
|
||||||
|
|
||||||
|
def config_overrides(self):
|
||||||
|
super(VersionBehindSslTestCase, self).config_overrides()
|
||||||
|
self.config_fixture.config(
|
||||||
|
secure_proxy_ssl_header='HTTP_X_FORWARDED_PROTO')
|
||||||
|
|
||||||
|
def _paste_in_port(self, response, port):
|
||||||
|
for link in response['links']:
|
||||||
|
if link['rel'] == 'self':
|
||||||
|
link['href'] = port
|
||||||
|
|
||||||
|
def _get_expected(self, host):
|
||||||
|
expected = VERSIONS_RESPONSE
|
||||||
|
for version in expected['versions']['values']:
|
||||||
|
if version['id'] == 'v3.0':
|
||||||
|
self._paste_in_port(version, host + 'v3/')
|
||||||
|
elif version['id'] == 'v2.0':
|
||||||
|
self._paste_in_port(version, host + 'v2.0/')
|
||||||
|
return expected
|
||||||
|
|
||||||
|
def test_versions_without_headers(self):
|
||||||
|
client = self.client(self.public_app)
|
||||||
|
host_name = 'host-%d' % random.randint(10, 30)
|
||||||
|
host_port = random.randint(10000, 30000)
|
||||||
|
host = 'http://%s:%s/' % (host_name, host_port)
|
||||||
|
resp = client.get(host)
|
||||||
|
self.assertEqual(300, resp.status_int)
|
||||||
|
data = jsonutils.loads(resp.body)
|
||||||
|
expected = self._get_expected(host)
|
||||||
|
self.assertEqual(expected, data)
|
||||||
|
|
||||||
|
def test_versions_with_header(self):
|
||||||
|
client = self.client(self.public_app)
|
||||||
|
host_name = 'host-%d' % random.randint(10, 30)
|
||||||
|
host_port = random.randint(10000, 30000)
|
||||||
|
resp = client.get('http://%s:%s/' % (host_name, host_port),
|
||||||
|
headers={'X-Forwarded-Proto': 'https'})
|
||||||
|
self.assertEqual(300, resp.status_int)
|
||||||
|
data = jsonutils.loads(resp.body)
|
||||||
|
expected = self._get_expected('https://%s:%s/' % (host_name,
|
||||||
|
host_port))
|
||||||
|
self.assertEqual(expected, data)
|
||||||
|
|
Loading…
Reference in New Issue