Add ALPN support for listeners

Users can define a list of application layer protocols to be negotiated
over a secure connection. For example, users can limit to HTTP/2 or
to HTTP/2 and HTTP/1.1 but exclude HTTP/1.0.

Depends-On: https://review.opendev.org/#/c/744520/

Change-Id: Ia7afa9268650744710bc486de1302eb36ac3849d
This commit is contained in:
Carlos Goncalves 2020-08-03 00:05:18 +02:00
parent 09f8acc306
commit c6d587c791
6 changed files with 51 additions and 6 deletions

View File

@ -78,7 +78,8 @@ LISTENER_ROWS = (
'client_crl_container_ref', 'client_crl_container_ref',
'allowed_cidrs', 'allowed_cidrs',
'tls_ciphers', 'tls_ciphers',
'tls_versions') 'tls_versions',
'alpn_protocols')
LISTENER_COLUMNS = ( LISTENER_COLUMNS = (
'id', 'id',

View File

@ -190,6 +190,15 @@ class CreateListener(command.ShowOne):
help="Set the TLS protocol version to be used " help="Set the TLS protocol version to be used "
"by the listener (can be set multiple times)." "by the listener (can be set multiple times)."
) )
parser.add_argument(
'--alpn-protocol',
dest='alpn_protocols',
metavar='<alpn_protocols>',
nargs='?',
action='append',
help="Set the ALPN protocol to be used "
"by the listener (can be set multiple times)."
)
return parser return parser
@ -500,6 +509,15 @@ class SetListener(command.Command):
help="Set the TLS protocol version to be used " help="Set the TLS protocol version to be used "
"by the listener (can be set multiple times)." "by the listener (can be set multiple times)."
) )
parser.add_argument(
'--alpn-protocol',
dest='alpn_protocols',
metavar='<alpn_protocols>',
nargs='?',
action='append',
help="Set the ALPN protocol to be used "
"by the listener (can be set multiple times)."
)
return parser return parser
@ -615,6 +633,11 @@ class UnsetListener(command.Command):
action='store_true', action='store_true',
help='Wait for action to complete', help='Wait for action to complete',
) )
parser.add_argument(
'--alpn-protocols',
action='store_true',
help="Clear all ALPN protocols from the listener."
)
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):

View File

@ -227,6 +227,7 @@ def get_listener_attrs(client_manager, parsed_args):
'allowed_cidrs': ('allowed_cidrs', list), 'allowed_cidrs': ('allowed_cidrs', list),
'tls_ciphers': ('tls_ciphers', str), 'tls_ciphers': ('tls_ciphers', str),
'tls_versions': ('tls_versions', list), 'tls_versions': ('tls_versions', list),
'alpn_protocols': ('alpn_protocols', list),
} }
_attrs = vars(parsed_args) _attrs = vars(parsed_args)

View File

@ -80,7 +80,8 @@ LISTENER_ATTRS = {
'client_crl_container_ref': uuidutils.generate_uuid(dashed=True), 'client_crl_container_ref': uuidutils.generate_uuid(dashed=True),
"allowed_cidrs": ['192.0.2.0/24', '198.51.100.0/24'], "allowed_cidrs": ['192.0.2.0/24', '198.51.100.0/24'],
'tls_ciphers': "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256", 'tls_ciphers': "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256",
'tls_versions': ['TLSv1.1', 'TLSv1.2'] 'tls_versions': ['TLSv1.1', 'TLSv1.2'],
'alpn_protocols': ['h2', 'http/1.1']
} }
LOADBALANCER_ATTRS = { LOADBALANCER_ATTRS = {

View File

@ -196,7 +196,11 @@ class TestListenerCreate(TestListener):
'--tls-version', '--tls-version',
self._listener.tls_versions[0], self._listener.tls_versions[0],
'--tls-version', '--tls-version',
self._listener.tls_versions[1]] self._listener.tls_versions[1],
'--alpn-protocol',
self._listener.alpn_protocols[0],
'--alpn-protocol',
self._listener.alpn_protocols[1]]
verifylist = [ verifylist = [
('loadbalancer', 'mock_lb_id'), ('loadbalancer', 'mock_lb_id'),
@ -214,7 +218,9 @@ class TestListenerCreate(TestListener):
('tls_ciphers', ('tls_ciphers',
self._listener.tls_ciphers), self._listener.tls_ciphers),
('tls_versions', ('tls_versions',
self._listener.tls_versions) self._listener.tls_versions),
('alpn_protocols',
self._listener.alpn_protocols),
] ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -300,7 +306,11 @@ class TestListenerSet(TestListener):
'--tls-version', '--tls-version',
self._listener.tls_versions[0], self._listener.tls_versions[0],
'--tls-version', '--tls-version',
self._listener.tls_versions[1]] self._listener.tls_versions[1],
'--alpn-protocol',
self._listener.alpn_protocols[0],
'--alpn-protocol',
self._listener.alpn_protocols[1]]
verifylist = [ verifylist = [
('listener', self._listener.id), ('listener', self._listener.id),
('name', 'new_name'), ('name', 'new_name'),
@ -315,7 +325,8 @@ class TestListenerSet(TestListener):
self._listener.client_crl_container_ref), self._listener.client_crl_container_ref),
('allowed_cidrs', self._listener.allowed_cidrs), ('allowed_cidrs', self._listener.allowed_cidrs),
('tls_ciphers', self._listener.tls_ciphers), ('tls_ciphers', self._listener.tls_ciphers),
('tls_versions', self._listener.tls_versions) ('tls_versions', self._listener.tls_versions),
('alpn_protocols', self._listener.alpn_protocols)
] ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -336,6 +347,7 @@ class TestListenerSet(TestListener):
'allowed_cidrs': self._listener.allowed_cidrs, 'allowed_cidrs': self._listener.allowed_cidrs,
'tls_ciphers': self._listener.tls_ciphers, 'tls_ciphers': self._listener.tls_ciphers,
'tls_versions': self._listener.tls_versions, 'tls_versions': self._listener.tls_versions,
'alpn_protocols': self._listener.alpn_protocols,
}}) }})
@mock.patch('osc_lib.utils.wait_for_status') @mock.patch('osc_lib.utils.wait_for_status')

View File

@ -0,0 +1,7 @@
---
features:
- |
Added ALPN support for listeners with parameter ``--alpn-protocol`` (can
be set multiple times). Users can define a list of application layer
protocols to be negotiated over a secure connection. For example, users
can limit to HTTP/2 or to HTTP/2 and HTTP/1.1 but exclude HTTP/1.0.