Merge "[NSXv] Add SSL support for metadata service in NSX-V plugin"
This commit is contained in:
commit
8177d68dfd
@ -104,6 +104,9 @@ function neutron_plugin_configure_service {
|
||||
_nsxv_ini_set nova_metadata_port "$NSXV_NOVA_METADATA_PORT"
|
||||
_nsxv_ini_set nova_metadata_ips "$NSXV_NOVA_METADATA_IPS"
|
||||
_nsxv_ini_set metadata_shared_secret "$NSXV_METADATA_SHARED_SECRET"
|
||||
_nsxv_ini_set metadata_insecure "$NSXV_METADATA_INSECURE"
|
||||
_nsxv_ini_set metadata_nova_client_cert "$NSXV_METADATA_NOVA_CERT"
|
||||
_nsxv_ini_set metadata_nova_client_priv_key "$NSXV_METADATA_NOVA_PRIV_KEY"
|
||||
_nsxv_ini_set edge_ha "$NSXV_EDGE_HA"
|
||||
_nsxv_ini_set exclusive_router_appliance_size "$NSXV_EXCLUSIVE_ROUTER_APPLIANCE_SIZE"
|
||||
}
|
||||
|
15
etc/nsx.ini
15
etc/nsx.ini
@ -71,10 +71,10 @@
|
||||
# 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,
|
||||
# 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
|
||||
# insecure = True
|
||||
|
||||
# (Required) Datacenter MoRef ID for Edge deployment
|
||||
# datacenter_moid =
|
||||
@ -143,6 +143,17 @@
|
||||
# (Optional) Shared secret to sign metadata requests
|
||||
# metadata_shared_secret =
|
||||
|
||||
# (Optional) If True, the end to end connection for metadata service is
|
||||
# not verified. If False, the default CA truststore is used for verification.
|
||||
# metadata_insecure =
|
||||
|
||||
# (Optional) Client certificate to use when metadata connection is to be
|
||||
# verified. If not provided, a self signed certificate will be used.
|
||||
# metadata_nova_client_cert =
|
||||
|
||||
# (Optional) Private key to use for client certificate
|
||||
# metadata_nova_client_priv_key =
|
||||
|
||||
# (Optional) Indicates if Nsxv spoofguard component is used to implement
|
||||
# port-security feature.
|
||||
# spoofguard_enabled = True
|
||||
|
@ -303,6 +303,15 @@ nsxv_opts = [
|
||||
cfg.StrOpt('metadata_shared_secret',
|
||||
secret=True,
|
||||
help=_('Shared secret to sign metadata requests')),
|
||||
cfg.BoolOpt('metadata_insecure',
|
||||
default=True,
|
||||
help=_('If True, the end to end connection for metadata '
|
||||
'service is not verified. If False, the default CA '
|
||||
'truststore is used for verification')),
|
||||
cfg.StrOpt('metadata_nova_client_cert',
|
||||
help=_('Client certificate for nova metadata api server')),
|
||||
cfg.StrOpt('metadata_nova_client_priv_key',
|
||||
help=_('Private key of client certificate')),
|
||||
cfg.BoolOpt('spoofguard_enabled',
|
||||
default=True,
|
||||
help=_("If True then plugin will use NSXV spoofguard "
|
||||
|
@ -35,3 +35,20 @@ INTERNAL_TENANT_ID = 'a1b2c3d4-e5f6-eeff-ffee-6f5e4d3c2b1a'
|
||||
|
||||
# L2 gateway edge name prefix
|
||||
L2_GATEWAY_EDGE = 'L2 bridging'
|
||||
|
||||
# LoadBalancer Certificate constants
|
||||
#NOTE(abhiraut): Number of days specify the total number of days for which the
|
||||
# the certificate will be active. This certificate will expire
|
||||
# in 10 years. Once the backend API allows creation of certs
|
||||
# which do not expire, the following constant should be removed.
|
||||
CERT_NUMBER_OF_DAYS = 3650
|
||||
CSR_REQUEST = ("<csr><subject>"
|
||||
"<attribute><key>CN</key><value>metadata.nsx.local</value>"
|
||||
"</attribute>"
|
||||
"<attribute><key>O</key><value>Organization</value></attribute>"
|
||||
"<attribute><key>OU</key><value>Unit</value></attribute>"
|
||||
"<attribute><key>L</key><value>Locality</value></attribute>"
|
||||
"<attribute><key>ST</key><value>State</value></attribute>"
|
||||
"<attribute><key>C</key><value>US</value></attribute>"
|
||||
"</subject><algorithm>RSA</algorithm><keySize>2048</keySize>"
|
||||
"</csr>")
|
||||
|
@ -16,6 +16,7 @@
|
||||
import hashlib
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.i18n import _LE
|
||||
from neutron import version
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
@ -147,3 +148,12 @@ def dict_match(dict1, dict2):
|
||||
elif v1 != v2:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def read_file(path):
|
||||
try:
|
||||
with open(path) as file:
|
||||
return file.read().strip()
|
||||
except IOError as e:
|
||||
LOG.error(_LE("Error while opening file "
|
||||
"%(path)s: %(err)s"), {'path': path, 'err': str(e)})
|
||||
|
@ -28,16 +28,20 @@ from neutron.i18n import _LE
|
||||
from vmware_nsx.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.common import nsxv_constants
|
||||
from vmware_nsx.common import utils
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield import (
|
||||
nsxv_loadbalancer as nsxv_lb)
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import (
|
||||
constants as vcns_const)
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common
|
||||
|
||||
METADATA_VSE_NAME = 'MdSrv'
|
||||
METADATA_IP_ADDR = '169.254.169.254'
|
||||
METADATA_TCP_PORT = 80
|
||||
METADATA_HTTPS_PORT = 443
|
||||
METADATA_HTTPS_VIP_PORT = 8775
|
||||
INTERNAL_SUBNET = '169.254.128.0/17'
|
||||
MAX_INIT_THREADS = 3
|
||||
|
||||
@ -486,6 +490,39 @@ class NsxVMetadataProxyHandler:
|
||||
address_groups.append(address_group)
|
||||
return address_groups
|
||||
|
||||
def _create_ssl_cert(self, edge_id=None):
|
||||
# Create a self signed certificate in the backend if both Cert details
|
||||
# and private key are not supplied in nsx.ini
|
||||
if (not cfg.CONF.nsxv.metadata_nova_client_cert and
|
||||
not cfg.CONF.nsxv.metadata_nova_client_priv_key):
|
||||
h = self.nsxv_plugin.nsx_v.vcns.create_csr(edge_id)[0]
|
||||
# Extract the CSR ID from header
|
||||
csr_id = lbaas_common.extract_resource_id(h['location'])
|
||||
# Create a self signed certificate
|
||||
cert = self.nsxv_plugin.nsx_v.vcns.create_csr_cert(csr_id)[1]
|
||||
cert_id = cert['objectId']
|
||||
else:
|
||||
# Raise an error if either the Cert path or the private key is not
|
||||
# configured
|
||||
error = None
|
||||
if not cfg.CONF.nsxv.metadata_nova_client_cert:
|
||||
error = _('Metadata certificate path not configured')
|
||||
elif not cfg.CONF.nsxv.metadata_nova_client_priv_key:
|
||||
error = _('Metadata client private key not configured')
|
||||
if error:
|
||||
raise nsxv_exc.NsxPluginException(err_msg=error)
|
||||
pem_encoding = utils.read_file(
|
||||
cfg.CONF.nsxv.metadata_nova_client_cert)
|
||||
priv_key = utils.read_file(
|
||||
cfg.CONF.nsxv.metadata_nova_client_priv_key)
|
||||
request = {
|
||||
'pemEncoding': pem_encoding,
|
||||
'privateKey': priv_key}
|
||||
cert = self.nsxv_plugin.nsx_v.vcns.upload_edge_certificate(
|
||||
edge_id, request)[1]
|
||||
cert_id = cert.get('certificates')[0]['objectId']
|
||||
return cert_id
|
||||
|
||||
def _setup_metadata_lb(self, rtr_id, vip, v_port, s_port, member_ips,
|
||||
proxy_lb=False, context=None):
|
||||
|
||||
@ -497,10 +534,26 @@ class NsxVMetadataProxyHandler:
|
||||
|
||||
lb_obj = nsxv_lb.NsxvLoadbalancer()
|
||||
|
||||
protocol = 'HTTP'
|
||||
ssl_pass_through = False
|
||||
cert_id = None
|
||||
# Set protocol to HTTPS with default port of 443 if metadata_insecure
|
||||
# is set to False.
|
||||
if not cfg.CONF.nsxv.metadata_insecure:
|
||||
protocol = 'HTTPS'
|
||||
if proxy_lb:
|
||||
v_port = METADATA_HTTPS_VIP_PORT
|
||||
else:
|
||||
v_port = METADATA_HTTPS_PORT
|
||||
# Create the certificate on the backend
|
||||
cert_id = self._create_ssl_cert(edge_id)
|
||||
ssl_pass_through = proxy_lb
|
||||
mon_type = protocol if proxy_lb else 'tcp'
|
||||
# Create virtual server
|
||||
virt_srvr = nsxv_lb.NsxvLBVirtualServer(
|
||||
name=METADATA_VSE_NAME,
|
||||
ip_address=vip,
|
||||
protocol=protocol,
|
||||
port=v_port)
|
||||
|
||||
# For router Edge, we add X-LB-Proxy-ID header
|
||||
@ -525,8 +578,11 @@ class NsxVMetadataProxyHandler:
|
||||
# XFF is inserted in router LBs
|
||||
app_profile = nsxv_lb.NsxvLBAppProfile(
|
||||
name='MDSrvProxy',
|
||||
template='HTTP',
|
||||
insert_xff=not proxy_lb)
|
||||
template=protocol,
|
||||
server_ssl_enabled=not cfg.CONF.nsxv.metadata_insecure,
|
||||
ssl_pass_through=ssl_pass_through,
|
||||
insert_xff=not proxy_lb,
|
||||
client_ssl_cert=cert_id)
|
||||
|
||||
virt_srvr.set_app_profile(app_profile)
|
||||
|
||||
@ -534,8 +590,8 @@ class NsxVMetadataProxyHandler:
|
||||
pool = nsxv_lb.NsxvLBPool(
|
||||
name='MDSrvPool')
|
||||
|
||||
monitor = nsxv_lb.NsxvLBMonitor(
|
||||
name='MDSrvMon', mon_type='http' if proxy_lb else 'icmp')
|
||||
monitor = nsxv_lb.NsxvLBMonitor(name='MDSrvMon',
|
||||
mon_type=mon_type.lower())
|
||||
pool.add_monitor(monitor)
|
||||
|
||||
i = 0
|
||||
|
@ -235,6 +235,7 @@ class NsxvLBAppProfile(object):
|
||||
ssl_pass_through=False,
|
||||
template='TCP',
|
||||
insert_xff=False,
|
||||
client_ssl_cert=None,
|
||||
persist=False,
|
||||
persist_method='cookie',
|
||||
persist_cookie_name='JSESSIONID',
|
||||
@ -256,6 +257,12 @@ class NsxvLBAppProfile(object):
|
||||
self.payload['persistence']['cookieMode'] = persist_cookie_mode
|
||||
self.payload['persistence']['cookieName'] = persist_cookie_name
|
||||
|
||||
if client_ssl_cert:
|
||||
self.payload['clientSsl'] = {
|
||||
'clientAuth': 'ignore',
|
||||
'serviceCertificate': [client_ssl_cert]
|
||||
}
|
||||
|
||||
def set_persistence(
|
||||
self,
|
||||
persist=False,
|
||||
|
@ -23,6 +23,7 @@ import retrying
|
||||
import six
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
from vmware_nsx.common import nsxv_constants
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import VcnsApiClient
|
||||
|
||||
@ -44,6 +45,7 @@ SECURITYGROUP_PREFIX = '/api/2.0/services/securitygroup'
|
||||
VDN_PREFIX = '/api/2.0/vdn'
|
||||
SERVICES_PREFIX = '/api/2.0/services'
|
||||
SPOOFGUARD_PREFIX = '/api/4.0/services/spoofguard'
|
||||
TRUSTSTORE_PREFIX = '%s/%s' % (SERVICES_PREFIX, 'truststore')
|
||||
|
||||
#LbaaS Constants
|
||||
LOADBALANCER_SERVICE = "loadbalancer/config"
|
||||
@ -67,6 +69,10 @@ SYSCTL_SERVICE = 'systemcontrol/config'
|
||||
# L2 gateway constants
|
||||
BRIDGE = "bridging/config"
|
||||
|
||||
# Self Signed Certificate constants
|
||||
CSR = "csr"
|
||||
CERTIFICATE = "certificate"
|
||||
|
||||
|
||||
def retry_upon_exception(exc, delay=500, max_delay=2000,
|
||||
max_attempts=cfg.CONF.nsxv.retries):
|
||||
@ -816,5 +822,17 @@ class Vcns(object):
|
||||
|
||||
def upload_edge_certificate(self, edge_id, request):
|
||||
"""Creates a certificate on the specified Edge appliance."""
|
||||
uri = '/api/2.0/services/truststore/certificate/%s' % edge_id
|
||||
uri = '%s/%s/%s' % (TRUSTSTORE_PREFIX, CERTIFICATE, edge_id)
|
||||
return self.do_request(HTTP_POST, uri, request, decode=True)
|
||||
|
||||
def create_csr(self, edge_id, request=nsxv_constants.CSR_REQUEST):
|
||||
"""Create a CSR on the specified Edge appliance."""
|
||||
uri = '%s/%s/%s' % (TRUSTSTORE_PREFIX, CSR, edge_id)
|
||||
return self.do_request(HTTP_POST, uri, request, format='xml',
|
||||
decode=False)
|
||||
|
||||
def create_csr_cert(self, csr_id):
|
||||
"""Create a CSR self signed cert on the specified Edge appliance."""
|
||||
uri = '%s/%s/%s?noOfDays=%s' % (TRUSTSTORE_PREFIX, CSR, csr_id,
|
||||
nsxv_constants.CERT_NUMBER_OF_DAYS)
|
||||
return self.do_request(HTTP_PUT, uri)
|
||||
|
Loading…
Reference in New Issue
Block a user