Correct generated links when behind an SSL terminating proxy
Adds SSLMiddleware that checks a configurable header to set the correct url_scheme used to generate links when host headers are in use. Change-Id: Id864bb53d175c868fdee58c04fd2ea27ee188e08 Closes-Bug: #1490034
This commit is contained in:
parent
7ac4cb4759
commit
0f183cf2e8
@ -41,6 +41,16 @@ cfg.CONF.register_opts([
|
||||
help='Enable API Maintenance Mode'),
|
||||
cfg.StrOpt('maintenance-mode-role', default='admin',
|
||||
help='Role allowed to bypass maintaince mode'),
|
||||
cfg.StrOpt('secure-proxy-ssl-header',
|
||||
default='X-Forwarded-Proto',
|
||||
help="The HTTP Header that will be used to determine which "
|
||||
"the original request protocol scheme was, even if it was "
|
||||
"removed by an SSL terminating proxy."),
|
||||
cfg.StrOpt('override-proto',
|
||||
default=None,
|
||||
help="A scheme that will be used to override "
|
||||
"the request protocol scheme, even if it was "
|
||||
"set by an SSL terminating proxy.")
|
||||
], group='service:api')
|
||||
|
||||
|
||||
@ -355,3 +365,26 @@ class APIv2ValidationErrorMiddleware(ValidationErrorMiddleware):
|
||||
def __init__(self, application):
|
||||
super(APIv2ValidationErrorMiddleware, self).__init__(application)
|
||||
self.api_version = 'API_v2'
|
||||
|
||||
|
||||
class SSLMiddleware(base.Middleware):
|
||||
"""A middleware that replaces the request wsgi.url_scheme environment
|
||||
variable with the value of HTTP header configured in
|
||||
secure_proxy_ssl_header if exists in the incoming request.
|
||||
This is useful if the server is behind a SSL termination proxy.
|
||||
|
||||
Code nabbed from Heat.
|
||||
"""
|
||||
def __init__(self, application):
|
||||
super(SSLMiddleware, self).__init__(application)
|
||||
LOG.info(_LI('Starting designate ssl middleware'))
|
||||
self.secure_proxy_ssl_header = 'HTTP_{0}'.format(
|
||||
cfg.CONF['service:api'].secure_proxy_ssl_header.upper().
|
||||
replace('-', '_'))
|
||||
self.override = cfg.CONF['service:api'].override_proto
|
||||
|
||||
def process_request(self, request):
|
||||
request.environ['wsgi.url_scheme'] = request.environ.get(
|
||||
self.secure_proxy_ssl_header, request.environ['wsgi.url_scheme'])
|
||||
if self.override:
|
||||
request.environ['wsgi.url_scheme'] = self.override
|
||||
|
@ -143,3 +143,42 @@ class KeystoneContextMiddlewareTest(oslotest.base.BaseTestCase):
|
||||
|
||||
self.app(self.request)
|
||||
self.assertFalse(self.ctxt.edit_managed_records)
|
||||
|
||||
|
||||
class SSLMiddlewareTest(oslotest.base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(SSLMiddlewareTest, self).setUp()
|
||||
self.app = middleware.SSLMiddleware({})
|
||||
|
||||
self.request = FakeRequest()
|
||||
|
||||
def test_bogus_header(self):
|
||||
self.request.environ['wsgi.url_scheme'] = 'http'
|
||||
# If someone sends something bogus, it will infect their self links
|
||||
self.request.environ['HTTP_X_FORWARDED_PROTO'] = 'poo'
|
||||
self.app(self.request)
|
||||
|
||||
self.assertEqual(self.request.environ['wsgi.url_scheme'], 'poo')
|
||||
|
||||
def test_http_header(self):
|
||||
self.request.environ['wsgi.url_scheme'] = ''
|
||||
self.request.environ['HTTP_X_FORWARDED_PROTO'] = 'http'
|
||||
self.app(self.request)
|
||||
|
||||
self.assertEqual(self.request.environ['wsgi.url_scheme'], 'http')
|
||||
|
||||
def test_https_header(self):
|
||||
self.request.environ['wsgi.url_scheme'] = 'http'
|
||||
self.request.environ['HTTP_X_FORWARDED_PROTO'] = 'https'
|
||||
self.app(self.request)
|
||||
|
||||
self.assertEqual(self.request.environ['wsgi.url_scheme'], 'https')
|
||||
|
||||
def test_override_proto(self):
|
||||
self.request.environ['wsgi.url_scheme'] = 'http'
|
||||
self.request.environ['HTTP_X_FORWARDED_PROTO'] = 'https'
|
||||
self.app.override = 'poo'
|
||||
|
||||
self.app(self.request)
|
||||
|
||||
self.assertEqual(self.request.environ['wsgi.url_scheme'], 'poo')
|
||||
|
@ -1,33 +1,36 @@
|
||||
[composite:osapi_dns]
|
||||
use = egg:Paste#urlmap
|
||||
/: osapi_dns_app_versions
|
||||
/: osapi_dns_versions
|
||||
/v1: osapi_dns_v1
|
||||
/v2: osapi_dns_v2
|
||||
/admin: osapi_dns_admin
|
||||
|
||||
[pipeline:osapi_dns_versions]
|
||||
pipeline = maintenance faultwrapper ssl osapi_dns_app_versions
|
||||
|
||||
[app:osapi_dns_app_versions]
|
||||
paste.app_factory = designate.api.versions:factory
|
||||
|
||||
[composite:osapi_dns_v1]
|
||||
use = call:designate.api.middleware:auth_pipeline_factory
|
||||
noauth = request_id noauthcontext maintenance validation_API_v1 faultwrapper normalizeuri osapi_dns_app_v1
|
||||
keystone = request_id authtoken keystonecontext maintenance validation_API_v1 faultwrapper normalizeuri osapi_dns_app_v1
|
||||
noauth = request_id noauthcontext maintenance validation_API_v1 faultwrapper ssl normalizeuri osapi_dns_app_v1
|
||||
keystone = request_id authtoken keystonecontext maintenance validation_API_v1 faultwrapper ssl normalizeuri osapi_dns_app_v1
|
||||
|
||||
[app:osapi_dns_app_v1]
|
||||
paste.app_factory = designate.api.v1:factory
|
||||
|
||||
[composite:osapi_dns_v2]
|
||||
use = call:designate.api.middleware:auth_pipeline_factory
|
||||
noauth = request_id faultwrapper validation_API_v2 noauthcontext maintenance normalizeuri osapi_dns_app_v2
|
||||
keystone = request_id faultwrapper validation_API_v2 authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
|
||||
noauth = request_id faultwrapper ssl validation_API_v2 noauthcontext maintenance normalizeuri osapi_dns_app_v2
|
||||
keystone = request_id faultwrapper ssl validation_API_v2 authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
|
||||
|
||||
[app:osapi_dns_app_v2]
|
||||
paste.app_factory = designate.api.v2:factory
|
||||
|
||||
[composite:osapi_dns_admin]
|
||||
use = call:designate.api.middleware:auth_pipeline_factory
|
||||
noauth = request_id faultwrapper noauthcontext maintenance normalizeuri osapi_dns_app_admin
|
||||
keystone = request_id faultwrapper authtoken keystonecontext maintenance normalizeuri osapi_dns_app_admin
|
||||
noauth = request_id faultwrapper ssl noauthcontext maintenance normalizeuri osapi_dns_app_admin
|
||||
keystone = request_id faultwrapper ssl authtoken keystonecontext maintenance normalizeuri osapi_dns_app_admin
|
||||
|
||||
[app:osapi_dns_app_admin]
|
||||
paste.app_factory = designate.api.admin:factory
|
||||
@ -58,3 +61,6 @@ paste.filter_factory = designate.api.middleware:APIv1ValidationErrorMiddleware.f
|
||||
|
||||
[filter:validation_API_v2]
|
||||
paste.filter_factory = designate.api.middleware:APIv2ValidationErrorMiddleware.factory
|
||||
|
||||
[filter:ssl]
|
||||
paste.filter_factory = designate.api.middleware:SSLMiddleware.factory
|
Loading…
Reference in New Issue
Block a user