Browse Source

Merge "Handle Octavia certificates properly" into stable/stein

changes/79/727079/1
Zuul 2 months ago
committed by Gerrit Code Review
parent
commit
2d2546ed9e
7 changed files with 66 additions and 49 deletions
  1. +5
    -0
      vmware_nsx/services/lbaas/lb_common.py
  2. +13
    -0
      vmware_nsx/services/lbaas/lb_helper.py
  3. +5
    -5
      vmware_nsx/services/lbaas/nsx_p/implementation/listener_mgr.py
  4. +12
    -11
      vmware_nsx/services/lbaas/nsx_v/implementation/listener_mgr.py
  5. +4
    -4
      vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py
  6. +12
    -21
      vmware_nsx/services/lbaas/octavia/octavia_driver.py
  7. +15
    -8
      vmware_nsx/tests/unit/services/lbaas/test_octavia_driver.py

+ 5
- 0
vmware_nsx/services/lbaas/lb_common.py View File

@@ -58,3 +58,8 @@ def session_persistence_type_changed(pool, old_pool):
oldsp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP)):
return True
return False


def get_listener_cert_ref(listener):
return listener.get('default_tls_container_id',
listener.get('default_tls_container_ref'))

+ 13
- 0
vmware_nsx/services/lbaas/lb_helper.py View File

@@ -66,9 +66,21 @@ class LBaaSNSXObjectManagerWrapper(object):

return completor_func

def _certificate_handler(self, obj_dict, args):
# Extract NLBaaSv2 certificate data into a dict which is readable by
# the listener_mgr
lbv2_cert = args.get('certificate')
if lbv2_cert:
cert = {'ref': obj_dict.get('default_tls_container_id'),
'certificate': lbv2_cert.get_certificate(),
'private_key': lbv2_cert.get_private_key(),
'passphrase': lbv2_cert.get_private_key_passphrase()}
args['certificate'] = cert

@log_helpers.log_method_call
def create(self, context, obj, **args):
obj_dict = self.translator(obj)
self._certificate_handler(obj_dict, args)
completor_func = self.get_completor_func(context, obj)
return self.implementor.create(context, obj_dict, completor_func,
**args)
@@ -77,6 +89,7 @@ class LBaaSNSXObjectManagerWrapper(object):
def update(self, context, old_obj, new_obj, **args):
old_obj_dict = self.translator(old_obj)
new_obj_dict = self.translator(new_obj)
self._certificate_handler(new_obj_dict, args)
completor_func = self.get_completor_func(context, new_obj)
return self.implementor.update(context, old_obj_dict, new_obj_dict,
completor_func, **args)


+ 5
- 5
vmware_nsx/services/lbaas/nsx_p/implementation/listener_mgr.py View File

@@ -52,13 +52,13 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
nsxpolicy = self.core_plugin.nsxpolicy
cert_client = nsxpolicy.certificate
ssl_client = nsxpolicy.load_balancer.client_ssl_profile
passphrase = certificate.get_private_key_passphrase()
passphrase = certificate.get('passphrase')
if not passphrase:
passphrase = core_resources.IGNORE
cert_client.create_or_overwrite(
cert_href, certificate_id=listener_id,
pem_encoded=certificate.get_certificate(),
private_key=certificate.get_private_key(),
pem_encoded=certificate.get('certificate'),
private_key=certificate.get('private_key'),
passphrase=passphrase,
tags=tags)

@@ -103,7 +103,7 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
kwargs['lb_persistence_profile_id'] = ''
if certificate:
ssl_profile_binding = self._upload_certificate(
listener['id'], listener['default_tls_container_id'], tags,
listener['id'], certificate['ref'], tags,
certificate=certificate)
if (listener['protocol'] == lb_const.LB_PROTOCOL_TERMINATED_HTTPS
and ssl_profile_binding):
@@ -304,7 +304,7 @@ class EdgeListenerManagerFromDict(base_mgr.NsxpLoadbalancerBaseManager):
"NSX: %s", app_profile_id, e)

# 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
try:
cert_client.delete(listener['id'])


+ 12
- 11
vmware_nsx/services/lbaas/nsx_v/implementation/listener_mgr.py View File

@@ -25,8 +25,9 @@ from vmware_nsx.common import locking
from vmware_nsx.db import nsxv_db
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 lb_common
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__)

@@ -132,9 +133,9 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
return cert_binding['edge_cert_id']

request = {
'pemEncoding': certificate.get_certificate(),
'privateKey': certificate.get_private_key()}
passphrase = certificate.get_private_key_passphrase()
'pemEncoding': certificate.get('certificate'),
'privateKey': certificate.get('private_key')}
passphrase = certificate.get('passphrase')
if passphrase:
request['passphrase'] = passphrase
cert_obj = self.vcns.upload_edge_certificate(edge_id, request)[1]
@@ -166,7 +167,7 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
if certificate:
try:
edge_cert_id = self._upload_certificate(
context, edge_id, listener['default_tls_container_id'],
context, edge_id, certificate['ref'],
certificate)
except Exception:
with excutils.save_and_reraise_exception():
@@ -178,7 +179,7 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
try:
with locking.LockManager.get_lock(edge_id):
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:
with excutils.save_and_reraise_exception():
completor(success=False)
@@ -193,7 +194,7 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):
try:
with locking.LockManager.get_lock(edge_id):
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,
lb_id,
@@ -231,19 +232,19 @@ class EdgeListenerManagerFromDict(base_mgr.EdgeLoadbalancerBaseManager):

edge_cert_id = None
if certificate:
if (old_listener['default_tls_container_id'] !=
new_listener['default_tls_container_id']):
if (lb_common.get_listener_cert_ref(old_listener) !=
lb_common.get_listener_cert_ref(new_listener)):
try:
edge_cert_id = self._upload_certificate(
context, edge_id,
new_listener['default_tls_container_id'],
certificate['ref'],
certificate)
except Exception:
with excutils.save_and_reraise_exception():
completor(success=False)
else:
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
context.session, new_listener['default_tls_container_id'],
context.session, certificate['ref'],
edge_id)
edge_cert_id = cert_binding['edge_cert_id']



+ 4
- 4
vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py View File

@@ -83,14 +83,14 @@ class EdgeListenerManagerFromDict(base_mgr.Nsxv3LoadbalancerBaseManager):
# If so, use that certificate for ssl binding. Otherwise,
# create a new certificate on NSX.
cert_ids = tm_client.find_cert_with_pem(
certificate.get_certificate())
certificate.get('certificate'))
if cert_ids:
nsx_cert_id = cert_ids[0]
else:
nsx_cert_id = tm_client.create_cert(
certificate.get_certificate(),
private_key=certificate.get_private_key(),
passphrase=certificate.get_private_key_passphrase(),
certificate.get('certificate'),
private_key=certificate.get('private_key'),
passphrase=certificate.get('passphrase'),
tags=tags)
return {
'client_ssl_profile_binding': {


+ 12
- 21
vmware_nsx/services/lbaas/octavia/octavia_driver.py View File

@@ -21,8 +21,6 @@ from oslo_log import helpers as log_helpers
from oslo_log import log as logging
import oslo_messaging as messaging
from oslo_messaging.rpc import dispatcher
import pecan
from stevedore import driver as stevedore_driver

from octavia.api.drivers import exceptions
from octavia.api.drivers import utils as oct_utils
@@ -76,7 +74,6 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
super(NSXOctaviaDriver, self).__init__()
self._init_rpc_messaging()
self._init_rpc_listener()
self._init_cert_manager()
self.repositories = repositories.Repositories()

@log_helpers.log_method_call
@@ -102,13 +99,6 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
access_policy)
self.octavia_server.start()

@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):
if obj_dict.get('project_id'):
return obj_dict['project_id']
@@ -323,7 +313,6 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
# Generate the default pool object
obj_dict['default_pool'] = self._get_pool_dict(
obj_dict['default_pool_id'], is_update, project_id)
# TODO(asarfaty): add default_tls_container_id

elif obj_type == 'Pool':
if 'listener' not in obj_dict:
@@ -409,15 +398,21 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
'new_loadbalancer': new_dict}
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
@log_helpers.log_method_call
def listener_create(self, listener):
cert = None
dict_list = self.obj_to_dict(listener)
if dict_list.get('tls_certificate_id'):
context = pecan.request.context.get('octavia_context')
cert = self.cert_manager.get_cert(context,
dict_list['tls_certificate_id'])
cert = self._create_lb_certificate(dict_list)
kw = {'listener': dict_list, 'cert': cert}
self.client.cast({}, 'listener_create', **kw)

@@ -433,11 +428,7 @@ class NSXOctaviaDriver(driver_base.ProviderDriver):
new_dict.update(self.obj_to_dict(
new_listener, is_update=True,
project_id=old_dict.get('project_id')))
cert = None
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'])
cert = self._create_lb_certificate(new_dict)
kw = {'old_listener': old_dict,
'new_listener': new_dict,
'cert': cert}


+ 15
- 8
vmware_nsx/tests/unit/services/lbaas/test_octavia_driver.py View File

@@ -48,8 +48,7 @@ class TestNsxProviderDriver(testtools.TestCase):
return
# init the NSX driver without the RPC & certificate
with mock.patch(DRIVER + '._init_rpc_messaging'), \
mock.patch(DRIVER + '._init_rpc_listener'), \
mock.patch(DRIVER + '._init_cert_manager'):
mock.patch(DRIVER + '._init_rpc_listener'):
self.driver = driver.NSXOctaviaDriver()
self.driver.client = mock.Mock()

@@ -67,6 +66,11 @@ class TestNsxProviderDriver(testtools.TestCase):
self.l7rule_id = uuidutils.generate_uuid()
self.project_id = 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_2 = uuidutils.generate_uuid()

@@ -135,7 +139,7 @@ class TestNsxProviderDriver(testtools.TestCase):
connection_limit=5,
default_pool=self.ref_pool,
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,
description='The listener',
insert_headers={'X-Forwarded-For': 'true'},
@@ -223,8 +227,9 @@ class TestNsxProviderDriver(testtools.TestCase):
def test_listener_create(self):
with mock.patch.object(self.driver.client, 'cast') as cast_method:
self.driver.listener_create(self.ref_listener)
cast_method.assert_called_with({}, 'listener_create', cert=None,
listener=mock.ANY)
cast_method.assert_called_with(
{}, 'listener_create', cert=self.default_tls_container_data,
listener=mock.ANY)
driver_obj = cast_method.call_args[1]['listener']
self.assertIn('id', driver_obj)
self.assertIn('project_id', driver_obj)
@@ -256,9 +261,11 @@ class TestNsxProviderDriver(testtools.TestCase):
def test_listener_update(self):
with mock.patch.object(self.driver.client, 'cast') as cast_method:
self.driver.listener_update(self.ref_listener, self.ref_listener)
cast_method.assert_called_with({}, 'listener_update', cert=None,
old_listener=mock.ANY,
new_listener=mock.ANY)
cast_method.assert_called_with(
{}, 'listener_update',
cert=self.default_tls_container_data,
old_listener=mock.ANY,
new_listener=mock.ANY)
driver_obj = cast_method.call_args[1]['new_listener']
self.assertIn('id', driver_obj)
self.assertIn('project_id', driver_obj)


Loading…
Cancel
Save