vmware-nsx/vmware_nsx/plugins/nsx_v/vshield/nsxv_loadbalancer.py
Abhishek Raut ea77b5f857 [NSXv] Add SSL support for metadata service in NSX-V plugin
Metadata service in the NSX-V plugin is handled by a Edge DHCP or
router VM. Currently the traffic between nova and the metadata service
is insecure. This patch adds the SSL support for metadata service
which will make the connection secure.

The certificate used for secure communication will be created on the
VC under the edge scope. If user does not supply the certificate and
private key for secure communication, a self signed certificate will be
generated in the backend. This self signed certificate will last for a
period of 10yrs.
A certifcate with the given details will be created in the backend if
such a configuration exists in nsx.ini
Appropriate config is pushed for the loadbalancer with the protocol set
to HTTPS if SSL is enabled for metadata service.

DocImpact

Change-Id: I5582cc1186ef4b8451f999b46e55bc2c684b1be3
2015-11-30 05:55:24 -08:00

400 lines
13 KiB
Python

# Copyright 2014 VMware, Inc.
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from oslo_log import log as logging
from vmware_nsx.plugins.nsx_v.vshield import nsxv_edge_cfg_obj
LOG = logging.getLogger(__name__)
class NsxvLoadbalancer(nsxv_edge_cfg_obj.NsxvEdgeCfgObj):
SERVICE_NAME = 'loadbalancer'
def __init__(
self,
enabled=True,
enable_service_insertion=False,
acceleration_enabled=False):
super(NsxvLoadbalancer, self).__init__()
self.payload = {
'enabled': enabled,
'enableServiceInsertion': enable_service_insertion,
'accelerationEnabled': acceleration_enabled}
self.virtual_servers = {}
def get_service_name(self):
return self.SERVICE_NAME
def add_virtual_server(self, virtual_server):
self.virtual_servers[virtual_server.payload['name']] = virtual_server
def del_virtual_server(self, name):
self.virtual_servers.pop(name, None)
def serializable_payload(self):
virt_servers = []
app_profiles = []
app_rules = []
pools = []
monitors = []
virt_id = 1
app_prof_id = 1
app_rule_id = 1
pool_id = 1
monitor_id = 1
member_id = 1
for virtual_server in self.virtual_servers.values():
s_virt = virtual_server.payload.copy()
s_virt['virtualServerId'] = 'virtualServer-%d' % virt_id
virt_id += 1
# Setup app profile
s_app_prof = virtual_server.app_profile.payload.copy()
s_app_prof['applicationProfileId'] = ('applicationProfile-%d' %
app_prof_id)
app_profiles.append(s_app_prof)
app_prof_id += 1
# Bind virtual server to app profile
s_virt['applicationProfileId'] = s_app_prof['applicationProfileId']
# Setup app rules
if virtual_server.app_rules.values():
s_virt['applicationRuleId'] = []
for app_rule in virtual_server.app_rules.values():
s_app_rule = app_rule.payload.copy()
s_app_rule['applicationRuleId'] = ('applicationRule-%d' %
app_rule_id)
app_rule_id += 1
# Add to LB object, bind to virtual server
app_rules.append(s_app_rule)
s_virt['applicationRuleId'].append(
s_app_rule['applicationRuleId'])
# Setup pools
s_pool = virtual_server.default_pool.payload.copy()
s_pool['poolId'] = 'pool-%d' % pool_id
pool_id += 1
pools.append(s_pool)
# Add pool members
s_pool['member'] = []
for member in virtual_server.default_pool.members.values():
s_m = member.payload.copy()
s_m['memberId'] = 'member-%d' % member_id
member_id += 1
s_pool['member'].append(s_m)
# Bind pool to virtual server
s_virt['defaultPoolId'] = s_pool['poolId']
s_pool['monitorId'] = []
# Add monitors
for monitor in virtual_server.default_pool.monitors.values():
s_mon = monitor.payload.copy()
s_mon['monitorId'] = 'monitor-%d' % monitor_id
monitor_id += 1
s_pool['monitorId'].append(s_mon['monitorId'])
monitors.append(s_mon)
virt_servers.append(s_virt)
payload = self.payload.copy()
payload['applicationProfile'] = app_profiles
if app_rules:
payload['applicationRule'] = app_rules
payload['monitor'] = monitors
payload['pool'] = pools
payload['virtualServer'] = virt_servers
payload['featureType'] = 'loadbalancer_4.0'
return payload
@staticmethod
def get_loadbalancer(vcns_obj, edge_id):
edge_lb = nsxv_edge_cfg_obj.NsxvEdgeCfgObj.get_object(
vcns_obj,
edge_id,
'%s/config' % NsxvLoadbalancer.SERVICE_NAME)
lb_obj = NsxvLoadbalancer(
edge_lb['enabled'],
edge_lb['enableServiceInsertion'],
edge_lb['accelerationEnabled'])
# Construct loadbalancer objects
for virt_srvr in edge_lb['virtualServer']:
v_s = NsxvLBVirtualServer(
virt_srvr['name'],
virt_srvr['ipAddress'],
virt_srvr['port'],
virt_srvr['protocol'],
virt_srvr['enabled'],
virt_srvr['accelerationEnabled'],
virt_srvr['connectionLimit'])
# Find application profile objects, attach to virtual server
for app_prof in edge_lb['applicationProfile']:
if (virt_srvr['applicationProfileId']
== app_prof['applicationProfileId']):
a_p = NsxvLBAppProfile(
app_prof['name'],
app_prof['serverSslEnabled'],
app_prof['sslPassthrough'],
app_prof['template'],
app_prof['insertXForwardedFor'])
if app_prof.get('persistence'):
a_p.set_persistence(
True,
app_prof['persistence']['method'],
app_prof['persistence'].get('cookieName'),
app_prof['persistence'].get('cookieMode'),
app_prof['persistence'].get('expire'))
v_s.set_app_profile(a_p)
# Find default pool, attach to virtual server
for pool in edge_lb['pool']:
if virt_srvr['defaultPoolId'] == pool['poolId']:
p = NsxvLBPool(
pool['name'],
pool['algorithm'],
pool['transparent'])
# Add pool members to pool
for member in pool['member']:
m = NsxvLBPoolMember(
member['name'],
member['ipAddress'],
member['port'],
member['monitorPort'],
member['condition'],
member['weight'],
member['minConn'],
member['maxConn'])
p.add_member(m)
# Add monitors to pool
for mon in edge_lb['monitor']:
if mon['monitorId'] in pool['monitorId']:
m = NsxvLBMonitor(
mon['name'],
mon['interval'],
mon['maxRetries'],
mon['method'],
mon['timeout'],
mon['type'],
mon['url'])
p.add_monitor(m)
v_s.set_default_pool(p)
# Add application rules to virtual server
for rule in edge_lb['applicationRule']:
if rule['applicationRuleId'] in virt_srvr['applicationRuleId']:
r = NsxvLBAppRule(
rule['name'],
rule['script'])
v_s.add_app_rule(r)
lb_obj.add_virtual_server(v_s)
return lb_obj
class NsxvLBAppProfile(object):
def __init__(
self,
name,
server_ssl_enabled=False,
ssl_pass_through=False,
template='TCP',
insert_xff=False,
client_ssl_cert=None,
persist=False,
persist_method='cookie',
persist_cookie_name='JSESSIONID',
persist_cookie_mode='insert',
persist_expire=30):
self.payload = {
'name': name,
'serverSslEnabled': server_ssl_enabled,
'sslPassthrough': ssl_pass_through,
'template': template,
'insertXForwardedFor': insert_xff}
if persist:
self.payload['persistence'] = {
'method': persist_method,
'expire': persist_expire
}
if persist_cookie_mode == 'cookie':
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,
persist_method='cookie',
persist_cookie_name='JSESSIONID',
persist_cookie_mode='insert',
persist_expire=30):
if persist:
self.payload['persistence'] = {
'method': persist_method,
'expire': persist_expire
}
if persist_cookie_mode == 'cookie':
self.payload['persistence']['cookieMode'] = persist_cookie_mode
self.payload['persistence']['cookieName'] = persist_cookie_name
else:
self.payload.pop('persistence', None)
class NsxvLBAppRule(object):
def __init__(self, name, script):
self.payload = {
'name': name,
'script': script}
class NsxvLBVirtualServer(object):
def __init__(
self,
name,
ip_address,
port=80,
protocol='HTTP',
enabled=True,
acceleration_enabled=False,
connection_limit=0,
enable_service_insertion=False):
self.payload = {
'name': name,
'ipAddress': ip_address,
'port': port,
'protocol': protocol,
'enabled': enabled,
'accelerationEnabled': acceleration_enabled,
'connectionLimit': connection_limit,
'enableServiceInsertion': enable_service_insertion}
self.app_rules = {}
self.app_profile = None
self.default_pool = None
def add_app_rule(self, app_rule):
self.app_rules[app_rule.payload['name']] = app_rule
def del_app_rule(self, name):
self.app_rules.pop(name, None)
def set_default_pool(self, pool):
self.default_pool = pool
def set_app_profile(self, app_profile):
self.app_profile = app_profile
class NsxvLBMonitor(object):
def __init__(
self,
name,
interval=10,
max_retries=3,
method='GET',
timeout=15,
mon_type='http',
url='/'):
self.payload = {
'name': name,
'interval': interval,
'maxRetries': max_retries,
'method': method,
'timeout': timeout,
'type': mon_type,
'url': url}
class NsxvLBPoolMember(object):
def __init__(
self,
name,
ip_address,
port,
monitor_port=None,
condition='enabled',
weight=1,
min_conn=0,
max_conn=0):
self.payload = {
'name': name,
'ipAddress': ip_address,
'port': port,
'monitorPort': monitor_port,
'condition': condition,
'weight': weight,
'minConn': min_conn,
'maxConn': max_conn}
class NsxvLBPool(object):
def __init__(
self,
name,
algorithm='round-robin',
transparent=False):
self.payload = {
'name': name,
'algorithm': algorithm,
'transparent': transparent}
self.members = {}
self.monitors = {}
def add_member(self, member):
self.members[member.payload['name']] = member
def del_member(self, name):
self.members.pop(name, None)
def add_monitor(self, monitor):
self.monitors[monitor.payload['name']] = monitor
def del_monitor(self, name):
self.monitors.pop(name, None)