Merge "Handle Octavia certificates properly"
This commit is contained in:
commit
e5640f074c
@ -58,3 +58,8 @@ def session_persistence_type_changed(pool, old_pool):
|
|||||||
oldsp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP)):
|
oldsp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP)):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_listener_cert_ref(listener):
|
||||||
|
return listener.get('default_tls_container_id',
|
||||||
|
listener.get('default_tls_container_ref'))
|
||||||
|
@ -52,13 +52,13 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
|
|||||||
nsxpolicy = self.core_plugin.nsxpolicy
|
nsxpolicy = self.core_plugin.nsxpolicy
|
||||||
cert_client = nsxpolicy.certificate
|
cert_client = nsxpolicy.certificate
|
||||||
ssl_client = nsxpolicy.load_balancer.client_ssl_profile
|
ssl_client = nsxpolicy.load_balancer.client_ssl_profile
|
||||||
passphrase = certificate.get_private_key_passphrase()
|
passphrase = certificate.get('passphrase')
|
||||||
if not passphrase:
|
if not passphrase:
|
||||||
passphrase = core_resources.IGNORE
|
passphrase = core_resources.IGNORE
|
||||||
cert_client.create_or_overwrite(
|
cert_client.create_or_overwrite(
|
||||||
cert_href, certificate_id=listener_id,
|
cert_href, certificate_id=listener_id,
|
||||||
pem_encoded=certificate.get_certificate(),
|
pem_encoded=certificate.get('certificate'),
|
||||||
private_key=certificate.get_private_key(),
|
private_key=certificate.get('private_key'),
|
||||||
passphrase=passphrase,
|
passphrase=passphrase,
|
||||||
tags=tags)
|
tags=tags)
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
|
|||||||
kwargs['lb_persistence_profile_id'] = ''
|
kwargs['lb_persistence_profile_id'] = ''
|
||||||
if certificate:
|
if certificate:
|
||||||
ssl_profile_binding = self._upload_certificate(
|
ssl_profile_binding = self._upload_certificate(
|
||||||
listener['id'], listener['default_tls_container_id'], tags,
|
listener['id'], certificate['ref'], tags,
|
||||||
certificate=certificate)
|
certificate=certificate)
|
||||||
if (listener['protocol'] ==
|
if (listener['protocol'] ==
|
||||||
lb_const.LB_PROTOCOL_TERMINATED_HTTPS and
|
lb_const.LB_PROTOCOL_TERMINATED_HTTPS and
|
||||||
@ -304,7 +304,7 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
|
|||||||
"NSX: %s", app_profile_id, e)
|
"NSX: %s", app_profile_id, e)
|
||||||
|
|
||||||
# Delete imported NSX cert if there is any
|
# Delete imported NSX cert if there is any
|
||||||
if listener.get('default_tls_container_id'):
|
if lb_common.get_listener_cert_ref(listener):
|
||||||
cert_client = self.core_plugin.nsxpolicy.certificate
|
cert_client = self.core_plugin.nsxpolicy.certificate
|
||||||
try:
|
try:
|
||||||
cert_client.delete(listener['id'])
|
cert_client.delete(listener['id'])
|
||||||
|
@ -25,8 +25,9 @@ from vmware_nsx.common import locking
|
|||||||
from vmware_nsx.db import nsxv_db
|
from vmware_nsx.db import nsxv_db
|
||||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
|
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
|
||||||
from vmware_nsx.services.lbaas import base_mgr
|
from vmware_nsx.services.lbaas import base_mgr
|
||||||
|
from vmware_nsx.services.lbaas import lb_common
|
||||||
from vmware_nsx.services.lbaas import lb_const
|
from vmware_nsx.services.lbaas import lb_const
|
||||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_v_common
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -132,9 +133,9 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
|
|||||||
return cert_binding['edge_cert_id']
|
return cert_binding['edge_cert_id']
|
||||||
|
|
||||||
request = {
|
request = {
|
||||||
'pemEncoding': certificate.get_certificate(),
|
'pemEncoding': certificate.get('certificate'),
|
||||||
'privateKey': certificate.get_private_key()}
|
'privateKey': certificate.get('private_key')}
|
||||||
passphrase = certificate.get_private_key_passphrase()
|
passphrase = certificate.get('passphrase')
|
||||||
if passphrase:
|
if passphrase:
|
||||||
request['passphrase'] = passphrase
|
request['passphrase'] = passphrase
|
||||||
cert_obj = self.vcns.upload_edge_certificate(edge_id, request)[1]
|
cert_obj = self.vcns.upload_edge_certificate(edge_id, request)[1]
|
||||||
@ -166,7 +167,7 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
|
|||||||
if certificate:
|
if certificate:
|
||||||
try:
|
try:
|
||||||
edge_cert_id = self._upload_certificate(
|
edge_cert_id = self._upload_certificate(
|
||||||
context, edge_id, listener['default_tls_container_id'],
|
context, edge_id, certificate['ref'],
|
||||||
certificate)
|
certificate)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
@ -178,7 +179,7 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
|
|||||||
try:
|
try:
|
||||||
with locking.LockManager.get_lock(edge_id):
|
with locking.LockManager.get_lock(edge_id):
|
||||||
h = (self.vcns.create_app_profile(edge_id, app_profile))[0]
|
h = (self.vcns.create_app_profile(edge_id, app_profile))[0]
|
||||||
app_profile_id = lb_common.extract_resource_id(h['location'])
|
app_profile_id = lb_v_common.extract_resource_id(h['location'])
|
||||||
except vcns_exc.VcnsApiException:
|
except vcns_exc.VcnsApiException:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
completor(success=False)
|
completor(success=False)
|
||||||
@ -193,7 +194,7 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
|
|||||||
try:
|
try:
|
||||||
with locking.LockManager.get_lock(edge_id):
|
with locking.LockManager.get_lock(edge_id):
|
||||||
h = self.vcns.create_vip(edge_id, vse)[0]
|
h = self.vcns.create_vip(edge_id, vse)[0]
|
||||||
edge_vse_id = lb_common.extract_resource_id(h['location'])
|
edge_vse_id = lb_v_common.extract_resource_id(h['location'])
|
||||||
|
|
||||||
nsxv_db.add_nsxv_lbaas_listener_binding(context.session,
|
nsxv_db.add_nsxv_lbaas_listener_binding(context.session,
|
||||||
lb_id,
|
lb_id,
|
||||||
@ -231,19 +232,19 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
|
|||||||
|
|
||||||
edge_cert_id = None
|
edge_cert_id = None
|
||||||
if certificate:
|
if certificate:
|
||||||
if (old_listener['default_tls_container_id'] !=
|
if (lb_common.get_listener_cert_ref(old_listener) !=
|
||||||
new_listener['default_tls_container_id']):
|
lb_common.get_listener_cert_ref(new_listener)):
|
||||||
try:
|
try:
|
||||||
edge_cert_id = self._upload_certificate(
|
edge_cert_id = self._upload_certificate(
|
||||||
context, edge_id,
|
context, edge_id,
|
||||||
new_listener['default_tls_container_id'],
|
certificate['ref'],
|
||||||
certificate)
|
certificate)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
completor(success=False)
|
completor(success=False)
|
||||||
else:
|
else:
|
||||||
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
|
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
|
||||||
context.session, new_listener['default_tls_container_id'],
|
context.session, certificate['ref'],
|
||||||
edge_id)
|
edge_id)
|
||||||
edge_cert_id = cert_binding['edge_cert_id']
|
edge_cert_id = cert_binding['edge_cert_id']
|
||||||
|
|
||||||
|
@ -83,14 +83,14 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
|
|||||||
# If so, use that certificate for ssl binding. Otherwise,
|
# If so, use that certificate for ssl binding. Otherwise,
|
||||||
# create a new certificate on NSX.
|
# create a new certificate on NSX.
|
||||||
cert_ids = tm_client.find_cert_with_pem(
|
cert_ids = tm_client.find_cert_with_pem(
|
||||||
certificate.get_certificate())
|
certificate.get('certificate'))
|
||||||
if cert_ids:
|
if cert_ids:
|
||||||
nsx_cert_id = cert_ids[0]
|
nsx_cert_id = cert_ids[0]
|
||||||
else:
|
else:
|
||||||
nsx_cert_id = tm_client.create_cert(
|
nsx_cert_id = tm_client.create_cert(
|
||||||
certificate.get_certificate(),
|
certificate.get('certificate'),
|
||||||
private_key=certificate.get_private_key(),
|
private_key=certificate.get('private_key'),
|
||||||
passphrase=certificate.get_private_key_passphrase(),
|
passphrase=certificate.get('passphrase'),
|
||||||
tags=tags)
|
tags=tags)
|
||||||
return {
|
return {
|
||||||
'client_ssl_profile_binding': {
|
'client_ssl_profile_binding': {
|
||||||
|
@ -22,8 +22,6 @@ from oslo_log import helpers as log_helpers
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import oslo_messaging as messaging
|
import oslo_messaging as messaging
|
||||||
from oslo_messaging.rpc import dispatcher
|
from oslo_messaging.rpc import dispatcher
|
||||||
import pecan
|
|
||||||
from stevedore import driver as stevedore_driver
|
|
||||||
|
|
||||||
from octavia.api.drivers import utils as oct_utils
|
from octavia.api.drivers import utils as oct_utils
|
||||||
from octavia.db import api as db_apis
|
from octavia.db import api as db_apis
|
||||||
@ -76,7 +74,6 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(NSXOctaviaDriver, self).__init__()
|
super(NSXOctaviaDriver, self).__init__()
|
||||||
self._init_rpc_messaging()
|
self._init_rpc_messaging()
|
||||||
self._init_cert_manager()
|
|
||||||
self.repositories = repositories.Repositories()
|
self.repositories = repositories.Repositories()
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
@log_helpers.log_method_call
|
||||||
@ -88,13 +85,6 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
|
|||||||
version='1.0')
|
version='1.0')
|
||||||
self.client = messaging.RPCClient(transport, target)
|
self.client = messaging.RPCClient(transport, target)
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
|
||||||
def _init_cert_manager(self):
|
|
||||||
self.cert_manager = stevedore_driver.DriverManager(
|
|
||||||
namespace='octavia.cert_manager',
|
|
||||||
name=cfg.CONF.certificates.cert_manager,
|
|
||||||
invoke_on_load=True).driver
|
|
||||||
|
|
||||||
def get_obj_project_id(self, obj_type, obj_dict):
|
def get_obj_project_id(self, obj_type, obj_dict):
|
||||||
if obj_dict.get('project_id'):
|
if obj_dict.get('project_id'):
|
||||||
return obj_dict['project_id']
|
return obj_dict['project_id']
|
||||||
@ -309,7 +299,6 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
|
|||||||
# Generate the default pool object
|
# Generate the default pool object
|
||||||
obj_dict['default_pool'] = self._get_pool_dict(
|
obj_dict['default_pool'] = self._get_pool_dict(
|
||||||
obj_dict['default_pool_id'], is_update, project_id)
|
obj_dict['default_pool_id'], is_update, project_id)
|
||||||
# TODO(asarfaty): add default_tls_container_id
|
|
||||||
|
|
||||||
elif obj_type == 'Pool':
|
elif obj_type == 'Pool':
|
||||||
if 'listener' not in obj_dict:
|
if 'listener' not in obj_dict:
|
||||||
@ -395,15 +384,21 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
|
|||||||
'new_loadbalancer': new_dict}
|
'new_loadbalancer': new_dict}
|
||||||
self.client.cast({}, 'loadbalancer_update', **kw)
|
self.client.cast({}, 'loadbalancer_update', **kw)
|
||||||
|
|
||||||
|
def _create_lb_certificate(self, listener_dict):
|
||||||
|
# Extract Octavia certificate data into a dict which is readable by
|
||||||
|
# the listener_mgr
|
||||||
|
if listener_dict.get('default_tls_container_ref'):
|
||||||
|
cert_data = listener_dict.get('default_tls_container_data', {})
|
||||||
|
return {'ref': listener_dict.get('default_tls_container_ref'),
|
||||||
|
'certificate': cert_data.get('certificate'),
|
||||||
|
'private_key': cert_data.get('private_key'),
|
||||||
|
'passphrase': cert_data.get('passphrase')}
|
||||||
|
|
||||||
# Listener
|
# Listener
|
||||||
@log_helpers.log_method_call
|
@log_helpers.log_method_call
|
||||||
def listener_create(self, listener):
|
def listener_create(self, listener):
|
||||||
cert = None
|
|
||||||
dict_list = self.obj_to_dict(listener)
|
dict_list = self.obj_to_dict(listener)
|
||||||
if dict_list.get('tls_certificate_id'):
|
cert = self._create_lb_certificate(dict_list)
|
||||||
context = pecan.request.context.get('octavia_context')
|
|
||||||
cert = self.cert_manager.get_cert(context,
|
|
||||||
dict_list['tls_certificate_id'])
|
|
||||||
kw = {'listener': dict_list, 'cert': cert}
|
kw = {'listener': dict_list, 'cert': cert}
|
||||||
self.client.cast({}, 'listener_create', **kw)
|
self.client.cast({}, 'listener_create', **kw)
|
||||||
|
|
||||||
@ -419,11 +414,7 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
|
|||||||
new_dict.update(self.obj_to_dict(
|
new_dict.update(self.obj_to_dict(
|
||||||
new_listener, is_update=True,
|
new_listener, is_update=True,
|
||||||
project_id=old_dict.get('project_id')))
|
project_id=old_dict.get('project_id')))
|
||||||
cert = None
|
cert = self._create_lb_certificate(new_dict)
|
||||||
if new_dict.get('tls_certificate_id'):
|
|
||||||
context = pecan.request.context.get('octavia_context')
|
|
||||||
cert = self.cert_manager.get_cert(context,
|
|
||||||
new_dict['tls_certificate_id'])
|
|
||||||
kw = {'old_listener': old_dict,
|
kw = {'old_listener': old_dict,
|
||||||
'new_listener': new_dict,
|
'new_listener': new_dict,
|
||||||
'cert': cert}
|
'cert': cert}
|
||||||
|
@ -47,8 +47,7 @@ class TestNsxProviderDriver(testtools.TestCase):
|
|||||||
if not code_ok:
|
if not code_ok:
|
||||||
return
|
return
|
||||||
# init the NSX driver without the RPC & certificate
|
# init the NSX driver without the RPC & certificate
|
||||||
with mock.patch(DRIVER + '._init_rpc_messaging'), \
|
with mock.patch(DRIVER + '._init_rpc_messaging'):
|
||||||
mock.patch(DRIVER + '._init_cert_manager'):
|
|
||||||
self.driver = driver.NSXOctaviaDriver()
|
self.driver = driver.NSXOctaviaDriver()
|
||||||
self.driver.client = mock.Mock()
|
self.driver.client = mock.Mock()
|
||||||
|
|
||||||
@ -66,6 +65,11 @@ class TestNsxProviderDriver(testtools.TestCase):
|
|||||||
self.l7rule_id = uuidutils.generate_uuid()
|
self.l7rule_id = uuidutils.generate_uuid()
|
||||||
self.project_id = uuidutils.generate_uuid()
|
self.project_id = uuidutils.generate_uuid()
|
||||||
self.default_tls_container_ref = uuidutils.generate_uuid()
|
self.default_tls_container_ref = uuidutils.generate_uuid()
|
||||||
|
self.default_tls_container_data = {
|
||||||
|
'ref': self.default_tls_container_ref,
|
||||||
|
'certificate': 'cert_text',
|
||||||
|
'private_key': 'pk_text',
|
||||||
|
'passphrase': 'pp_text'}
|
||||||
self.sni_container_ref_1 = uuidutils.generate_uuid()
|
self.sni_container_ref_1 = uuidutils.generate_uuid()
|
||||||
self.sni_container_ref_2 = uuidutils.generate_uuid()
|
self.sni_container_ref_2 = uuidutils.generate_uuid()
|
||||||
|
|
||||||
@ -134,7 +138,7 @@ class TestNsxProviderDriver(testtools.TestCase):
|
|||||||
connection_limit=5,
|
connection_limit=5,
|
||||||
default_pool=self.ref_pool,
|
default_pool=self.ref_pool,
|
||||||
default_pool_id=self.pool_id,
|
default_pool_id=self.pool_id,
|
||||||
default_tls_container_data='default_cert_data',
|
default_tls_container_data=self.default_tls_container_data,
|
||||||
default_tls_container_ref=self.default_tls_container_ref,
|
default_tls_container_ref=self.default_tls_container_ref,
|
||||||
description='The listener',
|
description='The listener',
|
||||||
insert_headers={'X-Forwarded-For': 'true'},
|
insert_headers={'X-Forwarded-For': 'true'},
|
||||||
@ -222,8 +226,9 @@ class TestNsxProviderDriver(testtools.TestCase):
|
|||||||
def test_listener_create(self):
|
def test_listener_create(self):
|
||||||
with mock.patch.object(self.driver.client, 'cast') as cast_method:
|
with mock.patch.object(self.driver.client, 'cast') as cast_method:
|
||||||
self.driver.listener_create(self.ref_listener)
|
self.driver.listener_create(self.ref_listener)
|
||||||
cast_method.assert_called_with({}, 'listener_create', cert=None,
|
cast_method.assert_called_with(
|
||||||
listener=mock.ANY)
|
{}, 'listener_create', cert=self.default_tls_container_data,
|
||||||
|
listener=mock.ANY)
|
||||||
driver_obj = cast_method.call_args[1]['listener']
|
driver_obj = cast_method.call_args[1]['listener']
|
||||||
self.assertIn('id', driver_obj)
|
self.assertIn('id', driver_obj)
|
||||||
self.assertIn('project_id', driver_obj)
|
self.assertIn('project_id', driver_obj)
|
||||||
@ -255,9 +260,11 @@ class TestNsxProviderDriver(testtools.TestCase):
|
|||||||
def test_listener_update(self):
|
def test_listener_update(self):
|
||||||
with mock.patch.object(self.driver.client, 'cast') as cast_method:
|
with mock.patch.object(self.driver.client, 'cast') as cast_method:
|
||||||
self.driver.listener_update(self.ref_listener, self.ref_listener)
|
self.driver.listener_update(self.ref_listener, self.ref_listener)
|
||||||
cast_method.assert_called_with({}, 'listener_update', cert=None,
|
cast_method.assert_called_with(
|
||||||
old_listener=mock.ANY,
|
{}, 'listener_update',
|
||||||
new_listener=mock.ANY)
|
cert=self.default_tls_container_data,
|
||||||
|
old_listener=mock.ANY,
|
||||||
|
new_listener=mock.ANY)
|
||||||
driver_obj = cast_method.call_args[1]['new_listener']
|
driver_obj = cast_method.call_args[1]['new_listener']
|
||||||
self.assertIn('id', driver_obj)
|
self.assertIn('id', driver_obj)
|
||||||
self.assertIn('project_id', driver_obj)
|
self.assertIn('project_id', driver_obj)
|
||||||
|
Loading…
Reference in New Issue
Block a user