vmware-nsxlib/vmware_nsxlib/v3/vpn_ipsec.py

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)