From 16b564346e2d77bd0e097183ebb0e4c74a1c02c6 Mon Sep 17 00:00:00 2001 From: Eric Brown Date: Mon, 24 Aug 2015 15:10:29 -0700 Subject: [PATCH] Ensure NSXv driver can verify certificates The NSXv driver was missing code to do certificate verification. In fact, it was intentional turned off. This patch adds the capability to turn it on. DocImpact: Two new options for the NSXv driver: ca_file and insecure. Change-Id: I12ffa2f5e80d4dd357e907631d2bcc76c13a0797 Closes-Bug: #1488265 --- devstack/lib/vmware_nsx_v | 2 ++ vmware_nsx/etc/nsx.ini | 8 ++++++++ vmware_nsx/neutron/plugins/vmware/common/config.py | 9 +++++++++ .../plugins/vmware/vshield/common/VcnsApiClient.py | 11 +++++++++-- vmware_nsx/neutron/plugins/vmware/vshield/vcns.py | 14 +++++++++++--- .../neutron/plugins/vmware/vshield/vcns_driver.py | 5 ++++- .../unit/vmware/nsx_v/test_nsxv_loadbalancer.py | 2 +- 7 files changed, 44 insertions(+), 7 deletions(-) diff --git a/devstack/lib/vmware_nsx_v b/devstack/lib/vmware_nsx_v index ef3b9ebedb..0b0074d26f 100644 --- a/devstack/lib/vmware_nsx_v +++ b/devstack/lib/vmware_nsx_v @@ -84,6 +84,8 @@ function neutron_plugin_configure_service { _nsxv_ini_set vdn_scope_id "$NSXV_VDN_SCOPE_ID" _nsxv_ini_set dvs_id "$NSXV_DVS_ID" _nsxv_ini_set manager_uri "$NSXV_MANAGER_URI" + _nsxv_ini_set ca_file "$NSXV_CA_FILE" + _nsxv_ini_set insecure "$NSXV_INSECURE" _nsxv_ini_set datacenter_moid "$NSXV_DATACENTER_MOID" _nsxv_ini_set datastore_id "$NSXV_DATASTORE_ID" _nsxv_ini_set resource_pool_id "$NSXV_RESOURCE_POOL_ID" diff --git a/vmware_nsx/etc/nsx.ini b/vmware_nsx/etc/nsx.ini index 560cebccfb..24ce95f71d 100644 --- a/vmware_nsx/etc/nsx.ini +++ b/vmware_nsx/etc/nsx.ini @@ -58,6 +58,14 @@ # Password for NSXv manager # password = default +# Specify a CA bundle file to use in verifying the NSXv server certificate. +# ca_file = + +# If true, the NSXv server certificate is not verified. If false, +# then the default CA truststore is used for verification. This option +# is ignored if "ca_file" is set. +# insecure = true + # (Required) Datacenter ID for Edge deployment # datacenter_moid = diff --git a/vmware_nsx/neutron/plugins/vmware/common/config.py b/vmware_nsx/neutron/plugins/vmware/common/config.py index bea9e24108..1de0160ce0 100644 --- a/vmware_nsx/neutron/plugins/vmware/common/config.py +++ b/vmware_nsx/neutron/plugins/vmware/common/config.py @@ -206,6 +206,15 @@ nsxv_opts = [ cfg.StrOpt('manager_uri', deprecated_group="vcns", help=_('uri for vsm')), + cfg.StrOpt('ca_file', + help='Specify a CA bundle file to use in verifying the NSXv ' + 'server certificate.'), + cfg.BoolOpt('insecure', + default=True, + help='If true, the NSXv server certificate is not verified. ' + 'If false, then the default CA truststore is used for ' + 'verification. This option is ignored if "ca_file" is ' + 'set.'), cfg.ListOpt('cluster_moid', default=[], help=_('Parameter listing the IDs of the clusters ' diff --git a/vmware_nsx/neutron/plugins/vmware/vshield/common/VcnsApiClient.py b/vmware_nsx/neutron/plugins/vmware/vshield/common/VcnsApiClient.py index 2f26b455b8..b67603428e 100644 --- a/vmware_nsx/neutron/plugins/vmware/vshield/common/VcnsApiClient.py +++ b/vmware_nsx/neutron/plugins/vmware/vshield/common/VcnsApiClient.py @@ -73,7 +73,8 @@ class VcnsApiHelper(object): 503: exceptions.ServiceUnavailable } - def __init__(self, address, user, password, format='json'): + def __init__(self, address, user, password, format='json', ca_file=None, + insecure=True): self.authToken = base64.encodestring(six.b("%s:%s" % (user, password))) self.user = user self.passwd = password @@ -83,12 +84,18 @@ class VcnsApiHelper(object): self.encode = jsonutils.dumps else: self.encode = xmldumps + self.ca_file = ca_file + self.insecure = insecure def request(self, method, uri, params=None, headers=None, encodeparams=True): uri = self.address + uri http = httplib2.Http() - http.disable_ssl_certificate_validation = True + if self.ca_file is not None: + http.ca_certs = self.ca_file + http.disable_ssl_certificate_validation = False + else: + http.disable_ssl_certificate_validation = self.insecure if headers is None: headers = {} diff --git a/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py b/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py index 1ea73a3b36..c37a077e1f 100644 --- a/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py +++ b/vmware_nsx/neutron/plugins/vmware/vshield/vcns.py @@ -72,14 +72,22 @@ def retry_upon_exception(exc, delay=500, max_delay=2000, class Vcns(object): - def __init__(self, address, user, password): + def __init__(self, address, user, password, ca_file, insecure): self.address = address self.user = user self.password = password + self.ca_file = ca_file + self.insecure = insecure self.jsonapi_client = VcnsApiClient.VcnsApiHelper(address, user, - password, 'json') + password, + format='json', + ca_file=ca_file, + insecure=insecure) self.xmlapi_client = VcnsApiClient.VcnsApiHelper(address, user, - password, 'xml') + password, + format='xml', + ca_file=ca_file, + insecure=insecure) @retry_upon_exception(exceptions.ServiceConflict) def _client_request(self, client, method, uri, diff --git a/vmware_nsx/neutron/plugins/vmware/vshield/vcns_driver.py b/vmware_nsx/neutron/plugins/vmware/vshield/vcns_driver.py index dfc5a23399..46c5e57a44 100644 --- a/vmware_nsx/neutron/plugins/vmware/vshield/vcns_driver.py +++ b/vmware_nsx/neutron/plugins/vmware/vshield/vcns_driver.py @@ -38,13 +38,16 @@ class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver, self.vcns_uri = cfg.CONF.nsxv.manager_uri self.vcns_user = cfg.CONF.nsxv.user self.vcns_passwd = cfg.CONF.nsxv.password + self.ca_file = cfg.CONF.nsxv.ca_file + self.insecure = cfg.CONF.nsxv.insecure self.datacenter_moid = cfg.CONF.nsxv.datacenter_moid self.deployment_container_id = cfg.CONF.nsxv.deployment_container_id self.resource_pool_id = cfg.CONF.nsxv.resource_pool_id self.datastore_id = cfg.CONF.nsxv.datastore_id self.external_network = cfg.CONF.nsxv.external_network self._task_manager = None - self.vcns = vcns.Vcns(self.vcns_uri, self.vcns_user, self.vcns_passwd) + self.vcns = vcns.Vcns(self.vcns_uri, self.vcns_user, self.vcns_passwd, + self.ca_file, self.insecure) @property def task_manager(self): diff --git a/vmware_nsx/neutron/tests/unit/vmware/nsx_v/test_nsxv_loadbalancer.py b/vmware_nsx/neutron/tests/unit/vmware/nsx_v/test_nsxv_loadbalancer.py index f61cbe33cf..a09602f17e 100644 --- a/vmware_nsx/neutron/tests/unit/vmware/nsx_v/test_nsxv_loadbalancer.py +++ b/vmware_nsx/neutron/tests/unit/vmware/nsx_v/test_nsxv_loadbalancer.py @@ -74,7 +74,7 @@ class NsxvLoadbalancerTestCase(base.BaseTestCase): def setUp(self): super(NsxvLoadbalancerTestCase, self).setUp() self._lb = nsxv_loadbalancer.NsxvLoadbalancer() - self._vcns = vcns.Vcns(None, None, None) + self._vcns = vcns.Vcns(None, None, None, None, True) def test_get_edge_loadbalancer(self): h = None