9e4dd8ac59
Change-Id: Ic82dbcd18d1dbe0a444bb7bfb646931fe25f4d0a
470 lines
15 KiB
Python
470 lines
15 KiB
Python
# Copyright 2017 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_nsxlib.v3 import utils
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
VPN_IPSEC_PATH = 'vpn/ipsec/'
|
|
|
|
|
|
# The following classes define IPSEC NSX constants that are alo relevant to the
|
|
# policy implementation:
|
|
|
|
class IkeVersionTypes(object):
|
|
"""Supported IKE versions (NSX default is V2)"""
|
|
IKE_VERSION_V1 = 'IKE_V1'
|
|
IKE_VERSION_V2 = 'IKE_V2'
|
|
IKE_VERSION_Flex = 'IKE_FLEX'
|
|
|
|
|
|
class EncryptionAlgorithmTypes(object):
|
|
"""Supported encryption algorithms (NSX default is AES_128)"""
|
|
ENCRYPTION_ALGORITHM_128 = 'AES_128'
|
|
ENCRYPTION_ALGORITHM_256 = 'AES_256'
|
|
ENCRYPTION_ALGORITHM_GCM_128 = 'AES_GCM_128' # only with IKE_V2
|
|
ENCRYPTION_ALGORITHM_GCM_192 = 'AES_GCM_192' # only with IKE_V2
|
|
ENCRYPTION_ALGORITHM_GCM_256 = 'AES_GCM_256' # only with IKE_V2
|
|
|
|
|
|
class DigestAlgorithmTypes(object):
|
|
"""Supported digest (auth) algorithms (NSX default is SHA2_256)"""
|
|
DIGEST_ALGORITHM_SHA1 = 'SHA1'
|
|
DIGEST_ALGORITHM_SHA256 = 'SHA2_256'
|
|
DIGEST_ALGORITHM_SHA2_384 = 'SHA2_384'
|
|
DIGEST_ALGORITHM_SHA2_512 = 'SHA2_512'
|
|
DIGEST_ALGORITHM_GMAC_128 = 'GMAC_128' # only for tunnel profile
|
|
DIGEST_ALGORITHM_GMAC_192 = 'GMAC_192' # only for tunnel profile
|
|
DIGEST_ALGORITHM_GMAC_256 = 'GMAC_256' # only for tunnel profile
|
|
|
|
|
|
class DHGroupTypes(object):
|
|
"""Supported DH groups for Perfect Forward Secrecy"""
|
|
DH_GROUP_2 = 'GROUP2'
|
|
DH_GROUP_5 = 'GROUP5'
|
|
DH_GROUP_14 = 'GROUP14'
|
|
DH_GROUP_15 = 'GROUP15'
|
|
DH_GROUP_16 = 'GROUP16'
|
|
DH_GROUP_19 = 'GROUP19'
|
|
DH_GROUP_20 = 'GROUP20'
|
|
DH_GROUP_21 = 'GROUP21'
|
|
|
|
|
|
class EncapsulationModeTypes(object):
|
|
"""Supported encapsulation modes for ipsec tunnel profile"""
|
|
ENCAPSULATION_MODE_TUNNEL = 'TUNNEL_MODE'
|
|
|
|
|
|
class TransformProtocolTypes(object):
|
|
"""Supported transform protocols for ipsec tunnel profile"""
|
|
TRANSFORM_PROTOCOL_ESP = 'ESP'
|
|
|
|
|
|
class AuthenticationModeTypes(object):
|
|
"""Supported authentication modes for ipsec peer endpoint (default PSK)"""
|
|
AUTH_MODE_PSK = 'PSK'
|
|
AUTH_MODE_CERT = 'CERTIFICATE'
|
|
|
|
|
|
class DpdProfileActionTypes(object):
|
|
"""Supported DPD profile actions"""
|
|
DPD_PROFILE_ACTION_HOLD = 'HOLD'
|
|
|
|
|
|
class DpdProfileTimeoutLimits(object):
|
|
"""Supported DPD timeout range"""
|
|
DPD_TIMEOUT_MIN = 3
|
|
DPD_TIMEOUT_MAX = 360
|
|
|
|
|
|
class IkeSALifetimeLimits(object):
|
|
"""Limits to the allowed SA lifetime in seconds (NSX default is 1 day)"""
|
|
SA_LIFETIME_MIN = 21600
|
|
SA_LIFETIME_MAX = 31536000
|
|
|
|
|
|
class IPsecSALifetimeLimits(object):
|
|
"""Limits to the allowed SA lifetime in seconds (NSX default is 3600)"""
|
|
SA_LIFETIME_MIN = 900
|
|
SA_LIFETIME_MAX = 31536000
|
|
|
|
|
|
class ConnectionInitiationModeTypes(object):
|
|
"""Supported connection initiation mode type"""
|
|
INITIATION_MODE_INITIATOR = 'INITIATOR'
|
|
INITIATION_MODE_RESPOND_ONLY = 'RESPOND_ONLY'
|
|
INITIATION_MODE_ON_DEMAND = 'ON_DEMAND'
|
|
|
|
|
|
class IkeLogLevelTypes(object):
|
|
"""Supported service IKE log levels (default ERROR)"""
|
|
LOG_LEVEL_DEBUG = 'DEBUG'
|
|
LOG_LEVEL_INFO = 'INFO'
|
|
LOG_LEVEL_WARN = 'WARN'
|
|
LOG_LEVEL_ERROR = 'ERROR'
|
|
|
|
|
|
class IkeProfile(utils.NsxLibApiBase):
|
|
|
|
@property
|
|
def resource_type(self):
|
|
return 'IPSecVPNIKEProfile'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'ike-profiles'
|
|
|
|
def create(self, name, description=None,
|
|
encryption_algorithm=None,
|
|
digest_algorithm=None,
|
|
ike_version=None,
|
|
dh_group=None,
|
|
sa_life_time=None,
|
|
tags=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name}
|
|
# optional parameters
|
|
if description:
|
|
body['description'] = description
|
|
if encryption_algorithm:
|
|
body['encryption_algorithms'] = [encryption_algorithm]
|
|
if digest_algorithm:
|
|
body['digest_algorithms'] = [digest_algorithm]
|
|
if ike_version:
|
|
body['ike_version'] = ike_version
|
|
if sa_life_time:
|
|
body['sa_life_time'] = sa_life_time
|
|
if dh_group:
|
|
body['dh_groups'] = [dh_group]
|
|
if tags:
|
|
body['tags'] = tags
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
|
|
class IPSecTunnelProfile(utils.NsxLibApiBase):
|
|
|
|
@property
|
|
def resource_type(self):
|
|
return 'IPSecVPNTunnelProfile'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'tunnel-profiles'
|
|
|
|
def create(self, name, description=None,
|
|
encryption_algorithm=None,
|
|
digest_algorithm=None,
|
|
pfs=None,
|
|
dh_group=None,
|
|
sa_life_time=None,
|
|
tags=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name}
|
|
# optional parameters
|
|
if description:
|
|
body['description'] = description
|
|
if encryption_algorithm:
|
|
body['encryption_algorithms'] = [encryption_algorithm]
|
|
if digest_algorithm:
|
|
body['digest_algorithms'] = [digest_algorithm]
|
|
if sa_life_time:
|
|
body['sa_life_time'] = sa_life_time
|
|
if dh_group:
|
|
body['dh_groups'] = [dh_group]
|
|
if tags:
|
|
body['tags'] = tags
|
|
# Boolean parameters
|
|
if pfs is not None:
|
|
body['enable_perfect_forward_secrecy'] = pfs
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
|
|
class IPSecDpdProfile(utils.NsxLibApiBase):
|
|
@property
|
|
def resource_type(self):
|
|
return 'IPSecVPNDPDProfile'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'dpd-profiles'
|
|
|
|
def create(self, name, description=None, enabled=None, timeout=None,
|
|
tags=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name}
|
|
# optional parameters
|
|
if description:
|
|
body['description'] = description
|
|
if timeout:
|
|
body['dpd_probe_interval'] = timeout
|
|
# Boolean parameters
|
|
if enabled is not None:
|
|
body['enabled'] = enabled
|
|
if tags:
|
|
body['tags'] = tags
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
def update(self, profile_id, name=None, description=None, enabled=None,
|
|
timeout=None, tags=None):
|
|
|
|
body = self.get(profile_id)
|
|
if name:
|
|
body['display_name'] = name
|
|
if description:
|
|
body['description'] = description
|
|
if timeout:
|
|
body['dpd_probe_interval'] = timeout
|
|
if enabled is not None:
|
|
body['enabled'] = enabled
|
|
if tags is not None:
|
|
body['tags'] = tags
|
|
return self.client.update(self.get_path(profile_id), body=body)
|
|
|
|
|
|
class IPSecPeerEndpoint(utils.NsxLibApiBase):
|
|
|
|
@property
|
|
def resource_type(self):
|
|
return 'IPSecVPNPeerEndpoint'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'peer-endpoints'
|
|
|
|
def create(self, name, peer_address, peer_id,
|
|
description=None,
|
|
authentication_mode=None,
|
|
dpd_profile_id=None,
|
|
ike_profile_id=None,
|
|
ipsec_tunnel_profile_id=None,
|
|
connection_initiation_mode=None,
|
|
psk=None, tags=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name,
|
|
'peer_address': peer_address,
|
|
'peer_id': peer_id}
|
|
# optional parameters
|
|
if description:
|
|
body['description'] = description
|
|
if authentication_mode:
|
|
body['authentication_mode'] = authentication_mode
|
|
if dpd_profile_id:
|
|
body['dpd_profile_id'] = dpd_profile_id
|
|
if ike_profile_id:
|
|
body['ike_profile_id'] = ike_profile_id
|
|
if ipsec_tunnel_profile_id:
|
|
body['ipsec_tunnel_profile_id'] = ipsec_tunnel_profile_id
|
|
if psk:
|
|
body['psk'] = psk
|
|
if connection_initiation_mode:
|
|
body['connection_initiation_mode'] = connection_initiation_mode
|
|
if tags:
|
|
body['tags'] = tags
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
def update(self, uuid, name=None, description=None, peer_address=None,
|
|
peer_id=None, connection_initiation_mode=None, psk=None,
|
|
tags=None):
|
|
body = self.get(uuid)
|
|
if description:
|
|
body['description'] = description
|
|
if name:
|
|
body['display_name'] = name
|
|
if psk:
|
|
body['psk'] = psk
|
|
if connection_initiation_mode:
|
|
body['connection_initiation_mode'] = connection_initiation_mode
|
|
if peer_address:
|
|
body['peer_address'] = peer_address
|
|
if peer_id:
|
|
body['peer_id'] = peer_id
|
|
if tags is not None:
|
|
body['tags'] = tags
|
|
return self.client.update(self.get_path(uuid), body=body)
|
|
|
|
|
|
class LocalEndpoint(utils.NsxLibApiBase):
|
|
|
|
@property
|
|
def resource_type(self):
|
|
return 'IPSecVPNLocalEndpoint'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'local-endpoints'
|
|
|
|
def create(self, name, local_address, ipsec_vpn_service_id,
|
|
description=None,
|
|
local_id=None,
|
|
certificate_id=None,
|
|
trust_ca_ids=None,
|
|
trust_crl_ids=None,
|
|
tags=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name,
|
|
'local_address': local_address,
|
|
'ipsec_vpn_service_id': {'target_id': ipsec_vpn_service_id}}
|
|
# optional parameters
|
|
if description:
|
|
body['description'] = description
|
|
if local_id:
|
|
body['local_id'] = local_id
|
|
if certificate_id:
|
|
body['certificate_id'] = certificate_id
|
|
if trust_ca_ids:
|
|
body['trust_ca_ids'] = trust_ca_ids
|
|
if trust_crl_ids:
|
|
body['trust_crl_ids'] = trust_crl_ids
|
|
if tags:
|
|
body['tags'] = tags
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
def update(self, uuid, name=None, description=None, local_address=None,
|
|
ipsec_vpn_service_id=None, local_id=None,
|
|
certificate_id=None,
|
|
trust_ca_ids=None,
|
|
trust_crl_ids=None,
|
|
tags=None):
|
|
body = self.get(uuid)
|
|
if description:
|
|
body['description'] = description
|
|
if name:
|
|
body['display_name'] = name
|
|
if local_address:
|
|
body['local_address'] = local_address
|
|
if ipsec_vpn_service_id:
|
|
body['ipsec_vpn_service_id'] = {'target_id': ipsec_vpn_service_id}
|
|
if local_id:
|
|
body['local_id'] = local_id
|
|
if certificate_id:
|
|
body['certificate_id'] = certificate_id
|
|
if trust_ca_ids:
|
|
body['trust_ca_ids'] = trust_ca_ids
|
|
if trust_crl_ids:
|
|
body['trust_crl_ids'] = trust_crl_ids
|
|
if tags is not None:
|
|
body['tags'] = tags
|
|
return self.client.update(self.get_path(uuid), body=body)
|
|
|
|
|
|
class Session(utils.NsxLibApiBase):
|
|
|
|
@property
|
|
def resource_type(self):
|
|
return 'PolicyBasedIPSecVPNSession'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'sessions'
|
|
|
|
def create(self, name, local_endpoint_id, peer_endpoint_id,
|
|
policy_rules, description=None,
|
|
enabled=True, tags=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name,
|
|
'description': description,
|
|
'local_endpoint_id': local_endpoint_id,
|
|
'peer_endpoint_id': peer_endpoint_id,
|
|
'enabled': enabled,
|
|
'resource_type': self.resource_type,
|
|
'policy_rules': policy_rules}
|
|
if tags:
|
|
body['tags'] = tags
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
def get_rule_obj(self, sources, destinations):
|
|
src_subnets = [{'subnet': src} for src in sources]
|
|
dst_subnets = [{'subnet': dst} for dst in destinations]
|
|
return {
|
|
'sources': src_subnets,
|
|
'destinations': dst_subnets
|
|
}
|
|
|
|
def update(self, uuid, name=None, description=None, policy_rules=None,
|
|
tags=None, enabled=None):
|
|
body = self.get(uuid)
|
|
if description:
|
|
body['description'] = description
|
|
if name:
|
|
body['display_name'] = name
|
|
if name:
|
|
body['display_name'] = name
|
|
if policy_rules is not None:
|
|
body['policy_rules'] = policy_rules
|
|
if enabled is not None:
|
|
body['enabled'] = enabled
|
|
return self.client.update(self.get_path(uuid), body=body)
|
|
|
|
def get_status(self, uuid, source='realtime'):
|
|
try:
|
|
return self.client.get(
|
|
self.get_path(uuid + '/status?source=%s' % source))
|
|
except Exception as e:
|
|
LOG.warning("No status found for session %s: %s", uuid, e)
|
|
return
|
|
|
|
|
|
class Service(utils.NsxLibApiBase):
|
|
|
|
@property
|
|
def resource_type(self):
|
|
return 'IPSecVPNService'
|
|
|
|
@property
|
|
def uri_segment(self):
|
|
return VPN_IPSEC_PATH + 'services'
|
|
|
|
def create(self, name, logical_router_id,
|
|
enabled=True, ike_log_level="ERROR",
|
|
tags=None, bypass_rules=None):
|
|
|
|
# mandatory parameters
|
|
body = {'display_name': name,
|
|
'logical_router_id': logical_router_id}
|
|
# optional parameters
|
|
if ike_log_level:
|
|
body['ike_log_level'] = ike_log_level
|
|
if enabled is not None:
|
|
body['enabled'] = enabled
|
|
if tags:
|
|
body['tags'] = tags
|
|
if bypass_rules:
|
|
body['bypass_rules'] = bypass_rules
|
|
return self.client.create(self.get_path(), body=body)
|
|
|
|
|
|
class VpnIpSec(object):
|
|
"""This is the class that have all vpn ipsec resource clients"""
|
|
|
|
def __init__(self, client, nsxlib_config, nsxlib=None):
|
|
self.ike_profile = IkeProfile(client, nsxlib_config, nsxlib=nsxlib)
|
|
self.tunnel_profile = IPSecTunnelProfile(client, nsxlib_config,
|
|
nsxlib=nsxlib)
|
|
self.dpd_profile = IPSecDpdProfile(client, nsxlib_config,
|
|
nsxlib=nsxlib)
|
|
self.peer_endpoint = IPSecPeerEndpoint(client, nsxlib_config,
|
|
nsxlib=nsxlib)
|
|
self.local_endpoint = LocalEndpoint(client, nsxlib_config,
|
|
nsxlib=nsxlib)
|
|
self.session = Session(client, nsxlib_config, nsxlib=nsxlib)
|
|
self.service = Service(client, nsxlib_config, nsxlib=nsxlib)
|