Fix accepting 'insert_headers' when unsupported

This patch fixes the Octavia listener API from accepting the
'insert_headers' parameter for protocols that do not support header
insertion.

Change-Id: I4ec2299b64b180f8b2d8f0b8485a6be9fe32d2eb
Story: 2007967
Task: 40464
(cherry picked from commit 08fad74966)
This commit is contained in:
Michael Johnson 2020-07-30 13:32:19 -07:00
parent 60ddeb65c4
commit 0117d21588
4 changed files with 83 additions and 11 deletions

View File

@ -128,6 +128,11 @@ class ListenersController(base.BaseController):
listener_dict.get('insert_headers'))
def _validate_insert_headers(self, insert_header_list, listener_protocol):
if (listener_protocol not in
constants.LISTENER_PROTOCOLS_SUPPORTING_HEADER_INSERTION):
raise exceptions.InvalidOption(
value='insert-headers',
option=('a %s protocol listener.' % listener_protocol))
if list(set(insert_header_list) - (
set(constants.SUPPORTED_HTTP_HEADERS +
constants.SUPPORTED_SSL_HEADERS))):
@ -171,9 +176,9 @@ class ListenersController(base.BaseController):
# Check for UDP compatibility
if (listener_protocol == constants.PROTOCOL_UDP and
self._is_tls_or_insert_header(listener_dict)):
raise exceptions.ValidationException(detail=_(
"%s protocol listener does not support TLS or header "
"insertion.") % constants.PROTOCOL_UDP)
raise exceptions.ValidationException(
detail=_("%s protocol listener does not "
"support TLS.") % constants.PROTOCOL_UDP)
# Check for TLS disabled
if (not CONF.api_settings.allow_tls_terminated_listeners and

View File

@ -781,3 +781,8 @@ VIP_SECURITY_GROUP_PREFIX = 'lb-'
AMP_BASE_PORT_PREFIX = 'octavia-lb-vrrp-'
OCTAVIA_OWNED = 'octavia_owned'
# Sadly in the LBaaS v2 API, header insertions are on the listener objects
# but they should be on the pool. Dealing with it until v3.
LISTENER_PROTOCOLS_SUPPORTING_HEADER_INSERTION = [PROTOCOL_HTTP,
PROTOCOL_TERMINATED_HTTPS]

View File

@ -671,13 +671,10 @@ class TestListener(base.BaseAPITest):
'protocol_port': 6666, 'connection_limit': 10,
'default_tls_container_ref': uuidutils.generate_uuid(),
'sni_container_refs': [sni1, sni2],
'insert_headers': {
"X-Forwarded-Port": "true",
"X-Forwarded-For": "true"},
'insert_headers': {},
'loadbalancer_id': self.lb_id}
expect_error_msg = (
"Validation failure: %s protocol listener does not support TLS or "
"header insertion.") % constants.PROTOCOL_UDP
expect_error_msg = ("Validation failure: %s protocol listener does "
"not support TLS.") % constants.PROTOCOL_UDP
res = self.post(self.LISTENERS_PATH, self._build_body(req_dict),
status=400, expect_errors=True)
self.assertEqual(expect_error_msg, res.json['faultstring'])
@ -1207,6 +1204,33 @@ class TestListener(base.BaseAPITest):
self.create_listener(constants.PROTOCOL_TCP, 80,
self.lb_id, allowed_cidrs=allowed_cidrs)
def _test_negative_create_with_headers(self, protocol):
req_dict = {'name': 'listener1', 'default_pool_id': None,
'description': 'desc1',
'admin_state_up': False,
'protocol': protocol,
'protocol_port': 6666, 'connection_limit': 10,
'insert_headers': {
"X-Forwarded-Port": "true",
"X-Forwarded-For": "true"},
'loadbalancer_id': self.lb_id}
res = self.post(self.LISTENERS_PATH, self._build_body(req_dict),
status=400)
self.assertIn(protocol, res.json['faultstring'])
self.assert_correct_status(lb_id=self.lb_id)
def test_negative_create_HTTPS_with_headers(self):
self._test_negative_create_with_headers(constants.PROTOCOL_HTTPS)
def test_negative_create_PROXY_with_headers(self):
self._test_negative_create_with_headers(constants.PROTOCOL_PROXY)
def test_negative_create_TCP_with_headers(self):
self._test_negative_create_with_headers(constants.PROTOCOL_TCP)
def test_negative_create_UDP_with_headers(self):
self._test_negative_create_with_headers(constants.PROTOCOL_UDP)
def test_update_allowed_cidrs(self):
allowed_cidrs = ['10.0.1.0/24', '10.0.2.0/24']
new_cidrs = ['10.0.1.0/24', '10.0.3.0/24']
@ -2300,7 +2324,9 @@ class TestListener(base.BaseAPITest):
lb_listener = {'protocol': 'HTTP',
'protocol_port': 80,
'loadbalancer_id': self.lb_id,
'insert_headers': {'X-Forwarded-For': 'true'}}
'insert_headers': {'X-Forwarded-For': 'true',
'X-Forwarded-Port': 'true',
'X-Forwarded-Proto': 'true'}}
body = self._build_body(lb_listener)
self.post(self.LISTENERS_PATH, body, status=201)
@ -2345,7 +2371,9 @@ class TestListener(base.BaseAPITest):
constants.PROTOCOL_HTTP, 80, self.lb_id)
self.set_lb_status(self.lb_id)
new_listener = self._build_body(
{'insert_headers': {'X-Forwarded-For': 'true'}})
{'insert_headers': {'X-Forwarded-For': 'true',
'X-Forwarded-Port': 'true',
'X-Forwarded-Proto': 'true'}})
listener_path = self.LISTENER_PATH.format(
listener_id=listener['listener'].get('id'))
update_listener = self.put(
@ -2396,6 +2424,35 @@ class TestListener(base.BaseAPITest):
# the status.
self.put(listener_path, new_listener, status=400).json
def _test_update_protocol_insert_headers_mismatch(self, protocol):
listener = self.create_listener(
protocol, 80, self.lb_id)
self.set_lb_status(self.lb_id)
new_listener = self._build_body(
{'insert_headers': {'X-Forwarded-Port': 'true'}})
listener_path = self.LISTENER_PATH.format(
listener_id=listener['listener'].get('id'))
update_listener = self.put(
listener_path, new_listener, status=400).json
self.assertIn(protocol, update_listener['faultstring'])
self.assert_correct_status(lb_id=self.lb_id)
def test_update_protocol_HTTPS_insert_headers(self):
self._test_update_protocol_insert_headers_mismatch(
constants.PROTOCOL_HTTPS)
def test_update_protocol_PROXY_insert_headers(self):
self._test_update_protocol_insert_headers_mismatch(
constants.PROTOCOL_PROXY)
def test_update_protocol_TCP_insert_headers(self):
self._test_update_protocol_insert_headers_mismatch(
constants.PROTOCOL_TCP)
def test_update_protocol_UDP_insert_headers(self):
self._test_update_protocol_insert_headers_mismatch(
constants.PROTOCOL_UDP)
def _getStats(self, listener_id):
res = self.get(self.LISTENER_PATH.format(
listener_id=listener_id + "/stats"))

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fixed an issue where listener "insert_headers" parameter was accepted for
protocols that do not support header insertion.