Merge "Handle SSL termination proxies for version list"

This commit is contained in:
Jenkins 2015-02-05 02:20:37 +00:00 committed by Gerrit Code Review
commit 500fb35e69
3 changed files with 66 additions and 1 deletions

View File

@ -139,7 +139,13 @@ FILE_OPTIONS = {
'exceeds the maximum length, the operation will fail '
'with an HTTP 403 Forbidden error. If set to false, '
'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': [
cfg.StrOpt('default_domain_id', default='default',
help='This references the domain to use for all '

View File

@ -196,6 +196,16 @@ class Application(BaseApplication):
context['query_string'] = dict(six.iteritems(req.params))
context['headers'] = dict(six.iteritems(req.headers))
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
params = req.environ.get(PARAMS_ENV, {})
# authentication and authorization attributes are set as environment

View File

@ -741,3 +741,52 @@ class VersionInheritEnabledTestCase(tests.TestCase):
self.assertThat(jsonutils.loads(resp.body),
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)