Adds a pool re-encryption scenario test
This patch adds a pool re-encryption scenario test that covers TLS enabled pools, pools with CA validation, and pools with certificate revocation lists. Co-Authored-By: Gregory Thiemonge <gthiemon@redhat.com> Change-Id: Ib3d8d766b8eb358b48da74f8634f6d24510394b4
This commit is contained in:
parent
41b3aac6b0
commit
74b6f2ff50
@ -21,6 +21,7 @@ AVAILABILITY_ZONE_PROFILE_ID = 'availability_zone_profile_id'
|
||||
ADMIN_STATE_UP = 'admin_state_up'
|
||||
BYTES_IN = 'bytes_in'
|
||||
BYTES_OUT = 'bytes_out'
|
||||
CA_TLS_CONTAINER_REF = 'ca_tls_container_ref'
|
||||
CLIENT_AUTHENTICATION = 'client_authentication'
|
||||
CLIENT_AUTH_NONE = 'NONE'
|
||||
CLIENT_AUTH_OPTIONAL = 'OPTIONAL'
|
||||
@ -28,6 +29,7 @@ CLIENT_AUTH_MANDATORY = 'MANDATORY'
|
||||
CLIENT_CA_TLS_CONTAINER_REF = 'client_ca_tls_container_ref'
|
||||
CLIENT_CRL_CONTAINER_REF = 'client_crl_container_ref'
|
||||
CREATED_AT = 'created_at'
|
||||
CRL_CONTAINER_REF = 'crl_container_ref'
|
||||
DESCRIPTION = 'description'
|
||||
FLAVOR_DATA = 'flavor_data'
|
||||
FLAVOR_ID = 'flavor_id'
|
||||
@ -63,6 +65,7 @@ TIMEOUT_CLIENT_DATA = 'timeout_client_data'
|
||||
TIMEOUT_MEMBER_CONNECT = 'timeout_member_connect'
|
||||
TIMEOUT_MEMBER_DATA = 'timeout_member_data'
|
||||
TIMEOUT_TCP_INSPECT = 'timeout_tcp_inspect'
|
||||
TLS_ENABLED = 'tls_enabled'
|
||||
DEFAULT_TLS_CONTAINER_REF = 'default_tls_container_ref'
|
||||
SNI_CONTAINER_REFS = 'sni_container_refs'
|
||||
DEFAULT_POOL_ID = 'default_pool_id'
|
||||
|
@ -171,11 +171,14 @@ func httpsServe(port int, id string, cert tls.Certificate,
|
||||
tls.CurveP256},
|
||||
PreferServerCipherSuites: true,
|
||||
CipherSuites: []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
},
|
||||
NextProtos: []string{"h2", "http/1.1", "http/1.0"},
|
||||
}
|
||||
} else {
|
||||
tlsConfig = &tls.Config{
|
||||
@ -186,6 +189,8 @@ func httpsServe(port int, id string, cert tls.Certificate,
|
||||
tls.CurveP256},
|
||||
PreferServerCipherSuites: true,
|
||||
CipherSuites: []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
@ -200,8 +205,6 @@ func httpsServe(port int, id string, cert tls.Certificate,
|
||||
Addr: portStr,
|
||||
Handler: mux,
|
||||
TLSConfig: tlsConfig,
|
||||
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn,
|
||||
http.Handler), 0),
|
||||
}
|
||||
log.Fatal(srv.ListenAndServeTLS(serverCertPem, serverKeyPem))
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ class PoolClient(base_client.BaseLBaaSClient):
|
||||
listener_id=Unset, name=Unset, description=Unset,
|
||||
tags=Unset,
|
||||
admin_state_up=Unset, session_persistence=Unset,
|
||||
ca_tls_container_ref=Unset, crl_container_ref=Unset,
|
||||
tls_enabled=Unset, tls_container_ref=Unset,
|
||||
return_object_only=True):
|
||||
"""Create a pool.
|
||||
|
||||
@ -47,6 +49,18 @@ class PoolClient(base_client.BaseLBaaSClient):
|
||||
:param session_persistence: A JSON object specifying the session
|
||||
persistence for the pool or null for no
|
||||
session persistence.
|
||||
:param ca_tls_container_ref: The key manager ref for a secret
|
||||
containing the PEM encoded CA certificate
|
||||
to validate pool members against.
|
||||
:param crl_container_ref: The key manager ref for a secret containing
|
||||
the PEM encoded CRL to use when validating
|
||||
pool members.
|
||||
:param tls_enabled: A boolean, True when the pool should connect to
|
||||
members using TLS.
|
||||
:param tls_container_ref: The key manager ref for a secret containing
|
||||
a PKCS12 bundle with the client
|
||||
authentication certificate and key used
|
||||
when connecting to pool members over TLS.
|
||||
:param return_object_only: If True, the response returns the object
|
||||
inside the root tag. False returns the full
|
||||
response from the API.
|
||||
@ -164,7 +178,9 @@ class PoolClient(base_client.BaseLBaaSClient):
|
||||
@skip_if_not_implemented
|
||||
def update_pool(self, pool_id, lb_algorithm=Unset, name=Unset,
|
||||
description=Unset, tags=Unset, admin_state_up=Unset,
|
||||
session_persistence=Unset, return_object_only=True):
|
||||
session_persistence=Unset, ca_tls_container_ref=Unset,
|
||||
crl_container_ref=Unset, tls_enabled=Unset,
|
||||
tls_container_ref=Unset, return_object_only=True):
|
||||
"""Update a pool.
|
||||
|
||||
:param pool_id: The pool ID to update.
|
||||
@ -177,6 +193,18 @@ class PoolClient(base_client.BaseLBaaSClient):
|
||||
:param session_persistence: A JSON object specifying the session
|
||||
persistence for the pool or null for no
|
||||
session persistence.
|
||||
:param ca_tls_container_ref: The key manager ref for a secret
|
||||
containing the PEM encoded CA certificate
|
||||
to validate pool members against.
|
||||
:param crl_container_ref: The key manager ref for a secret containing
|
||||
the PEM encoded CRL to use when validating
|
||||
pool members.
|
||||
:param tls_enabled: A boolean, True when the pool should connect to
|
||||
members using TLS.
|
||||
:param tls_container_ref: The key manager ref for a secret containing
|
||||
a PKCS12 bundle with the client
|
||||
authentication certificate and key used
|
||||
when connecting to pool members over TLS.
|
||||
:param return_object_only: If True, the response returns the object
|
||||
inside the root tag. False returns the full
|
||||
response from the API.
|
||||
|
@ -98,6 +98,23 @@ class TLSWithBarbicanTest(test_base.LoadBalancerBaseTestWithCompute):
|
||||
|
||||
return new_cert, new_key, new_secret_ref
|
||||
|
||||
@classmethod
|
||||
def _load_pool_pki(cls):
|
||||
# Create the pkcs12 bundle
|
||||
pkcs12 = cert_utils.generate_pkcs12_bundle(cls.member_client_cert,
|
||||
cls.member_client_key)
|
||||
LOG.debug('Pool client PKCS12 bundle: %s', base64.b64encode(pkcs12))
|
||||
|
||||
cls.pool_client_ref = cls._store_secret(cls.barbican_mgr, pkcs12)
|
||||
|
||||
cls.pool_CA_ref = cls._store_secret(
|
||||
cls.barbican_mgr,
|
||||
cls.member_ca_cert.public_bytes(serialization.Encoding.PEM))
|
||||
|
||||
cls.pool_CRL_ref = cls._store_secret(
|
||||
cls.barbican_mgr,
|
||||
cls.member_crl.public_bytes(serialization.Encoding.PEM))
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
"""Setup resources needed by the tests."""
|
||||
@ -174,6 +191,8 @@ class TLSWithBarbicanTest(test_base.LoadBalancerBaseTestWithCompute):
|
||||
cls.barbican_mgr,
|
||||
cls.client_crl.public_bytes(serialization.Encoding.PEM))
|
||||
|
||||
cls._load_pool_pki()
|
||||
|
||||
# Setup a load balancer for the tests to use
|
||||
lb_name = data_utils.rand_name("lb_member_lb1-tls")
|
||||
lb_kwargs = {const.PROVIDER: CONF.load_balancer.provider,
|
||||
@ -1197,3 +1216,149 @@ class TLSWithBarbicanTest(test_base.LoadBalancerBaseTestWithCompute):
|
||||
def test_http_1_1_tls_traffic(self):
|
||||
self._test_http_versions_tls_traffic(
|
||||
'HTTP/1.1', ['http/1.1', 'http/1.0'])
|
||||
|
||||
@decorators.idempotent_id('ee0faf71-d11e-4323-8673-e5e15779749b')
|
||||
def test_pool_reencryption(self):
|
||||
if not self.mem_listener_client.is_version_supported(
|
||||
self.api_version, '2.8'):
|
||||
raise self.skipException('Pool re-encryption is only available on '
|
||||
'Octavia API version 2.8 or newer.')
|
||||
pool_name = data_utils.rand_name("lb_member_pool1-tls-reencrypt")
|
||||
pool_kwargs = {
|
||||
const.NAME: pool_name,
|
||||
const.PROTOCOL: const.HTTP,
|
||||
const.LB_ALGORITHM: self.lb_algorithm,
|
||||
const.LOADBALANCER_ID: self.lb_id,
|
||||
const.TLS_ENABLED: True
|
||||
}
|
||||
pool = self.mem_pool_client.create_pool(**pool_kwargs)
|
||||
pool_id = pool[const.ID]
|
||||
|
||||
waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
|
||||
self.lb_id, const.PROVISIONING_STATUS,
|
||||
const.ACTIVE,
|
||||
CONF.load_balancer.build_interval,
|
||||
CONF.load_balancer.build_timeout)
|
||||
|
||||
# Set up Member 1 for Webserver 1
|
||||
member1_name = data_utils.rand_name("lb_member_member1-tls-reencrypt")
|
||||
member1_kwargs = {
|
||||
const.POOL_ID: pool_id,
|
||||
const.NAME: member1_name,
|
||||
const.ADMIN_STATE_UP: True,
|
||||
const.ADDRESS: self.webserver1_ip,
|
||||
const.PROTOCOL_PORT: 443,
|
||||
}
|
||||
if self.lb_member_1_subnet:
|
||||
member1_kwargs[const.SUBNET_ID] = self.lb_member_1_subnet[const.ID]
|
||||
|
||||
self.mem_member_client.create_member(**member1_kwargs)
|
||||
waiters.wait_for_status(
|
||||
self.mem_lb_client.show_loadbalancer, self.lb_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
|
||||
# Set up Member 2 for Webserver 2
|
||||
member2_name = data_utils.rand_name("lb_member_member2-tls-reencrypt")
|
||||
member2_kwargs = {
|
||||
const.POOL_ID: pool_id,
|
||||
const.NAME: member2_name,
|
||||
const.ADMIN_STATE_UP: True,
|
||||
const.ADDRESS: self.webserver2_ip,
|
||||
const.PROTOCOL_PORT: 443,
|
||||
}
|
||||
if self.lb_member_2_subnet:
|
||||
member2_kwargs[const.SUBNET_ID] = self.lb_member_2_subnet[const.ID]
|
||||
|
||||
self.mem_member_client.create_member(**member2_kwargs)
|
||||
waiters.wait_for_status(
|
||||
self.mem_lb_client.show_loadbalancer, self.lb_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
|
||||
listener_name = data_utils.rand_name(
|
||||
"lb_member_listener1-tls-reencrypt")
|
||||
listener_kwargs = {
|
||||
const.NAME: listener_name,
|
||||
const.PROTOCOL: const.HTTP,
|
||||
const.PROTOCOL_PORT: '84',
|
||||
const.LOADBALANCER_ID: self.lb_id,
|
||||
const.DEFAULT_POOL_ID: pool_id,
|
||||
}
|
||||
listener = self.mem_listener_client.create_listener(**listener_kwargs)
|
||||
self.listener_id = listener[const.ID]
|
||||
|
||||
waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
|
||||
self.lb_id, const.PROVISIONING_STATUS,
|
||||
const.ACTIVE,
|
||||
CONF.load_balancer.build_interval,
|
||||
CONF.load_balancer.build_timeout)
|
||||
|
||||
# Test with no CA validation
|
||||
self.check_members_balanced(self.lb_vip_address, protocol=const.HTTP,
|
||||
protocol_port=84)
|
||||
|
||||
# Test with CA validation - invalid CA
|
||||
pool_update_kwargs = {
|
||||
const.CA_TLS_CONTAINER_REF: self.client_ca_cert_ref
|
||||
}
|
||||
|
||||
self.mem_pool_client.update_pool(pool_id, **pool_update_kwargs)
|
||||
|
||||
waiters.wait_for_status(
|
||||
self.mem_lb_client.show_loadbalancer, self.lb_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
waiters.wait_for_status(
|
||||
self.mem_pool_client.show_pool, pool_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
|
||||
url = 'http://{0}:84'.format(self.lb_vip_address)
|
||||
self.validate_URL_response(url, expected_status_code=503)
|
||||
|
||||
# Test with CA validation - valid CA
|
||||
pool_update_kwargs = {
|
||||
const.CA_TLS_CONTAINER_REF: self.pool_CA_ref
|
||||
}
|
||||
|
||||
self.mem_pool_client.update_pool(pool_id, **pool_update_kwargs)
|
||||
|
||||
waiters.wait_for_status(
|
||||
self.mem_lb_client.show_loadbalancer, self.lb_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
waiters.wait_for_status(
|
||||
self.mem_pool_client.show_pool, pool_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
|
||||
self.check_members_balanced(self.lb_vip_address, protocol=const.HTTP,
|
||||
protocol_port=84)
|
||||
|
||||
# Test with CRL including one webserver certificate revoked
|
||||
pool_update_kwargs = {
|
||||
const.CRL_CONTAINER_REF: self.pool_CRL_ref
|
||||
}
|
||||
|
||||
self.mem_pool_client.update_pool(pool_id, **pool_update_kwargs)
|
||||
|
||||
waiters.wait_for_status(
|
||||
self.mem_lb_client.show_loadbalancer, self.lb_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
waiters.wait_for_status(
|
||||
self.mem_pool_client.show_pool, pool_id,
|
||||
const.PROVISIONING_STATUS, const.ACTIVE,
|
||||
CONF.load_balancer.check_interval,
|
||||
CONF.load_balancer.check_timeout)
|
||||
|
||||
self.check_members_balanced(self.lb_vip_address, protocol=const.HTTP,
|
||||
protocol_port=84, traffic_member_count=1)
|
||||
|
@ -567,6 +567,19 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest):
|
||||
cls.lb_mem_SGr_client.delete_security_group_rule,
|
||||
cls.lb_mem_SGr_client.show_security_group_rule,
|
||||
SGr['id'])
|
||||
# Create a security group rule to allow 443 (test webservers)
|
||||
SGr = cls.lb_mem_SGr_client.create_security_group_rule(
|
||||
direction='ingress',
|
||||
security_group_id=cls.lb_member_sec_group['id'],
|
||||
protocol='tcp',
|
||||
ethertype='IPv4',
|
||||
port_range_min=443,
|
||||
port_range_max=443)['security_group_rule']
|
||||
cls.addClassResourceCleanup(
|
||||
waiters.wait_for_not_found,
|
||||
cls.lb_mem_SGr_client.delete_security_group_rule,
|
||||
cls.lb_mem_SGr_client.show_security_group_rule,
|
||||
SGr['id'])
|
||||
# Create a security group rule to allow UDP 9999 (test webservers)
|
||||
# Port 9999 is used to illustrate health monitor ERRORs on closed
|
||||
# ports.
|
||||
@ -623,6 +636,19 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest):
|
||||
cls.lb_mem_SGr_client.delete_security_group_rule,
|
||||
cls.lb_mem_SGr_client.show_security_group_rule,
|
||||
SGr['id'])
|
||||
# Create a security group rule to allow 443 (test webservers)
|
||||
SGr = cls.lb_mem_SGr_client.create_security_group_rule(
|
||||
direction='ingress',
|
||||
security_group_id=cls.lb_member_sec_group['id'],
|
||||
protocol='tcp',
|
||||
ethertype='IPv6',
|
||||
port_range_min=443,
|
||||
port_range_max=443)['security_group_rule']
|
||||
cls.addClassResourceCleanup(
|
||||
waiters.wait_for_not_found,
|
||||
cls.lb_mem_SGr_client.delete_security_group_rule,
|
||||
cls.lb_mem_SGr_client.show_security_group_rule,
|
||||
SGr['id'])
|
||||
# Create a security group rule to allow 22 (ssh)
|
||||
SGr = cls.lb_mem_SGr_client.create_security_group_rule(
|
||||
direction='ingress',
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added scenario test coverage for pool re-encryption.
|
Loading…
Reference in New Issue
Block a user