diff --git a/vmngclient/api/template_api.py b/vmngclient/api/template_api.py index d068688ba..8c968a558 100644 --- a/vmngclient/api/template_api.py +++ b/vmngclient/api/template_api.py @@ -26,6 +26,7 @@ from vmngclient.api.templates.models.cisco_ntp_model import CiscoNTPModel from vmngclient.api.templates.models.cisco_omp_model import CiscoOMPModel from vmngclient.api.templates.models.cisco_ospf import CiscoOSPFModel +from vmngclient.api.templates.models.cisco_secure_internet_gateway import CiscoSecureInternetGatewayModel from vmngclient.api.templates.models.cisco_snmp_model import CiscoSNMPModel from vmngclient.api.templates.models.cisco_system import CiscoSystemModel from vmngclient.api.templates.models.cisco_vpn_interface_model import CiscoVpnInterfaceModel @@ -510,6 +511,7 @@ def is_created_by_generator(self, template: FeatureTemplate) -> bool: CiscoBGPModel, CiscoOSPFModel, CliTemplateModel, + CiscoSecureInternetGatewayModel, ) return isinstance(template, ported_templates) diff --git a/vmngclient/api/templates/models/cisco_secure_internet_gateway.py b/vmngclient/api/templates/models/cisco_secure_internet_gateway.py new file mode 100644 index 000000000..4a297647e --- /dev/null +++ b/vmngclient/api/templates/models/cisco_secure_internet_gateway.py @@ -0,0 +1,198 @@ +import ipaddress +from enum import Enum +from pathlib import Path +from typing import ClassVar, List, Optional + +from pydantic import BaseModel, Field + +from vmngclient.api.templates.feature_template import FeatureTemplate +from vmngclient.utils.pydantic_validators import ConvertIPToStringModel + +DEFAULT_TRACKER_THRESHOLD = 300 +DEFAULT_TRACKER_INTERVAL = 60 +DEFAULT_TRACKER_MULTIPLIER = 3 +DEFAULT_INTERFACE_MTU = 1400 +DEFAULT_INTERFACE_DPD_INTERVAL = 10 +DEFAULT_INTERFACE_DPD_RETRIES = 3 +DEFAULT_INTERFACE_IKE_VERSION = 2 +DEFAULT_INTERFACE_IKE_REKEY_INTERVAL = 14400 +DEFAULT_INTERFACE_IPSEC_REKEY_INTERVAL = 3600 +DEFAULT_INTERFACE_IPSEC_REPLAY_WINDOW = 512 +DEFAULT_INTERFACE_PAIR_ACTIVE_INTERFACE_WEIGHT = 1 +DEFAULT_INTERFACE_PAIR_BACKUP_INTERFACE_WEIGHT = 1 +DEFAULT_SIG_VPN_ID = 0 +DEFAULT_SERVICE_IDLE_TIME = 0 +DEFAULT_SERVICE_REFRESH_TIME = 0 + + +class Application(str, Enum): + SIG = "sig" + + +class TunnelSet(str, Enum): + SECURE_INTERNET_GATEWAY_UMBRELLA = "secure-internet-gateway-umbrella" + SECURE_INTERNET_GATEWAY_ZSCALER = "secure-internet-gateway-zscaler" + + +class TunnelDcPreference(str, Enum): + PRIMARY_DC = "primary-dc" + SECONDARY_DC = "secondary-dc" + + +class IkeCiphersuite(str, Enum): + AES256_CBC_SHA1 = "aes256-cbc-sha1" + AES256_CBC_SHA2 = "aes256-cbc-sha2" + AES128_CBC_SHA1 = "aes128-cbc-sha1" + AES128_CBC_SHA2 = "aes128-cbc-sha2" + + +class IkeGroup(str, Enum): + TWO = "2" + FOURTEEN = "14" + FIFTEEN = "15" + SIXTEEN = "16" + + +class IpsecCiphersuite(str, Enum): + AES256_CBC_SHA1 = "aes256-cbc-sha1" + AES256_CBC_SHA384 = "aes256-cbc-sha384" + AES256_CBC_SHA256 = "aes256-cbc-sha256" + AES256_CBC_SHA512 = "aes256-cbc-sha512" + AES256_GCM = "aes256-gcm" + NULL_SHA1 = "null-sha1" + NULL_SHA384 = "null-sha384" + NULL_SHA256 = "null-sha256" + NULL_SHA512 = "null-sha512" + + +class PerfectForwardSecrecy(str, Enum): + GROUP_2 = "group-2" + GROUP_14 = "group-14" + GROUP_15 = "group-15" + GROUP_16 = "group-16" + NONE = "none" + + +class Interface(ConvertIPToStringModel): + if_name: str = Field(alias="if-name") + auto: bool + shutdown: bool + description: Optional[str] + unnumbered: bool = True + address: Optional[ipaddress.IPv4Interface] + tunnel_source: ipaddress.IPv4Address = Field(alias="tunnel-source") + tunnel_source_interface: str = Field(alias="tunnel-source-interface") + tunnel_route_via: str = Field(alias="tunnel-route-via") + tunnel_destination: str = Field(alias="tunnel-destination") + application: Application = Application.SIG + tunnel_set: TunnelSet = Field(TunnelSet.SECURE_INTERNET_GATEWAY_UMBRELLA, alias="tunnel-set") + tunnel_dc_preference: TunnelDcPreference = Field(TunnelDcPreference.PRIMARY_DC, alias="tunnel-dc-preference") + tcp_mss_adjust: Optional[int] = Field(alias="tcp-mss-adjust") + mtu: int = DEFAULT_INTERFACE_MTU + dpd_interval: Optional[int] = Field(DEFAULT_INTERFACE_DPD_INTERVAL, alias="dpd-interval") + dpd_retries: Optional[int] = Field(DEFAULT_INTERFACE_DPD_RETRIES, alias="dpd-retries") + ike_version: int = Field(DEFAULT_INTERFACE_IKE_VERSION, alias="ike-version") + pre_shared_secret: Optional[str] = Field(alias="pre-shared-secret") + ike_rekey_interval: Optional[int] = Field(DEFAULT_INTERFACE_IKE_REKEY_INTERVAL, alias="ike-rekey-interval") + ike_ciphersuite: Optional[IkeCiphersuite] = Field(IkeCiphersuite.AES256_CBC_SHA1, alias="ike-ciphersuite") + ike_group: IkeGroup = Field(IkeGroup.FOURTEEN, alias="ike-group") + pre_shared_key_dynamic: bool = Field(True, alias="pre-shared-key-dynamic") + ike_local_id: Optional[str] = Field(alias="ike-local-id") + ike_remote_id: Optional[str] = Field(alias="ike-remote-id") + ipsec_rekey_interval: Optional[int] = Field(DEFAULT_INTERFACE_IPSEC_REKEY_INTERVAL, alias="ipsec-rekey-interval") + ipsec_replay_window: Optional[int] = Field(DEFAULT_INTERFACE_IPSEC_REPLAY_WINDOW, alias="ipsec-replay-window") + ipsec_ciphersuite: IpsecCiphersuite = Field(IpsecCiphersuite.AES256_GCM, alias="ipsec-ciphersuite") + perfect_forward_secrecy: PerfectForwardSecrecy = Field(PerfectForwardSecrecy.NONE, alias="perfect-forward-secrecy") + tracker: Optional[bool] + track_enable: Optional[bool] = Field(True, alias="track-enable") + + class Config: + allow_population_by_field_name = True + + +class SvcType(str, Enum): + SIG = "sig" + + +class InterfacePair(BaseModel): + active_interface: str = Field(alias="active-interface") + active_interface_weight: int = Field( + DEFAULT_INTERFACE_PAIR_ACTIVE_INTERFACE_WEIGHT, alias="active-interface-weight" + ) + backup_interface: Optional[str] = Field("None", alias="backup-interface") + backup_interface_weight: int = Field( + DEFAULT_INTERFACE_PAIR_BACKUP_INTERFACE_WEIGHT, alias="backup-interface-weight" + ) + + class Config: + allow_population_by_field_name = True + + +class DisplayTimeUnit(str, Enum): + MINUTE = "MINUTE" + HOUR = "HOUR" + DAY = "DAY" + + +class RefreshTimeUnit(str, Enum): + MINUTE = "MINUTE" + HOUR = "HOUR" + DAY = "DAY" + + +class Service(BaseModel): + svc_type: SvcType = Field(SvcType.SIG, alias="svc-type") + interface_pair: List[InterfacePair] = Field(alias="interface-pair") + auth_required: Optional[bool] = Field(False, alias="auth-required") + xff_forward_enabled: Optional[bool] = Field(False, alias="xff-forward-enabled") + ofw_enabled: Optional[bool] = Field(False, alias="ofw-enabled") + ips_control: Optional[bool] = Field(False, alias="ips-control") + caution_enabled: Optional[bool] = Field(False, alias="caution-enabled") + primary_data_center: Optional[str] = Field("Auto", alias="primary-data-center") + secondary_data_center: Optional[str] = Field("Auto", alias="secondary-data-center") + ip: Optional[bool] + idle_time: Optional[int] = Field(DEFAULT_SERVICE_IDLE_TIME, alias="idle-time") + display_time_unit: Optional[DisplayTimeUnit] = Field(DisplayTimeUnit.MINUTE, alias="display-time-unit") + ip_enforced_for_known_browsers: Optional[bool] = Field(False, alias="ip-enforced-for-known-browsers") + refresh_time: Optional[int] = Field(DEFAULT_SERVICE_REFRESH_TIME, alias="refresh-time") + refresh_time_unit: Optional[RefreshTimeUnit] = Field(RefreshTimeUnit.MINUTE, alias="refresh-time-unit") + enabled: Optional[bool] + block_internet_until_accepted: Optional[bool] = Field(False, alias="block-internet-until-accepted") + force_ssl_inspection: Optional[bool] = Field(False, alias="force-ssl-inspection") + timeout: Optional[int] + data_center_primary: Optional[str] = Field("Auto", alias="data-center-primary") + data_center_secondary: Optional[str] = Field("Auto", alias="data-center-secondary") + + class Config: + allow_population_by_field_name = True + + +class TrackerType(str, Enum): + SIG = "SIG" + + +class Tracker(BaseModel): + name: str + endpoint_api_url: str = Field(alias="endpoint-api-url") + threshold: Optional[int] = DEFAULT_TRACKER_THRESHOLD + interval: Optional[int] = DEFAULT_TRACKER_INTERVAL + multiplier: Optional[int] = DEFAULT_TRACKER_MULTIPLIER + tracker_type: TrackerType = Field(alias="tracker-type") + + class Config: + allow_population_by_field_name = True + + +class CiscoSecureInternetGatewayModel(FeatureTemplate, ConvertIPToStringModel): + class Config: + arbitrary_types_allowed = True + allow_population_by_field_name = True + + vpn_id: int = Field(DEFAULT_SIG_VPN_ID, alias="vpn-id") + interface: List[Interface] + service: List[Service] + tracker_src_ip: ipaddress.IPv4Interface = Field(alias="tracker-src-ip") + tracker: Optional[List[Tracker]] + + payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED" + type: ClassVar[str] = "cisco_secure_internet_gateway" diff --git a/vmngclient/api/templates/models/supported.py b/vmngclient/api/templates/models/supported.py index 876bc42a4..f30f698ed 100644 --- a/vmngclient/api/templates/models/supported.py +++ b/vmngclient/api/templates/models/supported.py @@ -4,6 +4,7 @@ from vmngclient.api.templates.models.cisco_logging_model import CiscoLoggingModel from vmngclient.api.templates.models.cisco_ntp_model import CiscoNTPModel from vmngclient.api.templates.models.cisco_ospf import CiscoOSPFModel +from vmngclient.api.templates.models.cisco_secure_internet_gateway import CiscoSecureInternetGatewayModel from vmngclient.api.templates.models.cisco_snmp_model import CiscoSNMPModel from vmngclient.api.templates.models.cisco_system import CiscoSystemModel from vmngclient.api.templates.models.cisco_vpn_interface_model import CiscoVpnInterfaceModel @@ -27,4 +28,5 @@ "cisco_vpn": CiscoVPNModel, "cisco_snmp": CiscoSNMPModel, "cisco_system": CiscoSystemModel, + "cisco_secure_internet_gateway": CiscoSecureInternetGatewayModel, } diff --git a/vmngclient/utils/pydantic_validators.py b/vmngclient/utils/pydantic_validators.py index 8a24fdbc4..c7893803d 100644 --- a/vmngclient/utils/pydantic_validators.py +++ b/vmngclient/utils/pydantic_validators.py @@ -1,3 +1,6 @@ +import ipaddress +from typing import Any + from pydantic import BaseModel, root_validator @@ -8,3 +11,20 @@ def convert_bool_to_string_validator(cls, values): if isinstance(value, bool): values[key] = str(value).lower() return values + + +class ConvertIPToStringModel(BaseModel): + @root_validator # type: ignore + def convert_ip_to_string_validator(cls, values): + for key, value in values.items(): + values[key] = convert_ip_to_string(value) + return values + + +def convert_ip_to_string(values: Any): + if isinstance(values, list): + for index, ip in enumerate(values): + values[index] = convert_ip_to_string(ip) + if isinstance(values, ipaddress._BaseAddress): + values = str(values) + return values