class VSSContext(Engine): typeof = 'vss_context' virtual_resource = ElementRef('virtual_resource') def __init__(self, name, **meta): super(VSSContext, self).__init__(name, **meta) @classmethod def create(cls, isc_name, isc_policy_id, isc_traffic_tag, vss_container): """ Create the VSS Context within the VSSContainer :param str name: ISC name, possibly append policy name?? :param str isc_policy_id: Policy ID in SMC (the 'key' attribute) :param str isc_traffic_tag: NSX groupId (serviceprofile-145) :param VSSContainer vss_container: VSS Container to get create context :raises CreateElementFailed :rtype: VSSContext """ container = element_resolver(vss_container) return ElementCreator(cls, href=container + '/vss_context', json = { 'vc_isc': { 'isc_name': isc_name, 'isc_policy_id': isc_policy_id, 'isc_traffic_tag': isc_traffic_tag } }) def remove_from_master_node(self, wait_for_finish=False, timeout=20, **kw): """ Remove this VSS Context from it's parent VSS Container. This is required before calling VSSContext.delete(). It preps the engine for removal. :param bool wait_for_finish: wait for the task to finish :param int timeout: how long to wait if delay :type: TaskOperationPoller """ return Task.execute(self, 'remove_from_master_node', timeout=timeout, wait_for_finish=wait_for_finish, **kw) def move_to_master_node(self, master): pass @property def isc_settings(self): """ ISC Settings are used to provide information about the security policy mapping for the engine. :return dict of engine vc_isc attribute 'vc_isc': {'isc_name': 'isc_VMPolicy', 'isc_policy_id': 17, 'isc_traffic_tag': 'serviceprofile-145'}, """ return self.data.get('vc_isc')
class ExternalBGPPeer(Element): """ An External BGP represents the AS and IP settings for a remote BGP peer. Creating a BGP peer requires that you also pre-create an :class:`~AutonomousSystem` element:: AutonomousSystem.create(name='neighborA', as_number=500) ExternalBGPPeer.create(name='name', neighbor_as_ref=AutonomousSystem('neighborA'), neighbor_ip='1.1.1.1') :ivar AutonomousSystem neighbor_as: AS for this external BGP peer """ typeof = 'external_bgp_peer' neighbor_as = ElementRef('neighbor_as') @classmethod def create(cls, name, neighbor_as, neighbor_ip, neighbor_port=179, comment=None): """ Create an external BGP Peer. :param str name: name of peer :param str,AutonomousSystem neighbor_as_ref: AutonomousSystem element or href. :param str neighbor_ip: ip address of BGP peer :param int neighbor_port: port for BGP, default 179. :raises CreateElementFailed: failed creating :return: instance with meta :rtype: ExternalBGPPeer """ json = {'name': name, 'neighbor_ip': neighbor_ip, 'neighbor_port': neighbor_port, 'comment': comment} neighbor_as_ref = element_resolver(neighbor_as) json.update(neighbor_as=neighbor_as_ref) return ElementCreator(cls, json) @property def neighbor_ip(self): """ IP address of the external BGP Peer :return: ipaddress of external bgp peer :rtype: str """ return self.data.get('neighbor_ip') @property def neighbor_port(self): """ Port used for neighbor AS :return: neighbor port :rtype: int """ return self.data.get('neighbor_port')
class GatewayCertificate(SubElement): """ A Gateway Certificate repesents a certificate assigned to a NGFW certificate used for VPN endpoints. Gateway certificates are typically renewed automatically when the auto renew option is set on the engine. However you can also optionally force renew a gateway certificate, export, check the expiration, or find the certificate authority that signed this gateway certificate. :ivar certificate_authority: CA for this GatewayCertificate """ typeof = "gateway_certificate" certificate_authority = ElementRef("certificate_authority") @staticmethod def _create( self, common_name, public_key_algorithm="rsa", signature_algorithm="rsa_sha_512", key_length=2048, signing_ca=None, ): """ Internal method called as a reference from the engine.vpn node """ if signing_ca is None: signing_ca = VPNCertificateCA.objects.filter("Internal RSA").first() cert_auth = element_resolver(signing_ca) return ElementCreator( GatewayCertificate, exception=CertificateError, href=self.internal_gateway.get_relation("generate_certificate"), json={ "common_name": common_name, "public_key_algorithm": public_key_algorithm, "signature_algorithm": signature_algorithm, "public_key_length": key_length, "certificate_authority_href": cert_auth, }, ) @property def certificate(self): return self.certificate_base64 def renew(self): pass @property def expiration(self): pass def export_certificate(self): pass
class ExternalLdapUserDomain(Browseable, Element): """ External User Domain represents an external LDAP service configured to retrieve identity information. Identities are synchronized into SMC and then can be used as source objects within a policy. :ivar list(ActiveDirectoryServer) ldap_server: LDAP server/s used by this external domain :ivar AuthenticationMethod auth_method: default authentication method for this domain. Can also be set as attribute. """ typeof = 'external_ldap_user_domain' ldap_server = ElementList('ldap_server') auth_method = ElementRef('auth_method') @classmethod def create(cls, name, ldap_server, isdefault=False, auth_method=None, comment=None): """ Create an External LDAP user domain. These are used as containers for retrieving user and groups from the configured LDAP server/s. If you have multiple authentication methods supported for your LDAP server, or have none configured, you can set the `auth_method` to a supported AuthenticationMethod. :param str name: name of external LDAP domain :param list(str,ActiveDirectoryServer) ldap_server: list of existing authentication servers in href or element format :param bool isdefault: set this to 'Default LDAP domain' :param str,AuthenticationMethod auth_method: authentication method to use. Usually set when multiple are defined in LDAP service or none are defined. :param str comment: optional comment :raises CreateElementFailed: failed to create :rtype: ExternalLdapUserDomain """ return ElementCreator(cls, json={ 'name': name, 'ldap_server': element_resolver(ldap_server), 'auth_method': element_resolver(auth_method), 'isdefault': isdefault, 'comment': comment })
class ValidatePolicyTask(ScheduledTaskMixin, Element): """ Run a policy validation task. This does not perform a policy push. This may be useful if you want to validate any pending changes before a future policy push. :ivar Element policy: The policy associated with this task """ typeof = "validate_policy_task" policy = ElementRef("policy") @classmethod def create(cls, name, engines, policy=None, comment=None, **kwargs): """ Create a new validate policy task. If a policy is not specified, the engines existing policy will be validated. Override default validation settings as kwargs. :param str name: name of task :param engines: list of engines to validate :type engines: list(Engine) :param Policy policy: policy to validate. Uses the engines assigned policy if none specified. :param kwargs: see :func:`~policy_validation_settings` for keyword arguments and default values. :raises ElementNotFound: engine or policy specified does not exist :raises CreateElementFailed: failure to create the task :return: the task :rtype: ValidatePolicyTask """ json = { "name": name, "resources": [eng.href for eng in engines], "policy": policy.href if policy is not None else policy, "comment": comment, } if kwargs: json.update(policy_validation_settings(**kwargs)) return ElementCreator(cls, json)
class DHCPServer(Element): """ A DHCP Server based element. Used in various areas to define External DHCP Server. """ typeof = "dhcp_server" location = ElementRef("location_ref") @classmethod def create(cls, name, address, ipv6_address=None, location=None, comment=None): """ Create a DHCP Server element. :param str name: Name of DHCP Server :param str address: IP address for DHCP Server element :param str ipv6_address: IPv6 addres fir DHCP Server :param str location: Specifies the location for the server if there is a NAT device between the server and other SMC components. :param str comment: Comment for DHCP Server element :raises CreateElementFailed: Failed to create with reason :rtype: DHCPServer """ json = { "name": name, "address": address, "ipv6_address": ipv6_address, "comment": comment } if location: json.update(location_ref=element_resolver(location)) return ElementCreator(cls, json)
class MultilinkMember(object): """ A multilink member represents an netlink member used on a multilink configuration. Multilink uses netlinks to specify settings specific to a connection, network, whether it should be active or standby and optionally QoS. Use this class to create mutlilink members that are required for creating a Multilink element. :ivar Network network: network element reference specifying netlink subnet :ivar StaticNetlink,DynamicNetlink netlink: netlink element reference """ network = ElementRef('network_ref') netlink = ElementRef('netlink_ref') def __init__(self, kwargs): self.data = ElementCache(kwargs) def __eq__(self, other): return all([ self.ip_range == other.ip_range, self.netlink_role == other.netlink_role, self.data.get('network_ref') == other.data.get('network_ref'), self.data.get('netlink_ref') == other.data.get('netlink_ref') ]) def __ne__(self, other): return not self == other def __hash__(self): return hash((self.ip_range, self.netlink_role, self.data.get('network_ref'), self.data.get('netlink_ref'))) @property def ip_range(self): """ Specifies the IP address range for dynamic source address translation (NAT) for the internal source IP addresses on the NetLink. Can also be set. :rtype: str """ return self.data.get('ip_range') @ip_range.setter def ip_range(self, value): if '-' in value: self.data.update(ip_range=value) @property def netlink_role(self): """ Shows whether the Netlink is active or standby. Active - traffic is routed through the NetLink according to the method you specify in the Outbound Multi-Link element properties. Standby - traffic is only routed through the netlink if all primary (active) netlinks are unavailable. :rtype: str """ return self.data.get('netlink_role') @netlink_role.setter def netlink_role(self, value): if value in ('standby', 'active'): self.data.update(netlink_role=value) @classmethod def create(cls, netlink, ip_range=None, netlink_role='active'): """ Create a multilink member. Multilink members are added to an Outbound Multilink configuration and define the ip range, static netlink to use, and the role. This element can be passed to the Multilink constructor to simplify creation of the outbound multilink. :param StaticNetlink,DynamicNetlink netlink: static netlink element to use as member :param str ip_range: the IP range for source NAT for this member. The IP range should be part of the defined network range used by this netlink. Not required for dynamic netlink :param str netlink_role: role of this netlink, 'active' or 'standby' :raises ElementNotFound: Specified netlink could not be found :rtype: MultilinkMember """ member_def = dict( netlink_ref=netlink.href, netlink_role=netlink_role, ip_range=ip_range if netlink.typeof == 'netlink' else '0.0.0.0') if netlink.typeof == 'netlink': # static netlink vs dynamic netlink member_def.update(network_ref=netlink.network[0].href) return cls(member_def) def __repr__(self): return 'MultilinkMember(netlink={},netlink_role={},ip_range={})'.format( self.netlink, self.netlink_role, self.ip_range)
class Policy(Element): """ Policy is the base class for all policy types managed by the SMC. This base class is not intended to be instantiated directly. Subclasses should implement create(....) individually as each subclass will likely have different input requirements. All generic methods that are policy level, such as 'open', 'save', 'force_unlock', 'export', and 'upload' are encapsulated into this base class. :ivar Element template: The template associated with this policy. Can be None :ivar InspectionPolicy inspection_policy: related inspection policy :ivar FileFilteringPolicy file_filtering_policy: related file policy """ template = ElementRef('template') inspection_policy = ElementRef('inspection_policy') file_filtering_policy = ElementRef('file_filtering_policy') def upload(self, engine, timeout=5, wait_for_finish=False, **kw): """ Upload policy to specific device. Using wait for finish returns a poller thread for monitoring progress:: policy = FirewallPolicy('_NSX_Master_Default') poller = policy.upload('myfirewall', wait_for_finish=True) while not poller.done(): poller.wait(3) print(poller.task.progress) print("Task finished: %s" % poller.message()) :param str engine: name of device to upload policy to :raises: TaskRunFailed :return: TaskOperationPoller """ return Task.execute(self, 'upload', params={'filter': engine}, timeout=timeout, wait_for_finish=wait_for_finish, **kw) def force_unlock(self): """ Forcibly unlock a locked policy :return: None """ self.make_request(PolicyCommandFailed, method='create', resource='force_unlock') def search_rule(self, search): """ Search a rule for a rule tag or name value Result will be the meta data for rule (name, href, type) Searching for a rule in specific policy:: f = FirewallPolicy(policy) search = f.search_rule(searchable) :param str search: search string :return: rule elements matching criteria :rtype: list(Element) """ result = self.make_request(resource='search_rule', params={'filter': search}) if result: results = [] for data in result: typeof = data.get('type') if 'ethernet' in typeof: klazz = lookup_class('ethernet_rule') elif typeof in [ 'ips_ipv4_access_rule', 'l2_interface_ipv4_access_rule' ]: klazz = lookup_class('layer2_ipv4_access_rule') else: klazz = lookup_class(typeof) results.append(klazz(**data)) return results return [] def rule_counters(self, engine, duration_type='one_week', duration=0, start_time=0): """ .. versionadded:: 0.5.6 Obtain rule counters for this policy. Requires SMC >= 6.2 Rule counters can be obtained for a given policy and duration for those counters can be provided in duration_type. A custom start range can also be provided. :param Engine engine: the target engine to obtain rule counters from :param str duration_type: duration for obtaining rule counters. Valid options are: one_day, one_week, one_month, six_months, one_year, custom, since_last_upload :param int duration: if custom set for duration type, specify the duration in seconds (Default: 0) :param int start_time: start time in milliseconds (Default: 0) :raises: ActionCommandFailed :return: list of rule counter objects :rtype: RuleCounter """ json = {'target_ref': engine.href, 'duration_type': duration_type} return [ RuleCounter(**rule) for rule in self.make_request( method='create', resource='rule_counter', json=json) ]
class ActiveDirectoryServer(ContactAddressMixin, Element): """ Create an Active Directory Element. At a minimum you must provide the name, address and base_dn for the connection. If you do not provide bind_user_id and bind_password, the connection type will use anonymous authentication (not recommended). You can also pass kwargs to customize aspects of the AD server configuration. Valid kwargs are: :param TLSProfile tls_profile: TLS profile used when ldaps or start_tls specified :param str user_id_attr: The name that the server uses for the UserID Attribute (default: sAMAccountName) :param str user_principal_name: The name of the attribute for storing the users UPN (default: userPrincipalName) :param str display_name_attr_name: The attribute storing the users friendly name (default: displayName) :param str email: The attribute storing the users email address (default: email) :param str group_member_attr: The attribute storing group membership details (default: member) :param str job_title_attr_name: The attribute storing users job title (default: title) :param str frame_ip_attr_name: The attribute storing the users IP address when user is authenticated via RADIUS (default: msRADIUSFramedIPAddress) :param str mobile_attr_name: The attribute storing the users mobile (default: mobile) :param str office_location_attr: The attribute storing the users office location (default: physicalDeliveryOfficeName) :param str photo: The attribute with users photo used for display (default: photo) :param list group_object_class: If your Active Directory or LDAP server has LDAP object classes that are not defined in the SMC by default, you must add those object classes to the LDAP Object classes in the server properties (default: ['group', 'organizationUnit', 'organization', 'country', 'groupOfNames', 'sggroup'] :param list user_object_class: LDAP classes used for user identification (default: ['inetOrgPerson','organizationalPerson', 'person', 'sguser']) :param str client_cert_based_user_search: Not implemented :param int auth_port: required when internet authentication service is enabled (default: 1812) :param str auth_ipaddress: required when internet authentication service is enabled :param str shared_secret: required when internet authentication service is enabled :param int retries: Used with IAS. Number of times firewall will try to connect to the RADIUS or TACACS+ authentication server if the connection fails (default: 2) """ typeof = 'active_directory_server' tls_profile = ElementRef('tls_profile_ref') supported_method = ElementList('supported_method') @classmethod def create(cls, name, address, base_dn, bind_user_id=None, bind_password=None, port=389, protocol='ldap', tls_profile=None, tls_identity=None, domain_controller=None, supported_method=None, timeout=10, max_search_result=0, page_size=0, internet_auth_service_enabled=False, retries=3, **kwargs): """ Create an AD server element using basic settings. You can also provide additional kwargs documented in the class description:: ActiveDirectoryServer.create(name='somedirectory', address='10.10.10.10', base_dn='dc=domain,dc=net', bind_user_id='cn=admin,cn=users,dc=domain,dc=net', bind_password='******') Configure NPS along with Active Directory:: ActiveDirectoryServer.create(name='somedirectory5', address='10.10.10.10', base_dn='dc=du,dc=net', internet_auth_service_enabled=True, retries=3, auth_ipaddress='10.10.10.15', auth_port=1900, shared_secret='123456') :param str name: name of AD element for display :param str address: address of AD server :param str base_dn: base DN for which to retrieve users, format is 'dc=domain,dc=com' :param str bind_user_id: bind user ID credentials, fully qualified. Format is 'cn=admin,cn=users,dc=domain,dc=com'. If not provided, anonymous bind is used :param str bind_password: bind password, required if bind_user_id set :param int port: LDAP bind port, (default: 389) :param str protocol: Which LDAP protocol to use, options 'ldap/ldaps/ldap_tls'. If ldaps or ldap_tls is used, you must provide a tls_profile element (default: ldap) :param str,TLSProfile tls_profile by element of str href. Used when protocol is set to ldaps or ldap_tls :param str,TLSIdentity tls_identity: check server identity when establishing TLS connection :param list(DomainController) domain_controller: list of domain controller objects to add an additional domain controllers for AD communication :param list(AuthenticationMethod) supported_method: authentication services allowed for this resource :param int timeout: The time (in seconds) that components wait for the server to reply :param int max_search_result: The maximum number of LDAP entries that are returned in an LDAP response (default: 0 for no limit) :param int page_size: The maximum number of LDAP entries that are returned on each page of the LDAP response. (default: 0 for no limit) :param bool internet_auth_service_enabled: whether to attach an NPS service to this AD controller (default: False). If setting to true, provide kwargs values for auth_ipaddress, auth_port and shared_secret :raises CreateElementFailed: failed creating element :rtype: ActiveDirectoryServer """ json = { 'name': name, 'address': address, 'base_dn': base_dn, 'bind_user_id': bind_user_id, 'bind_password': bind_password, 'port': port, 'protocol': protocol, 'timeout': timeout, 'domain_controller': domain_controller or [], 'retries': retries, 'max_search_result': max_search_result, 'page_size': page_size, 'internet_auth_service_enabled': internet_auth_service_enabled, 'supported_method': element_resolver(supported_method) or [] } for obj_class in ('group_object_class', 'user_object_class'): json[obj_class] = kwargs.pop(obj_class, []) if protocol in ('ldaps', 'ldap_tls'): if not tls_profile: raise CreateElementFailed( 'You must provide a TLS Profile when TLS ' 'connections are configured to the AD controller.') json.update(tls_profile_ref=element_resolver(tls_profile), tls_identity=tls_identity) if internet_auth_service_enabled: ias = { 'auth_port': kwargs.pop('auth_port', 1812), 'auth_ipaddress': kwargs.pop('auth_ipaddress', ''), 'shared_secret': kwargs.pop('shared_secret') } json.update(ias) json.update(kwargs) return ElementCreator(cls, json) @classmethod def update_or_create(cls, with_status=False, **kwargs): """ Update or create active directory configuration. :param dict kwargs: kwargs to satisfy the `create` constructor arguments if the element doesn't exist or attributes to change :raises CreateElementFailed: failed creating element :return: element instance by type or 3-tuple if with_status set """ element, updated, created = super( ActiveDirectoryServer, cls).update_or_create(defer_update=True, **kwargs) if not created: domain_controller = kwargs.pop('domain_controller', []) if domain_controller: current_dc_list = element.domain_controller for dc in domain_controller: if dc not in current_dc_list: element.data.setdefault('domain_controller', []).append(dc.data) updated = True if updated: element.update() if with_status: return element, updated, created return element @property def domain_controller(self): """ List of optional domain controllers specified for this AD resource. When adding domain controllers through update_or_create, only domain controllers that do not already exist are added. :rtype: list(DomainController) """ return [ DomainController(**dc) for dc in self.data.get('domain_controller', []) ] def check_connectivity(self): """ Return a status for this active directory controller :raises ActionCommandFailed: failed to check connectivity with reason :rtype: bool """ return self.make_request( href=self.get_relation('check_connectivity')) is None
class OSPFProfile(Element): """ An OSPF Profile contains administrative distance and redistribution settings. An OSPF Profile is set on the engine element when enabling OSPF. These settings are always in effect: * No autosummary Example of creating an OSPFProfile with the default domain profile:: OSPFProfile.create(name='myospf') .. note:: Enable OSPF on engine using engine.ospf.enable() :ivar int external_distance: external distance metric :ivar int inter_distance: inter distance metric :ivar int intra_distance: intra distance metric :ivar int default_metric: set a default metric for all unset areas :ivar list redistribution_entry: settings for static, connected, etc :ivar OSPFDomainSetting domain_settings_ref: OSPF Domain Settings profile used for this OSPF Profile """ typeof = 'ospfv2_profile' domain_settings_ref = ElementRef('domain_settings_ref') @classmethod def create(cls, name, domain_settings_ref=None, external_distance=110, inter_distance=110, intra_distance=110, redistribution_entry=None, default_metric=None, comment=None): """ Create an OSPF Profile. If providing a list of redistribution entries, provide in the following dict format: {'enabled': boolean, 'metric_type': 'external_1' or 'external_2', 'metric': 2, 'type': 'kernel'} Valid types for redistribution entries are: kernel, static, connected, bgp, and default_originate. You can also provide a 'filter' key with either an IPAccessList or RouteMap element to use for further access control on the redistributed route type. If metric_type is not provided, external_1 (E1) will be used. An example of a redistribution_entry would be:: {u'enabled': True, u'metric': 123, u'metric_type': u'external_2', u'filter': RouteMap('myroutemap'), u'type': u'static'} :param str name: name of profile :param str,OSPFDomainSetting domain_settings_ref: OSPFDomainSetting element or href :param int external_distance: route metric (E1-E2) :param int inter_distance: routes learned from different areas (O IA) :param int intra_distance: routes learned from same area (O) :param list redistribution_entry: how to redistribute the OSPF routes. :raises CreateElementFailed: create failed with reason :rtype: OSPFProfile """ json = {'name': name, 'external_distance': external_distance, 'inter_distance': inter_distance, 'intra_distance': intra_distance, 'default_metric': default_metric, 'comment': comment} if redistribution_entry: json.update(redistribution_entry= _format_redist_entry(redistribution_entry)) domain_settings_ref = element_resolver(domain_settings_ref) or \ OSPFDomainSetting('Default OSPFv2 Domain Settings').href json.update(domain_settings_ref=domain_settings_ref) return ElementCreator(cls, json) @classmethod def update_or_create(cls, filter_key=None, with_status=False, **kwargs): if 'redistribution_entry' in kwargs: kwargs.update(redistribution_entry=_format_redist_entry( kwargs.pop('redistribution_entry', []))) element, updated, created = super(OSPFProfile, cls).update_or_create( filter_key, defer_update=True, **kwargs) if not created: # Deferred update, update redistribution settings if 'redistribution_entry' in kwargs: element.data['redistribution_entry'] = kwargs.get('redistribution_entry') element.update() updated = True if with_status: return element, updated, created return element
class OSPF(object): """ OSPF configuration on the engine. Access through an engine reference:: engine.dynamic_routing.ospf.status engine.dynamic_rotuing.ospf.enable(....) When making changes to the OSPF configuration, any methods called that change the configuration also require that engine.update() is called once changes are complete. This way you can make multiple changes without refreshing the engine cache. :ivar OSPFProfile profile: OSPFProfile reference for this engine """ profile = ElementRef('ospfv2_profile_ref') def __init__(self, data=None): self.data = data if data else ElementCache() @property def router_id(self): """ Get the router ID for this OSPF configuration. If None, then the ID will use the interface IP. :return: str or None """ return self.data.get('router_id') @property def status(self): """ Is OSPF enabled on this engine. :rtype: bool """ return self.data.get('enabled') def disable(self): """ Disable OSPF on this engine. :return: None """ self.data.update( enabled=False) def enable(self, ospf_profile=None, router_id=None): """ Enable OSPF on this engine. For master engines, enable OSPF on the virtual firewall. Once enabled on the engine, add an OSPF area to an interface:: engine.dynamic_routing.ospf.enable() interface = engine.routing.get(0) interface.add_ospf_area(OSPFArea('myarea')) :param str,OSPFProfile ospf_profile: OSPFProfile element or str href; if None, use default profile :param str router_id: single IP address router ID :raises ElementNotFound: OSPF profile not found :return: None """ ospf_profile = element_resolver(ospf_profile) if ospf_profile \ else OSPFProfile('Default OSPFv2 Profile').href self.data.update( enabled=True, ospfv2_profile_ref=ospf_profile, router_id=router_id) def update_configuration(self, **kwargs): """ Update the OSPF configuration using kwargs that match the `enable` constructor. :param dict kwargs: keyword arguments matching enable constructor. :return: whether change was made :rtype: bool """ updated = False if 'ospf_profile' in kwargs: kwargs.update(ospfv2_profile_ref=kwargs.pop('ospf_profile')) for name, value in kwargs.items(): _value = element_resolver(value) if self.data.get(name) != _value: self.data[name] = _value updated = True return updated
class OSPFArea(Element): """ OSPF Area is an element that identifies general settings for an OSPF configuration applied to an engine routing node. The OSPFArea has a reference to an OSPFInterfaceSetting and is required when creating. Create a basic OSPFArea with just area id:: OSPFArea.create(name='myarea', area_id=0) Create an OSPFArea and use a custom OSPFInterfaceSetting element:: OSPFArea.create( name='customOSPFArea', interface_settings_ref=OSPFInterfaceSetting('myospf'), area_id=3) **Advanced example:** Adding ospf_virtual_links_endpoints:: OSPFArea.create( name='ospf', interface_settings_ref=intf, area_id=3, ospfv2_virtual_links_endpoints_container= [{'interface_settings_ref': 'http://172.18.1.150:8082/6.1/elements/ospfv2_interface_settings/8', 'router_id_endpoint_A': '192.168.1.1', 'router_id_endpoint_B': '192.168.1.254'}, {'router_id_endpoint_A': '172.18.1.254', 'router_id_endpoint_B': '172.18.1.200'}]) When using ABR substitute rules, there are 3 actions, 'aggregate', 'not_advertise' and 'substitute_with'. All references required are of type :py:class:`smc.elements.network.Network`. These elements can either be created or retrieved using collections, or by getting the resource directly. Example of creating an OSPF area and using ABR settings:: OSPFArea.create( name='area_with_abr', interface_settings_ref=intf, area_id=1, ospf_abr_substitute_container=[ {'subnet_ref': 'http://172.18.1.150:8082/6.1/elements/network/143', 'substitute_ref': 'http://172.18.1.150:8082/6.1/elements/network/1547', 'substitute_type': 'substitute_with'}, {'subnet_ref': 'http://172.18.1.150:8082/6.1/elements/network/979', 'substitute_type': 'aggregate'}]) :ivar OSPFInterfaceSetting interface_settings_ref: reference to the OSPFInterfaceSetting element """ typeof = 'ospfv2_area' interface_settings_ref = ElementRef('interface_settings_ref') @classmethod def create(cls, name, interface_settings_ref=None, area_id=1, area_type='normal', outbound_filters=None, inbound_filters=None, shortcut_capable_area=False, ospfv2_virtual_links_endpoints_container=None, ospf_abr_substitute_container=None, comment=None, **kwargs): """ Create a new OSPF Area :param str name: name of OSPFArea configuration :param str,OSPFInterfaceSetting interface_settings_ref: an OSPFInterfaceSetting element or href. If None, uses the default system profile :param str name: area id :param str area_type: \|normal\|stub\|not_so_stubby\|totally_stubby\| totally_not_so_stubby :param list outbound_filters: reference to an IPAccessList and or IPPrefixList. You can only have one outbound prefix or access list :param list inbound_filters: reference to an IPAccessList and or IPPrefixList. You can only have one outbound prefix or access list :param shortcut_capable_area: True|False :param list ospfv2_virtual_links_endpoints_container: virtual link endpoints :param list ospf_abr_substitute_container: substitute types: \|aggregate\|not_advertise\|substitute_with :param str comment: optional comment :raises CreateElementFailed: failed to create with reason :rtype: OSPFArea """ interface_settings_ref = element_resolver(interface_settings_ref) or \ OSPFInterfaceSetting('Default OSPFv2 Interface Settings').href if 'inbound_filters_ref' in kwargs: inbound_filters = kwargs.get('inbound_filters_ref') if 'outbound_filters_ref' in kwargs: outbound_filters = kwargs.get('outbound_filters_ref') json = {'name': name, 'area_id': area_id, 'area_type': area_type, 'comment': comment, 'inbound_filters_ref': element_resolver(inbound_filters), 'interface_settings_ref': interface_settings_ref, 'ospf_abr_substitute_container': ospf_abr_substitute_container, 'ospfv2_virtual_links_endpoints_container': ospfv2_virtual_links_endpoints_container, 'outbound_filters_ref': element_resolver(outbound_filters), 'shortcut_capable_area': shortcut_capable_area} return ElementCreator(cls, json) @classmethod def update_or_create(cls, filter_key=None, with_status=False, **kwargs): if 'inbound_filters' in kwargs: kwargs.update(inbound_filters_ref= element_resolver(kwargs.pop('inbound_filters'))) if 'outbound_filters' in kwargs: kwargs.update(outbound_filters_ref= element_resolver(kwargs.pop('outbound_filters'))) return super(OSPFArea, cls).update_or_create(filter_key, with_status, **kwargs) @property def inbound_filters(self): """ Inbound filters attached to this OSPF Area. Filters can be type IPPrefixList or IPAccessList :rtype: list """ return [Element.from_href(filt) for filt in self.data.get('inbound_filters_ref', [])] @property def outbound_filters(self): """ Outbound filters attached to this OSPF Area. Filters can be type IPPrefixList or IPAccessList :rtype: list """ return [Element.from_href(filt) for filt in self.data.get('outbound_filters_ref', [])]
class OSPFInterfaceSetting(Element): """ OSPF Interface Setting indicate specific configurations that are applied to the interface and OSPF Area configuration, including authentication. If you require non-default settings applied to your interface OSPF instance, you can create a custom interface profile:: OSPFInterfaceSetting.create( name='myprofile', dead_interval=30, hello_interval=5) When using authentication on interface settings, there are two types, password authentication (plain text) or message digest. When specifying an authentication_type='password', the password parameter must be provided. When specifying authentication_type='message_digest', the key_chain_ref parameter must be specified. """ typeof = 'ospfv2_interface_settings' key_chain_ref = ElementRef('key_chain_ref') @classmethod def create(cls, name, dead_interval=40, hello_interval=10, hello_interval_type='normal', dead_multiplier=1, mtu_mismatch_detection=True, retransmit_interval=5, router_priority=1, transmit_delay=1, authentication_type=None, password=None, key_chain_ref=None): """ Create custom OSPF interface settings profile :param str name: name of interface settings :param int dead_interval: in seconds :param str hello_interval: in seconds :param str hello_interval_type: \|normal\|fast_hello :param int dead_multipler: fast hello packet multipler :param bool mtu_mismatch_detection: True|False :param int retransmit_interval: in seconds :param int router_priority: set priority :param int transmit_delay: in seconds :param str authentication_type: \|password\|message_digest :param str password: max 8 chars (required when authentication_type='password') :param str,Element key_chain_ref: OSPFKeyChain (required when authentication_type='message_digest') :raises CreateElementFailed: create failed with reason :return: instance with meta :rtype: OSPFInterfaceSetting """ json = {'name': name, 'authentication_type': authentication_type, 'password': password, 'key_chain_ref': element_resolver(key_chain_ref), 'dead_interval': dead_interval, 'dead_multiplier': dead_multiplier, 'hello_interval': hello_interval, 'hello_interval_type': hello_interval_type, 'mtu_mismatch_detection': mtu_mismatch_detection, 'retransmit_interval': retransmit_interval, 'router_priority': router_priority, 'transmit_delay': transmit_delay} return ElementCreator(cls, json)
class ElasticsearchCluster(ContactAddressMixin, Element): """ An ElasticsearchCluster server type element. """ typeof = "elasticsearch_cluster" location = ElementRef("location_ref") @classmethod def create( cls, name, addresses, port=9200, es_retention_period=30, es_shard_number=0, es_replica_number=0, enable_cluster_sniffer=False, location=None, comment=None, tls_profile=None, use_internal_credentials=True, tls_credentials=None, ): """ Create a Elasticsearch Cluster Server element. :param str name: Name of Elasticsearch Cluster :param list addresses: comma-separated list of one or more FQDNs or IP addresses :param int port: Default port is 9200 :param int es_retention_period: How much time logs will be kept 30days default :param int es_shard_number: Auto by default, number of shards :param int es_replica_number : number of ES replicas :param bool enable_cluster_sniffer : Enable cluster sniffer (False default) :param str location: Specifies the location for the server if there is a NAT device between the server and other SMC components. :param str comment: Comment for Elasticsearch cluster Server element :param str tls_profile: tls profile name to use :param bool use_internal_credentials: use internal credentials :param str tls_credentials: tls credentials name to use :raises CreateElementFailed: Failed to create with reason :rtype: ElasticsearchCluster """ json = { "name": name, "port": port, "es_retention_period": es_retention_period, "es_shard_number": es_shard_number, "es_replica_number": es_replica_number, "es_enable_cluster_sniffer": enable_cluster_sniffer, "comment": comment, } addresses_lst = addresses.split(",") json.update(addresses=addresses_lst) if location: location_href = Location(location).href json.update(location_ref=location_href) if tls_profile: tls_profile_ref = tls.TLSProfile(tls_profile).href json.update(tls_profile=tls_profile_ref) if tls_credentials: tls_credentials_ref = tls.TLSServerCredential(tls_credentials).href json.update( es_tls_settings={ "use_internal_credentials": use_internal_credentials, "tls_credentials": tls_credentials_ref, }) else: json.update(es_tls_settings={ "use_internal_credentials": use_internal_credentials }) return ElementCreator(cls, json)
class TunnelEndpoint(object): """ A Tunnel Endpoint represents one side of a route based VPN. Based on the RBVPN type required, you must create the local and remote endpoints and pass them into the RouteVPN create classmethods. :ivar InternalGateway,ExternalGateway gateway: reference to the element that is used by this tunnel endpoint :ivar TunnelInterface tunnel_interface: Tunnel interface used by this tunnel endpoint """ gateway = ElementRef("gateway_ref") def __init__(self, gateway_ref=None, tunnel_interface_ref=None, endpoint_ref=None, ip_address=None): self.gateway_ref = gateway_ref self.tunnel_interface_ref = tunnel_interface_ref self.endpoint_ref = endpoint_ref self.ip_address = ip_address @property def endpoint(self): """ Endpoint is used to specify which interface is enabled for VPN. This is the InternalEndpoint property of the InternalGateway. .. note:: This will only return a value if the tunnel type is GRE :return: internal endpoint where VPN is enabled :rtype: InternalEndpoint,ExternalGateway """ if self.endpoint_ref and self.tunnel_interface_ref: return InternalEndpoint(href=self.endpoint_ref) return Element.from_href(self.endpoint_ref) @property def tunnel_interface(self): """ Show the tunnel interface for this TunnelEndpoint. :return: interface for this endpoint :rtype: TunnelInterface """ if self.tunnel_interface_ref: return TunnelInterface(href=self.tunnel_interface_ref) @classmethod def create_gre_tunnel_endpoint(cls, endpoint=None, tunnel_interface=None, remote_address=None): """ Create the GRE tunnel mode or no encryption mode endpoint. If the GRE tunnel mode endpoint is an SMC managed device, both an endpoint and a tunnel interface is required. If the endpoint is externally managed, only an IP address is required. :param InternalEndpoint,ExternalEndpoint endpoint: the endpoint element for this tunnel endpoint. :param TunnelInterface tunnel_interface: the tunnel interface for this tunnel endpoint. Required for SMC managed devices. :param str remote_address: IP address, only required if the tunnel endpoint is a remote gateway. :rtype: TunnelEndpoint """ tunnel_interface = tunnel_interface.href if tunnel_interface else None endpoint = endpoint.href if endpoint else None return TunnelEndpoint(tunnel_interface_ref=tunnel_interface, endpoint_ref=endpoint, ip_address=remote_address) @classmethod def create_gre_transport_endpoint(cls, endpoint, tunnel_interface=None): """ Create the GRE transport mode endpoint. If the GRE transport mode endpoint is an SMC managed device, both an endpoint and a tunnel interface is required. If the GRE endpoint is an externally managed device, only an endpoint is required. :param InternalEndpoint,ExternalEndpoint endpoint: the endpoint element for this tunnel endpoint. :param TunnelInterface tunnel_interface: the tunnel interface for this tunnel endpoint. Required for SMC managed devices. :rtype: TunnelEndpoint """ tunnel_interface = tunnel_interface.href if tunnel_interface else None return TunnelEndpoint(endpoint_ref=endpoint.href, tunnel_interface_ref=tunnel_interface) @classmethod def create_ipsec_endpoint(cls, gateway, tunnel_interface=None): """ Create the VPN tunnel endpoint. If the VPN tunnel endpoint is an SMC managed device, both a gateway and a tunnel interface is required. If the VPN endpoint is an externally managed device, only a gateway is required. :param InternalGateway,ExternalGateway gateway: the gateway for this tunnel endpoint :param TunnelInterface tunnel_interface: Tunnel interface for this RBVPN. This can be None if the gateway is a non-SMC managed gateway. :rtype: TunnelEndpoint """ tunnel_interface = tunnel_interface.href if tunnel_interface else None return TunnelEndpoint(gateway_ref=gateway.href, tunnel_interface_ref=tunnel_interface) @property def data(self): return {k: v for k, v in vars(self).items() if v} @property def remote_address(self): """ Show the remote IP address configured for a GRE RBVPN using Tunnel or No Encryption Mode configurations. """ return self.ip_address
class PolicyVPN(Element): """ Create a new VPN Policy. :: >>> PolicyVPN.create(name='myvpn') PolicyVPN(name=myvpn) >>> v = PolicyVPN('myvpn') >>> print(v.vpn_profile) VPNProfile(name=VPN-A Suite) When making VPN Policy modifications, you must first call :func:`open`, make your modifications and then call :func:`save` followed by :func:`close`. :ivar VPNProfile vpn_profile: VPN Profile used by this Policy VPN """ typeof = "vpn" vpn_profile = ElementRef("vpn_profile") @classmethod def create(cls, name, nat=False, mobile_vpn_toplogy_mode=None, vpn_profile=None): """ Create a new policy based VPN :param name: name of vpn policy :param bool nat: whether to apply NAT to the VPN (default False) :param mobile_vpn_toplogy_mode: whether to allow remote vpn :param VPNProfile vpn_profile: reference to VPN profile, or uses default :rtype: PolicyVPN """ vpn_profile = element_resolver(vpn_profile) or VPNProfile("VPN-A Suite").href json = { "mobile_vpn_topology_mode": mobile_vpn_toplogy_mode, "name": name, "nat": nat, "vpn_profile": vpn_profile, } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreatePolicyFailed(err) @property def nat(self): """ Is NAT enabled on this vpn policy :return: NAT enabled :rtype: bool """ return self.data.get("nat") def enable_disable_nat(self): """ Enable or disable NAT on this policy. If NAT is disabled, it will be enabled and vice versa. :return: None """ if self.nat: self.data["nat"] = False else: self.data["nat"] = True @property def central_gateway_node(self): """ Central Gateway Node acts as the hub of a hub-spoke VPN. :rtype: SubElementCollection(GatewayNode) """ return sub_collection( self.get_relation("central_gateway_node"), type("CentralGatewayNode", (GatewayNode,), {}), ) @property def satellite_gateway_node(self): """ Node level settings for configured satellite gateways :rtype: SubElementCollection(GatewayNode) """ return sub_collection( self.get_relation("satellite_gateway_node"), type("SatelliteGatewayNode", (GatewayNode,), {}), ) @property def mobile_gateway_node(self): """ Mobile Gateway's are represented by client endpoints connecting to the policy based VPN. :rtype: SubElementCollection(GatewayNode) """ return sub_collection( self.get_relation("mobile_gateway_node"), type("MobileGatewayNode", (GatewayNode,), {}) ) @property def tunnels(self): """ Return all tunnels for this VPN. A tunnel is defined as two end points within the VPN topology. Endpoints are automatically configureed based on whether they are a central gateway or satellite gateway. This provides access to enabling/disabling and setting the preshared key for the linked endpoints. List all tunnel mappings for this policy vpn:: for tunnel in policy.tunnels: tunnela = tunnel.tunnel_side_a tunnelb = tunnel.tunnel_side_b print(tunnela.gateway) print(tunnelb.gateway) :rtype: SubElementCollection(GatewayTunnel) """ return sub_collection(self.get_relation("gateway_tunnel"), GatewayTunnel) def open(self): """ Open the policy for editing. This is only a valid method for SMC version <= 6.1 :raises PolicyCommandFailed: couldn't open policy with reason :return: None """ self.make_request(PolicyCommandFailed, method="create", resource="open") def save(self): """ Save the policy after editing. This is only a valid method for SMC version <= 6.1 :raises PolicyCommandFailed: save failed with reason :return: None """ self.make_request(PolicyCommandFailed, method="create", resource="save") self._del_cache() def close(self): """ Close the policy. This is only a valid method for SMC version <= 6.1 :raises PolicyCommandFailed: close failed with reason :return: None """ self.make_request(PolicyCommandFailed, method="create", resource="close") def validate(self): """ Return a validation string from the SMC after running validate on this VPN policy. :return: status as dict :rtype: dict """ return self.make_request(resource="validate") @property def mobile_vpn_topology(self): """ Is the policy VPN configured for mobile VPN gateways. Valid modes: 'Selected Gateways below', 'Only central Gateways from overall topology', 'All Gateways from overall topology', 'None' """ return self.data.get("mobile_vpn_topology_mode") def add_mobile_gateway(self, all_central_gateways=False, all_gateways=False, gateways=None): """ Add a mobile VPN gateway to this policy VPN. You can select all central gateways, all gateways in overall topology or specify a list of gateways to allow for mobile VPN. Example of adding or removing a mobile VPN gateway:: policy_vpn = PolicyVPN('myvpn') policy_vpn.update(mobile_vpn_topology_mode='Selected Gateways below') policy_vpn.open() policy_vpn.add_mobile_vpn_gateway(gateways=Engine('azure')) policy_vpn.save() policy_vpn.close() :param Engine,ExternalGateway gateway: An external gateway, engine or href for the mobile gateway :raises PolicyCommandFailed: could not add gateway :rtype: None """ if all_central_gateways: self.update(mobile_vpn_topology_mode="Only central Gateways from overall topology") elif all_gateways: self.update(mobile_vpn_topology_mode="All Gateways from overall topology") if gateways and self.mobile_vpn_topology != "Selected Gateways below": raise PolicyCommandFailed( "You must first update the policy VPN with " "the Selected Gateways below setting before adding members" ) if gateways: try: gateway = gateways.vpn.internal_gateway.href # Engine except AttributeError: raise PolicyCommandFailed( "VPN endpoint does not appear to " "be a managed engine: %s" % gateways ) self.make_request( PolicyCommandFailed, method="create", resource="mobile_gateway_node", json={"gateway": gateway, "node_usage": "mobile"}, ) def add_central_gateway(self, gateway): """ Add SMC managed internal gateway to the Central Gateways of this VPN :param Engine,ExternalGateway gateway: An external gateway, engine or href for the central gateway :raises PolicyCommandFailed: could not add gateway :return: None """ try: gateway = gateway.vpn.internal_gateway.href except AttributeError: gateway = element_resolver(gateway) self.make_request( PolicyCommandFailed, method="create", resource="central_gateway_node", json={"gateway": gateway, "node_usage": "central"}, ) def add_satellite_gateway(self, gateway): """ Add gateway node as a satellite gateway for this VPN. You must first have the gateway object created. This is typically used when you either want a hub-and-spoke topology or the test_external gateway is a non-SMC managed device. :param Engine,ExternalGateway gateway: An external gateway, engine or href for the central gateway :raises PolicyCommandFailed: could not add gateway :return: None """ try: gateway = gateway.vpn.internal_gateway.href except AttributeError: gateway = element_resolver(gateway) self.make_request( PolicyCommandFailed, method="create", resource="satellite_gateway_node", json={"gateway": gateway, "node_usage": "satellite"}, ) @staticmethod def add_internal_gateway_to_vpn(internal_gateway_href, vpn_policy, vpn_role="central"): """ Add an internal gateway (managed engine node) to a VPN policy based on the internal gateway href. :param str internal_gateway_href: href for engine internal gw :param str vpn_policy: name of vpn policy :param str vpn_role: central|satellite :return: True for success :rtype: bool """ try: vpn = PolicyVPN(vpn_policy) vpn.open() if vpn_role == "central": vpn.add_central_gateway(internal_gateway_href) else: vpn.add_satellite_gateway(internal_gateway_href) vpn.save() vpn.close() except ElementNotFound: return False return True
class VPNSite(SubElement): """ VPN Site information for an internal or test_external gateway Sites are used to encapsulate hosts or networks as 'protected' for VPN policy configuration. Create a new vpn site for an engine:: engine = Engine('myengine') network = Network('network-192.168.5.0/25') #get resource engine.vpn.sites.create('newsite', [network.href]) Sites can also be added to ExternalGateway's as well:: extgw = ExternalGateway('mygw') extgw.vpn_site.create('newsite', [Network('foo')]) This class is a property of :py:class:`smc.core.engine.InternalGateway` or :py:class:`smc.vpn.elements.ExternalGateway` and should not be accessed directly. :ivar InternalGateway,ExternalGateway gateway: gateway referenced """ typeof = "vpn_site" gateway = ElementRef("gateway") def create(self, name, site_element): """ Create a VPN site for an internal or external gateway :param str name: name of site :param list site_element: list of protected networks/hosts :type site_element: list[str,Element] :raises CreateElementFailed: create element failed with reason :return: href of new element :rtype: str """ site_element = element_resolver(site_element) json = {"name": name, "site_element": site_element} return ElementCreator(self.__class__, href=self.href, json=json) @classmethod def update_or_create(cls, external_gateway, name, site_element=None, with_status=False): """ Update or create a VPN Site elements or modify an existing VPN site based on value of provided site_element list. The resultant VPN site end result will be what is provided in the site_element argument (can also be an empty list to clear existing). :param ExternalGateway external_gateway: The external gateway for this VPN site :param str name: name of the VPN site :param list(str,Element) site_element: list of resolved Elements to add to the VPN site :param bool with_status: If set to True, returns a 3-tuple of (VPNSite, modified, created), where modified and created is the boolean status for operations performed. :raises ElementNotFound: ExternalGateway or unresolved site_element """ site_element = [] if not site_element else site_element site_elements = [element_resolver(element) for element in site_element] vpn_site = external_gateway.vpn_site.get_exact(name) updated = False created = False if vpn_site: # If difference, reset if set(site_elements) != set(vpn_site.data.get("site_element", [])): vpn_site.data["site_element"] = site_elements vpn_site.update() updated = True else: vpn_site = external_gateway.vpn_site.create( name=name, site_element=site_elements) created = True if with_status: return vpn_site, updated, created return vpn_site @property def name(self): name = super(VPNSite, self).name if not name: return self.data.get("name") return name @property def site_element(self): """ Site elements for this VPN Site. :return: Elements used in this VPN site :rtype: list(Element) """ return [ Element.from_href(element) for element in self.data.get("site_element") ] def add_site_element(self, element): """ Add a site element or list of elements to this VPN. :param list element: list of Elements or href's of vpn site elements :type element: list(str,Network) :raises UpdateElementFailed: fails due to reason :return: None """ element = element_resolver(element) self.data["site_element"].extend(element) self.update()
class BGPPeering(Element): """ BGP Peering is applied directly to an interface and defines basic connection settings. A BGPConnectionProfile is required to create a BGPPeering and if not provided, the default profile will be used. The most basic peering can simply specify the name of the peering and leverage the default BGPConnectionProfile:: BGPPeering.create(name='my-aws-peer') :ivar BGPConnectionProfile connection_profile: BGP connection profile for this peering """ typeof = 'bgp_peering' connection_profile = ElementRef('connection_profile') @classmethod def create(cls, name, connection_profile_ref=None, md5_password=None, local_as_option='not_set', max_prefix_option='not_enabled', send_community='no', connected_check='disabled', orf_option='disabled', next_hop_self=True, override_capability=False, dont_capability_negotiate=False, remote_private_as=False, route_reflector_client=False, soft_reconfiguration=True, ttl_option='disabled', comment=None): """ Create a new BGPPeering configuration. :param str name: name of peering :param str,BGPConnectionProfile connection_profile_ref: required BGP connection profile. System default used if not provided. :param str md5_password: optional md5_password :param str local_as_option: the local AS mode. Valid options are: 'not_set', 'prepend', 'no_prepend', 'replace_as' :param str max_prefix_option: The max prefix mode. Valid options are: 'not_enabled', 'enabled', 'warning_only' :param str send_community: the send community mode. Valid options are: 'no', 'standard', 'extended', 'standard_and_extended' :param str connected_check: the connected check mode. Valid options are: 'disabled', 'enabled', 'automatic' :param str orf_option: outbound route filtering mode. Valid options are: 'disabled', 'send', 'receive', 'both' :param bool next_hop_self: next hop self setting :param bool override_capability: is override received capabilities :param bool dont_capability_negotiate: do not send capabilities :param bool remote_private_as: is remote a private AS :param bool route_reflector_client: Route Reflector Client (iBGP only) :param bool soft_reconfiguration: do soft reconfiguration inbound :param str ttl_option: ttl check mode. Valid options are: 'disabled', 'ttl-security' :raises CreateElementFailed: failed creating profile :return: instance with meta :rtype: BGPPeering """ json = { 'name': name, 'local_as_option': local_as_option, 'max_prefix_option': max_prefix_option, 'send_community': send_community, 'connected_check': connected_check, 'orf_option': orf_option, 'next_hop_self': next_hop_self, 'override_capability': override_capability, 'dont_capability_negotiate': dont_capability_negotiate, 'soft_reconfiguration': soft_reconfiguration, 'remove_private_as': remote_private_as, 'route_reflector_client': route_reflector_client, 'ttl_option': ttl_option, 'comment': comment } if md5_password: json.update(md5_password=md5_password) connection_profile_ref = element_resolver(connection_profile_ref) or \ BGPConnectionProfile('Default BGP Connection Profile').href json.update(connection_profile=connection_profile_ref) return ElementCreator(cls, json)
class BGP(object): """ BGP represents the BGP configuration on a given engine. An instance is returned from an engine reference:: engine = Engine('myengine') engine.dynamic_routing.bgp.status engine.dynamic_routing.bgp.announced_networks ... When making changes to the BGP configuration, any methods called that change the configuration also require that engine.update() is called once changes are complete. This way you can make multiple changes without refreshing the engine cache. For example, adding advertised networks to the configuration:: engine.dynamic_routing.bgp.update_configuration(announced_network=[Network('foo')]) engine.update() :ivar AutonomousSystem autonomous_system: AS reference for this BGP configuration :ivar BGPProfile profile: BGP profile reference for this configuration """ autonomous_system = ElementRef('bgp_as_ref') profile = ElementRef('bgp_profile_ref') def __init__(self, data=None): self.data = data if data else ElementCache() @property def router_id(self): """ Get the router ID for this BGP configuration. If None, then the ID will use the interface IP. :return: str or None """ return self.data.get('router_id') @property def status(self): """ Is BGP enabled on this engine. :rtype: bool """ return self.data.get('enabled') def disable(self): """ Disable BGP on this engine. :return: None """ self.data.update(enabled=False, announced_ne_setting=[]) def enable(self, autonomous_system, announced_networks, router_id=None, bgp_profile=None): """ Enable BGP on this engine. On master engine, enable BGP on the virtual firewall. When adding networks to `announced_networks`, the element types can be of type :class:`smc.elements.network.Host`, :class:`smc.elements.network.Network` or :class:`smc.elements.group.Group`. If passing a Group, it must have element types of host or network. Within announced_networks, you can pass a 2-tuple that provides an optional :class:`smc.routing.route_map.RouteMap` if additional policy is required for a given network. :: engine.dynamic_routing.bgp.enable( autonomous_system=AutonomousSystem('aws_as'), announced_networks=[Network('bgpnet'),Network('inside')], router_id='10.10.10.10') :param str,AutonomousSystem autonomous_system: provide the AS element or str href for the element :param str,BGPProfile bgp_profile: provide the BGPProfile element or str href for the element; if None, use system default :param list announced_networks: list of networks to advertise via BGP Announced networks can be single networks,host or group elements or a 2-tuple with the second tuple item being a routemap element :param str router_id: router id for BGP, should be an IP address. If not set, automatic discovery will use default bound interface as ID. :raises ElementNotFound: OSPF, AS or Networks not found :return: None .. note:: For arguments that take str or Element, the str value should be the href of the element. """ autonomous_system = element_resolver(autonomous_system) bgp_profile = element_resolver(bgp_profile) or \ BGPProfile('Default BGP Profile').href announced = self._unwrap(announced_networks) self.data.update(enabled=True, bgp_as_ref=autonomous_system, bgp_profile_ref=bgp_profile, announced_ne_setting=announced, router_id=router_id) def update_configuration(self, **kwargs): """ Update configuration using valid kwargs as defined in the enable constructor. :param dict kwargs: kwargs to satisfy valid args from `enable` :rtype: bool """ updated = False if 'announced_networks' in kwargs: kwargs.update( announced_ne_setting=kwargs.pop('announced_networks')) if 'bgp_profile' in kwargs: kwargs.update(bgp_profile_ref=kwargs.pop('bgp_profile')) if 'autonomous_system' in kwargs: kwargs.update(bgp_as_ref=kwargs.pop('autonomous_system')) announced_ne = kwargs.pop('announced_ne_setting', None) for name, value in kwargs.items(): _value = element_resolver(value) if self.data.get(name) != _value: self.data[name] = _value updated = True if announced_ne is not None: s = self.data.get('announced_ne_setting') ne = self._unwrap(announced_ne) if len(announced_ne) != len(s) or not self._equal(ne, s): self.data.update(announced_ne_setting=ne) updated = True return updated def _equal(self, dict1, dict2): _s = { entry.get('announced_ne_ref'): entry.get('announced_rm_ref') for entry in dict1 } _d = { entry.get('announced_ne_ref'): entry.get('announced_rm_ref') for entry in dict2 } return len({k: _s[k] for k in _s if k not in _d or _d.get(k) != _s[k]}) == 0 def _unwrap(self, network): _announced = [] for net in network: d = dict() if isinstance(net, tuple): _network, _routemap = net d.update(announced_ne_ref=_network.href) if _routemap: d.update(announced_rm_ref=_routemap.href) _announced.append(d) continue d.update(announced_ne_ref=net.href) _announced.append(d) return _announced @property def announced_networks(self): """ Show all announced networks for the BGP configuration. Returns tuple of advertised network, routemap. Route map may be None. :: for advertised in engine.bgp.advertisements: net, route_map = advertised :return: list of tuples (advertised_network, route_map). """ return [(Element.from_href(ne.get('announced_ne_ref')), Element.from_href(ne.get('announced_rm_ref'))) for ne in self.data.get('announced_ne_setting')]
class RouteVPN(Element): """ Route based VPN in NGFW. :ivar VPNProfile vpn_profile: VPNProfile reference for this RouteVPN :ivar TunnelMonitoringGroup monitoring_group: tunnel monitoring group reference """ typeof = 'rbvpn_tunnel' vpn_profile = ElementRef('vpn_profile_ref') monitoring_group = ElementRef('monitoring_group_ref') @classmethod def create_ipsec_tunnel(cls, name, local_endpoint, remote_endpoint, preshared_key=None, monitoring_group=None, vpn_profile=None, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None): """ The VPN tunnel type negotiates IPsec tunnels in the same way as policy-based VPNs, but traffic is selected to be sent into the tunnel based on routing. :param str name: name of VPN :param TunnelEndpoint local_endpoint: the local side endpoint for this VPN. :param TunnelEndpoint remote_endpoint: the remote side endpoint for this VPN. :param str preshared_key: required if remote endpoint is an ExternalGateway :param TunnelMonitoringGroup monitoring_group: the group to place this VPN in for monitoring. Default: 'Uncategorized'. :param VPNProfile vpn_profile: VPN profile for this VPN. (default: VPN-A Suite) :param int mtu: Set MTU for this VPN tunnel (default: 0) :param boolean pmtu_discovery: enable pmtu discovery (default: True) :param int ttl: ttl for connections on the VPN (default: 0) :param bool enabled: enable the RBVPN or leave it disabled :param str comment: optional comment :raises CreateVPNFailed: failed to create the VPN with reason :rtype: RouteVPN """ group = monitoring_group or TunnelMonitoringGroup('Uncategorized') profile = vpn_profile or VPNProfile('VPN-A Suite') json = { 'name': name, 'mtu': mtu, 'ttl': ttl, 'enabled': enabled, 'monitoring_group_ref': group.href, 'pmtu_discovery': pmtu_discovery, 'preshared_key': preshared_key, 'rbvpn_tunnel_side_a': local_endpoint.data, 'rbvpn_tunnel_side_b': remote_endpoint.data, 'tunnel_mode': 'vpn', 'comment': comment, 'vpn_profile_ref': profile.href } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) @classmethod def create_gre_tunnel_mode(cls, name, local_endpoint, remote_endpoint, policy_vpn, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None): """ Create a GRE based tunnel mode route VPN. Tunnel mode GRE wraps the GRE tunnel in an IPSEC tunnel to provide encrypted end-to-end security. Therefore a policy based VPN is required to 'wrap' the GRE into IPSEC. :param str name: name of VPN :param TunnelEndpoint local_endpoint: the local side endpoint for this VPN. :param TunnelEndpoint remote_endpoint: the remote side endpoint for this VPN. :param PolicyVPN policy_vpn: reference to a policy VPN :param TunnelMonitoringGroup monitoring_group: the group to place this VPN in for monitoring. (default: 'Uncategorized') :param int mtu: Set MTU for this VPN tunnel (default: 0) :param boolean pmtu_discovery: enable pmtu discovery (default: True) :param int ttl: ttl for connections on the VPN (default: 0) :param str comment: optional comment :raises CreateVPNFailed: failed to create the VPN with reason :rtype: RouteVPN """ json = { 'name': name, 'ttl': ttl, 'mtu': mtu, 'pmtu_discovery': pmtu_discovery, 'tunnel_encryption': 'tunnel_mode', 'tunnel_mode': 'gre', 'enabled': enabled, 'comment': comment, 'rbvpn_tunnel_side_a': local_endpoint.data, 'rbvpn_tunnel_side_b': remote_endpoint.data } if policy_vpn is None: json['tunnel_encryption'] = 'no_encryption' else: json['tunnel_mode_vpn_ref'] = policy_vpn.href try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) @classmethod def create_gre_tunnel_no_encryption(cls, name, local_endpoint, remote_endpoint, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None): """ Create a GRE Tunnel with no encryption. See `create_gre_tunnel_mode` for constructor descriptions. """ return cls.create_gre_tunnel_mode( name, local_endpoint, remote_endpoint, policy_vpn=None, mtu=mtu, pmtu_discovery=pmtu_discovery, ttl=ttl, enabled=enabled, comment=comment) @classmethod def create_gre_transport_mode(cls, name, local_endpoint, remote_endpoint, preshared_key, monitoring_group=None, vpn_profile=None, mtu=0, ttl=0, pmtu_discovery=True, enabled=True, comment=None): """ Create a transport based route VPN. This VPN type uses IPSEC for protecting the payload, therefore a VPN Profile is specified. :param str name: name of VPN :param TunnelEndpoint local_endpoint: the local side endpoint for this VPN. :param TunnelEndpoint remote_endpoint: the remote side endpoint for this VPN. :param str preshared_key: preshared key for RBVPN :param TunnelMonitoringGroup monitoring_group: the group to place this VPN in for monitoring. (default: 'Uncategorized') :param VPNProfile vpn_profile: VPN profile for this VPN. (default: VPN-A Suite) :param int mtu: Set MTU for this VPN tunnel (default: 0) :param boolean pmtu_discovery: enable pmtu discovery (default: True) :param int ttl: ttl for connections on the VPN (default: 0) :param str comment: optional comment :raises CreateVPNFailed: failed to create the VPN with reason :rtype: RouteVPN """ group = monitoring_group or TunnelMonitoringGroup('Uncategorized') profile = vpn_profile or VPNProfile('VPN-A Suite') json = { 'name': name, 'mtu': mtu, 'ttl': ttl, 'preshared_key': preshared_key, 'pmtu_discovery': pmtu_discovery, 'monitoring_group_ref': group.href, 'rbvpn_tunnel_side_a': local_endpoint.data, 'rbvpn_tunnel_side_b': remote_endpoint.data, 'tunnel_encryption': 'transport_mode', 'vpn_profile_ref': profile.href, 'tunnel_mode': 'gre', 'enabled': enabled, 'comment': comment } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) def enable(self): """ Enable this route based VPN :return: None """ if not self.enabled: self.update(enabled=True) def disable(self): """ Disable this route based VPN :return: None """ if self.enabled: self.update(enabled=False) def set_preshared_key(self, new_key): """ Set the preshared key for this VPN. A pre-shared key is only present when the tunnel type is 'VPN' or the encryption mode is 'transport'. :return: None """ if self.data.get('preshared_key'): self.update(preshared_key=new_key) @property def local_endpoint(self): """ The local endpoint for this RBVPN :rtype: TunnelEndpoint """ return TunnelEndpoint(**self.rbvpn_tunnel_side_a) @property def remote_endpoint(self): """ The remote endpoint for this RBVPN :rtype: TunnelEndpoint """ return TunnelEndpoint(**self.rbvpn_tunnel_side_b) @property def tunnel_mode(self): """ The tunnel mode for this RBVPN :rtype: str """ return self.data.get('tunnel_mode')
class PolicyVPN(Element): """ Create a new VPN Policy. :: >>> PolicyVPN.create(name='myvpn') PolicyVPN(name=myvpn) >>> v = PolicyVPN('myvpn') >>> print(v.vpn_profile) VPNProfile(name=VPN-A Suite) When making VPN Policy modifications, you must first call :func:`open`, make your modifications and then call :func:`save` followed by :func:`close`. :ivar VPNProfile vpn_profile: VPN Profile used by this Policy VPN """ typeof = 'vpn' vpn_profile = ElementRef('vpn_profile') @classmethod def create(cls, name, nat=False, mobile_vpn_toplogy_mode=None, vpn_profile=None): """ Create a new policy based VPN :param name: name of vpn policy :param bool nat: whether to apply NAT to the VPN (default False) :param mobile_vpn_toplogy_mode: whether to allow remote vpn :param VPNProfile vpn_profile: reference to VPN profile, or uses default :rtype: PolicyVPN """ vpn_profile = element_resolver(vpn_profile) or \ VPNProfile('VPN-A Suite').href json = { 'mobile_vpn_topology_mode': mobile_vpn_toplogy_mode, 'name': name, 'nat': nat, 'vpn_profile': vpn_profile } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreatePolicyFailed(err) @property def nat(self): """ Is NAT enabled on this vpn policy :return: NAT enabled :rtype: bool """ return self.data.get('nat') def enable_disable_nat(self): """ Enable or disable NAT on this policy. If NAT is disabled, it will be enabled and vice versa. :return: None """ if self.nat: self.data['nat'] = False else: self.data['nat'] = True @property def central_gateway_node(self): """ Central Gateway Node acts as the hub of a hub-spoke VPN. :rtype: SubElementCollection(GatewayNode) """ return sub_collection(self.get_relation('central_gateway_node'), type('CentralGatewayNode', (GatewayNode, ), {})) @property def satellite_gateway_node(self): """ Node level settings for configured satellite gateways :rtype: SubElementCollection(GatewayNode) """ return sub_collection( self.get_relation('satellite_gateway_node'), type('SatelliteGatewayNode', (GatewayNode, ), {})) @property def mobile_gateway_node(self): """ Mobile Gateway's are represented by client endpoints connecting to the policy based VPN. :rtype: SubElementCollection(GatewayNode) """ return sub_collection(self.get_relation('mobile_gateway_node'), type('MobileGatewayNode', (GatewayNode, ), {})) @property def tunnels(self): """ Return all tunnels for this VPN. A tunnel is defined as two end points within the VPN topology. Endpoints are automatically configureed based on whether they are a central gateway or satellite gateway. This provides access to enabling/disabling and setting the preshared key for the linked endpoints. List all tunnel mappings for this policy vpn:: for tunnel in policy.tunnels: tunnela = tunnel.tunnel_side_a tunnelb = tunnel.tunnel_side_b print(tunnela.gateway) print(tunnelb.gateway) :rtype: SubElementCollection(GatewayTunnel) """ return sub_collection(self.get_relation('gateway_tunnel'), GatewayTunnel) def open(self): """ Open the policy for editing. This is only a valid method for SMC version <= 6.1 :raises PolicyCommandFailed: couldn't open policy with reason :return: None """ self.make_request(PolicyCommandFailed, method='create', resource='open') def save(self): """ Save the policy after editing. This is only a valid method for SMC version <= 6.1 :raises PolicyCommandFailed: save failed with reason :return: None """ self.make_request(PolicyCommandFailed, method='create', resource='save') def close(self): """ Close the policy. This is only a valid method for SMC version <= 6.1 :raises PolicyCommandFailed: close failed with reason :return: None """ self.make_request(PolicyCommandFailed, method='create', resource='close') def validate(self): """ Return a validation string from the SMC after running validate on this VPN policy. :return: status as string :rtype: str """ return self.make_request(resource='validate').get('value') @property def mobile_vpn_topology(self): """ Is the policy VPN configured for mobile VPN gateways. Valid modes: 'Selected Gateways below', 'Only central Gateways from overall topology', 'All Gateways from overall topology', 'None' """ return self.data.get('mobile_vpn_topology_mode') # @mobile_vpn_topology.setter # def mobile_vpn_topology(self, value): # self.data.update(mobile_vpn_topology_mode=value) # @mobile_vpn_topology.setter # def mobile_vpn_topology(self, value): # self.update(mobile_vpn_topology_mode=value) # if self.mobile_vpn_topology == 'None' and value.startswith('Selected'): # self.update(mobile_vpn_topology='Selected Gateways below') # self.make_request( # PolicyCommandFailed, # method='create', # resource='mobile_gateway_node', # json={'gateway': ClientGateway('VPN Client').href, # 'node_usage': 'mobile'}) # elif self.mobile_vpn_topology != value: # self.update(mobile_vpn_topology_mode=value) def add_mobile_gateway(self, gateway): """ Add a mobile VPN gateway to this policy VPN. Example of adding or removing a mobile VPN gateway:: policy_vpn = PolicyVPN('myvpn') policy_vpn.open() policy_vpn.add_mobile_vpn_gateway(ExternalGateway('extgw3')) for mobile_gateway in policy_vpn.mobile_gateway_node: if mobile_gateway.gateway == ExternalGateway('extgw3'): mobile_gateway.delete() policy_vpn.save() policy_vpn.close() :param Engine,ExternalGateway gateway: An external gateway, engine or href for the mobile gateway :raises PolicyCommandFailed: could not add gateway """ try: gateway = gateway.vpn.internal_gateway.href # Engine except AttributeError: gateway = element_resolver(gateway) # External Gateway self.make_request(PolicyCommandFailed, method='create', resource='mobile_gateway_node', json={ 'gateway': gateway, 'node_usage': 'mobile' }) def add_central_gateway(self, gateway): """ Add SMC managed internal gateway to the Central Gateways of this VPN :param Engine,ExternalGateway gateway: An external gateway, engine or href for the central gateway :raises PolicyCommandFailed: could not add gateway :return: None """ try: gateway = gateway.vpn.internal_gateway.href except AttributeError: gateway = element_resolver(gateway) self.make_request(PolicyCommandFailed, method='create', resource='central_gateway_node', json={ 'gateway': gateway, 'node_usage': 'central' }) def add_satellite_gateway(self, gateway): """ Add gateway node as a satellite gateway for this VPN. You must first have the gateway object created. This is typically used when you either want a hub-and-spoke topology or the test_external gateway is a non-SMC managed device. :param Engine,ExternalGateway gateway: An external gateway, engine or href for the central gateway :raises PolicyCommandFailed: could not add gateway :return: None """ try: gateway = gateway.vpn.internal_gateway.href except AttributeError: gateway = element_resolver(gateway) self.make_request(PolicyCommandFailed, method='create', resource='satellite_gateway_node', json={ 'gateway': gateway, 'node_usage': 'satellite' }) @staticmethod def add_internal_gateway_to_vpn(internal_gateway_href, vpn_policy, vpn_role='central'): """ Add an internal gateway (managed engine node) to a VPN policy based on the internal gateway href. :param str internal_gateway_href: href for engine internal gw :param str vpn_policy: name of vpn policy :param str vpn_role: central|satellite :return: True for success :rtype: bool """ try: vpn = PolicyVPN(vpn_policy) vpn.open() if vpn_role == 'central': vpn.add_central_gateway(internal_gateway_href) else: vpn.add_satellite_gateway(internal_gateway_href) vpn.save() vpn.close() except ElementNotFound: return False return True
class Situation(Element): """ Situation defines a common interface for inspection and correlated situations. """ situation_context = ElementRef('situation_context_ref') @property def severity(self): """ The severity of this inspection situation, critical, high, low, information :rtype: int """ return SEVERITY.get(self.data.get('severity')) @property def description(self): """ The description for this situation :rtype: str """ return self.data.get('description', '') @property def attacker(self): """ How the Attacker is determined when the Situation matches. This information is used for blacklisting and in log entries and may be None :rtype: str or None """ return self.data.get('attacker') @property def target(self): """ How the Target is determined when the Situation matches. This information is used for blacklisting and in log entries and may be None :rtype: str or None """ return self.data.get('target') @property def parameter_values(self): """ Parameter values for this inspection situation. This correlate to the the situation_context. :rtype: list(SituationParameterValue) """ for param in self.data.get('parameter_values', []): cache = ElementCache(data=self.make_request(href=param)) name = '{}'.format(cache.type.title()).replace('_', '') yield type(name, (SituationParameterValue, ), {'data': cache})(name=cache.name, type=cache.type, href=param)
class ExternalGateway(Element): """ External Gateway defines an VPN Gateway for a non-SMC managed device. This will specify details such as the endpoint IP, and VPN site protected networks. Example of manually provisioning each step:: Network.create(name='mynetwork', ipv4_network='172.18.1.0/24') gw = ExternalGateway.create(name='mygw') gw.external_endpoint.create(name='myendpoint', address='10.10.10.10') gw.vpn_site.create(name='mysite', site_element=[Network('mynetwork')]) :ivar GatewayProfile gateway_profile: A gateway profile will define the capabilities (i.e. crypto) allowed for this VPN. """ typeof = "external_gateway" gateway_profile = ElementRef("gateway_profile") @classmethod def create(cls, name, trust_all_cas=True, gateway_profile=None, **kwargs): """ Create new External Gateway :param str name: name of test_external gateway :param bool trust_all_cas: whether to trust all internal CA's (default: True) :param GatewayProfile,href gateway_profile: optional gateway profile, otherwise default :return: instance with meta :rtype: ExternalGateway """ json = { "name": name, "trust_all_cas": trust_all_cas, "gateway_profile": element_resolver(gateway_profile) if gateway_profile else element_default(GatewayProfile, "Default"), } json.update(kwargs) return ElementCreator(cls, json) @classmethod def update_or_create(cls, name, external_endpoint=None, vpn_site=None, trust_all_cas=True, with_status=False): """ Update or create an ExternalGateway. The ``external_endpoint`` and ``vpn_site`` parameters are expected to be a list of dicts with key/value pairs to satisfy the respective elements create constructor. VPN Sites will represent the final state of the VPN site list. ExternalEndpoint that are pre-existing will not be deleted if not provided in the ``external_endpoint`` parameter, however existing elements will be updated as specified. :param str name: name of external gateway :param list(dict) external_endpoint: list of dict items with key/value to satisfy ExternalEndpoint.create constructor :param list(dict) vpn_site: list of dict items with key/value to satisfy VPNSite.create constructor :param bool with_status: If set to True, returns a 3-tuple of (ExternalGateway, modified, created), where modified and created is the boolean status for operations performed. :raises ValueError: missing required argument/s for constructor argument :rtype: ExternalGateway """ if external_endpoint: for endpoint in external_endpoint: if "name" not in endpoint: raise ValueError("External endpoints are configured " "but missing the name parameter.") if vpn_site: for site in vpn_site: if "name" not in site: raise ValueError("VPN sites are configured but missing " "the name parameter.") # Make sure VPN sites are resolvable before continuing sites = [ element_resolver(element, do_raise=True) for element in site.get("site_element", []) ] site.update(site_element=sites) updated = False created = False try: extgw = ExternalGateway.get(name) except ElementNotFound: extgw = ExternalGateway.create(name, trust_all_cas) created = True if external_endpoint: for endpoint in external_endpoint: _, modified, was_created = ExternalEndpoint.update_or_create( extgw, with_status=True, **endpoint) if was_created or modified: updated = True if vpn_site: for site in vpn_site: _, modified, was_created = VPNSite.update_or_create( extgw, name=site["name"], site_element=site.get("site_element"), with_status=True, ) if was_created or modified: updated = True if with_status: return extgw, updated, created return extgw @property def vpn_site(self): """ A VPN site defines a collection of IP's or networks that identify address space that is defined on the other end of the VPN tunnel. :rtype: CreateCollection(VPNSite) """ return create_collection(self.get_relation("vpn_site"), VPNSite) @property def external_endpoint(self): """ An External Endpoint is the IP based definition for the destination VPN peers. There may be multiple per External Gateway. Add a new endpoint to an existing test_external gateway:: >>> list(ExternalGateway.objects.all()) [ExternalGateway(name=cisco-remote-side), ExternalGateway(name=remoteside)] >>> gateway.external_endpoint.create('someendpoint', '12.12.12.12') 'http://1.1.1.1:8082/6.1/elements/external_gateway/22961/external_endpoint/27467' :rtype: CreateCollection(ExternalEndpoint) """ return create_collection(self.get_relation("external_endpoint"), ExternalEndpoint) @property def trust_all_cas(self): """ Gateway setting identifying whether all CA's specified in the profile are supported or only specific ones. :rtype: bool """ return self.data.get("trust_all_cas")
class StaticNetlink(Element): """ A Static Netlink is applied to an interface to provide an alternate route to a destination. It is typically used when you have fixed IP interfaces versus using DHCP (use a Dynamic NetLink). :ivar Router,Engine gateway: gateway for this netlink. Should be the 'next hop' element associated with the netlink :ivar list(Network) network: list of networks associated with this netlink :ivar int input_speed: input speed in Kbps, used for ratio-based load-balancing :ivar int output_speed: output speed in Kbps, used for ratio-based load-balancing :ivar list probe_address: list of IP addresses to use as probing addresses to validate connectivity :ivar int standby_mode_period: Specifies the probe period when standby mode is used (in seconds) :ivar int standby_mode_timeout: probe timeout in seconds :ivar int active_mode_period: Specifies the probe period when active mode is used (in seconds) :ivar int active_mode_timeout: probe timeout in seconds """ typeof = 'netlink' gateway = ElementRef('gateway_ref') network = ElementList(('6.5', 'ref'), ('6.6', 'network_ref')) @classmethod def create(cls, name, gateway, network, input_speed=None, output_speed=None, domain_server_address=None, provider_name=None, probe_address=None, standby_mode_period=3600, standby_mode_timeout=30, active_mode_period=5, active_mode_timeout=1, comment=None): """ Create a new StaticNetlink to be used as a traffic handler. :param str name: name of netlink Element :param gateway_ref: gateway to map this netlink to. This can be an element or str href. :type gateway_ref: Router,Engine :param list ref: network/s associated with this netlink. :type ref: list(str,Element) :param int input_speed: input speed in Kbps, used for ratio-based load-balancing :param int output_speed: output speed in Kbps, used for ratio-based load-balancing :param list domain_server_address: dns addresses for netlink. Engine DNS can override this field :type dns_addresses: list(str,Element) :param str provider_name: optional name to identify provider for this netlink :param list probe_address: list of IP addresses to use as probing addresses to validate connectivity :type probe_ip_address: list(str) :param int standby_mode_period: Specifies the probe period when standby mode is used (in seconds) :param int standby_mode_timeout: probe timeout in seconds :param int active_mode_period: Specifies the probe period when active mode is used (in seconds) :param int active_mode_timeout: probe timeout in seconds :raises ElementNotFound: if using type Element parameters that are not found. :raises CreateElementFailed: failure to create netlink with reason :rtype: StaticNetlink .. note:: To monitor the status of the network links, you must define at least one probe IP address. """ json = {'name': name, 'gateway_ref': element_resolver(gateway), 'input_speed': input_speed, 'output_speed': output_speed, 'probe_address': probe_address, 'nsp_name': provider_name, 'comment': comment, 'standby_mode_period': standby_mode_period, 'standby_mode_timeout': standby_mode_timeout, 'active_mode_period': active_mode_period, 'active_mode_timeout': active_mode_timeout} if is_version_less_than_or_equal('6.5'): json.update(ref=element_resolver(network)) else: json.update(network_ref=element_resolver(network)) if domain_server_address: r = RankedDNSAddress([]) r.add(domain_server_address) json.update(domain_server_address=r.entries) return ElementCreator(cls, json) @classmethod def update_or_create(cls, with_status=False, **kwargs): """ Update or create static netlink. DNS entry differences are not resolved, instead any entries provided will be the final state for this netlink. If the intent is to add/remove DNS entries you can use the :meth:`~domain_server_address` method to add or remove. :raises CreateElementFailed: failed creating element :return: element instance by type or 3-tuple if with_status set """ dns_address = kwargs.pop('domain_server_address', []) element, updated, created = super(StaticNetlink, cls).update_or_create( with_status=True, defer_update=True, **kwargs) if not created: if dns_address: new_entries = RankedDNSAddress([]) new_entries.add(dns_address) element.data.update(domain_server_address=new_entries.entries) updated = True if updated: element.update() if with_status: return element, updated, created return element @property def domain_server_address(self): """ Configured DNS servers for this netlink :return: list of DNS servers; if elements are specifed, they will be returned as type Element :rtype: RankedDNSAddress """ return RankedDNSAddress(self.data.get('domain_server_address')) @property def networks(self): return self.network
class ProxyServer(ContactAddressMixin, Element): """ A ProxyServer element is used in the firewall policy to provide the ability to send HTTP, HTTPS, FTP or SMTP traffic to a next hop proxy. There are two types of next hop proxies, 'Generic' and 'Forcepoint AP Web". Example of creating a configuration for a Forcepoint AP-Web proxy redirect:: server = ProxyServer.update_or_create(name='myproxy', address='1.1.1.1', proxy_service='forcepoint_ap-web_cloud', fp_proxy_key='mypassword', fp_proxy_key_id=3, fp_proxy_user_id=1234, inspected_service=[{'service_type': 'HTTP', 'port': '80'}]) Create a Generic Proxy forward service:: server = ProxyServer.update_or_create(name='generic', address='1.1.1.1,1.1.1.2', inspected_service=[{'service_type': 'HTTP', 'port': 80}, {'service_type': 'HTTPS', 'port': 8080}]) Inspected services take a list of keys `service_type` and `port`. Service type key values are 'HTTP', 'HTTPS', 'FTP' and 'SMTP'. Port value is the port for the respective protocol. :param str http_proxy: type of proxy configuration, either generic or forcepoint_ap-web_cloud """ typeof = 'proxy_server' location = ElementRef('location_ref') @classmethod def create(cls, name, address, inspected_service, secondary=None, balancing_mode='ha', proxy_service='generic', location=None, comment=None, add_x_forwarded_for=False, trust_host_header=False, **kw): """ Create a Proxy Server element :param str name: name of proxy server element :param str address: address of element. Can be a single FQDN or comma separated list of IP addresses :param list secondary: list of secondary IP addresses :param str balancing_mode: how to balance traffic, valid options are ha (first available server), src, dst, srcdst (default: ha) :param str proxy_service: which proxy service to use for next hop, options are generic or forcepoint_ap-web_cloud :param str,Element location: location for this proxy server :param bool add_x_forwarded_for: add X-Forwarded-For header when using the Generic Proxy forwarding method (default: False) :param bool trust_host_header: trust the host header when using the Generic Proxy forwarding method (default: False) :param dict inspected_service: inspection services dict. Valid keys are service_type and port. Service type valid values are HTTP, HTTPS, FTP or SMTP and are case sensitive :param str comment: optional comment :param kw: keyword arguments are used to collect settings when the proxy_service value is forcepoint_ap-web_cloud. Valid keys are `fp_proxy_key`, `fp_proxy_key_id`, `fp_proxy_user_id`. The fp_proxy_key is the password value. All other values are of type int """ json = { 'name': name, 'comment': comment, 'secondary': secondary or [], 'http_proxy': proxy_service, 'balancing_mode': balancing_mode, 'inspected_service': inspected_service, 'trust_host_header': trust_host_header, 'add_x_forwarded_for': add_x_forwarded_for, 'location_ref': element_resolver(location) } addresses = address.split(',') json.update(address=addresses.pop(0)) json.update(ip_address=addresses if 'ip_address' not in kw else kw['ip_address']) if proxy_service == 'forcepoint_ap-web_cloud': for key in ('fp_proxy_key', 'fp_proxy_key_id', 'fp_proxy_user_id'): if key not in kw: raise CreateElementFailed( 'Missing required fp key when adding a ' 'proxy server to forward to forcepoint. Missing key: %s' % key) json[key] = kw.get(key) return ElementCreator(cls, json) @property def proxy_service(self): """ The proxy service for this proxy server configuration :rtype: str """ return self.data.get('http_proxy') @classmethod def update_or_create(cls, with_status=False, **kwargs): element, updated, created = super(ProxyServer, cls).update_or_create( defer_update=True, **kwargs) if not created: if 'proxy_service' in element.data and element.http_proxy != element.data[ 'proxy_service']: element.data['http_proxy'] = element.data.pop('proxy_service') updated = True if 'address' in kwargs: if ',' in element.data.get('address'): addresses = element.data.pop('address').split(',') element.data['address'] = addresses.pop(0) # Remainder is ip_address attribute if set(addresses) ^ set(element.data.get('ip_address', [])): element.data['ip_address'] = addresses updated = True inspected_service = kwargs.pop('inspected_service', None) if inspected_service is not None: service_keys = set( [k.get('service_type') for k in inspected_service]) element_keys = set([ k.get('service_type') for k in element.data.get('inspected_service', []) ]) if service_keys ^ element_keys: element.data['inspected_service'] = inspected_service updated = True if updated: element.update() if with_status: return element, updated, created return element @property def inspected_services(self): """ The specified services for inspection. An inspected service is a reference to a protocol that can be forwarded for inspection, such as HTTP, HTTPS, FTP and SMTP. :rtype: list(InspectedService) """ return [ InspectedService(**service) for service in self.make_request(resource='inspected_services') ]
class RouteVPN(Element): """ Route based VPN in NGFW. :ivar VPNProfile vpn_profile: VPNProfile reference for this RouteVPN :ivar TunnelMonitoringGroup monitoring_group: tunnel monitoring group reference """ typeof = "rbvpn_tunnel" vpn_profile = ElementRef("vpn_profile_ref") monitoring_group = ElementRef(("6.5", "monitoring_group_ref"), ("6.6", "tunnel_group_ref")) @classmethod def create_ipsec_tunnel(cls, *args, **kwargs): """ The VPN tunnel type negotiates IPsec tunnels in the same way as policy-based VPNs, but traffic is selected to be sent into the tunnel based on routing. :param str name: name of VPN :param TunnelEndpoint local_endpoint: the local side endpoint for this VPN. :param TunnelEndpoint remote_endpoint: the remote side endpoint for this VPN. :param str preshared_key: required if remote endpoint is an ExternalGateway :param TunnelMonitoringGroup monitoring_group: the group to place this VPN in for monitoring. Default: 'Uncategorized'. :param VPNProfile vpn_profile: VPN profile for this VPN. (default: VPN-A Suite) :param int mtu: Set MTU for this VPN tunnel (default: 0) :param boolean pmtu_discovery: enable pmtu discovery (default: True) :param int ttl: ttl for connections on the VPN (default: 0) :param bool enabled: enable the RBVPN or leave it disabled :param str comment: optional comment :raises CreateVPNFailed: failed to create the VPN with reason :rtype: RouteVPN """ versioned_method = get_best_version( ("6.5", cls._create_ipsec_tunnel_65), ("6.6", cls._create_ipsec_tunnel_66)) return versioned_method(*args, **kwargs) @classmethod def _create_ipsec_tunnel_65( cls, name, local_endpoint, remote_endpoint, preshared_key=None, monitoring_group=None, vpn_profile=None, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None, ): group = monitoring_group or RouteVPNTunnelMonitoringGroup( "Uncategorized") profile = vpn_profile or VPNProfile("VPN-A Suite") json = { "name": name, "mtu": mtu, "ttl": ttl, "enabled": enabled, "monitoring_group_ref": group.href, "pmtu_discovery": pmtu_discovery, "preshared_key": preshared_key, "rbvpn_tunnel_side_a": local_endpoint.data, "rbvpn_tunnel_side_b": remote_endpoint.data, "tunnel_mode": "vpn", "comment": comment, "vpn_profile_ref": profile.href, } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) @classmethod def _create_ipsec_tunnel_66( cls, name, local_endpoint, remote_endpoint, preshared_key=None, monitoring_group=None, vpn_profile=None, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None, ): group = monitoring_group or TunnelMonitoringGroup("Uncategorized") profile = vpn_profile or VPNProfile("VPN-A Suite") json = { "name": name, "mtu": mtu, "ttl": ttl, "enabled": enabled, "tunnel_group_ref": group.href, "pmtu_discovery": pmtu_discovery, "preshared_key": preshared_key, "rbvpn_tunnel_side_a": local_endpoint.data, "rbvpn_tunnel_side_b": remote_endpoint.data, "tunnel_mode": "vpn", "comment": comment, "vpn_profile_ref": profile.href, } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) @classmethod def create_gre_tunnel_mode( cls, name, local_endpoint, remote_endpoint, policy_vpn, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None, ): """ Create a GRE based tunnel mode route VPN. Tunnel mode GRE wraps the GRE tunnel in an IPSEC tunnel to provide encrypted end-to-end security. Therefore a policy based VPN is required to 'wrap' the GRE into IPSEC. :param str name: name of VPN :param TunnelEndpoint local_endpoint: the local side endpoint for this VPN. :param TunnelEndpoint remote_endpoint: the remote side endpoint for this VPN. :param PolicyVPN policy_vpn: reference to a policy VPN :param TunnelMonitoringGroup monitoring_group: the group to place this VPN in for monitoring. (default: 'Uncategorized') :param int mtu: Set MTU for this VPN tunnel (default: 0) :param boolean pmtu_discovery: enable pmtu discovery (default: True) :param int ttl: ttl for connections on the VPN (default: 0) :param str comment: optional comment :raises CreateVPNFailed: failed to create the VPN with reason :rtype: RouteVPN """ json = { "name": name, "ttl": ttl, "mtu": mtu, "pmtu_discovery": pmtu_discovery, "tunnel_encryption": "tunnel_mode", "tunnel_mode": "gre", "enabled": enabled, "comment": comment, "rbvpn_tunnel_side_a": local_endpoint.data, "rbvpn_tunnel_side_b": remote_endpoint.data, } if policy_vpn is None: json["tunnel_encryption"] = "no_encryption" else: json["tunnel_mode_vpn_ref"] = policy_vpn.href try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) @classmethod def create_gre_tunnel_no_encryption( cls, name, local_endpoint, remote_endpoint, mtu=0, pmtu_discovery=True, ttl=0, enabled=True, comment=None, ): """ Create a GRE Tunnel with no encryption. See `create_gre_tunnel_mode` for constructor descriptions. """ return cls.create_gre_tunnel_mode( name, local_endpoint, remote_endpoint, policy_vpn=None, mtu=mtu, pmtu_discovery=pmtu_discovery, ttl=ttl, enabled=enabled, comment=comment, ) @classmethod def create_gre_transport_mode(cls, *args, **kwargs): """ Create a transport based route VPN. This VPN type uses IPSEC for protecting the payload, therefore a VPN Profile is specified. :param str name: name of VPN :param TunnelEndpoint local_endpoint: the local side endpoint for this VPN. :param TunnelEndpoint remote_endpoint: the remote side endpoint for this VPN. :param str preshared_key: preshared key for RBVPN :param TunnelMonitoringGroup monitoring_group: the group to place this VPN in for monitoring. (default: 'Uncategorized') :param VPNProfile vpn_profile: VPN profile for this VPN. (default: VPN-A Suite) :param int mtu: Set MTU for this VPN tunnel (default: 0) :param boolean pmtu_discovery: enable pmtu discovery (default: True) :param int ttl: ttl for connections on the VPN (default: 0) :param str comment: optional comment :raises CreateVPNFailed: failed to create the VPN with reason :rtype: RouteVPN """ versioned_method = get_best_version( ("6.5", cls._create_gre_transport_mode_65), ("6.6", cls._create_gre_transport_mode_66)) return versioned_method(*args, **kwargs) @classmethod def _create_gre_transport_mode_65( cls, name, local_endpoint, remote_endpoint, preshared_key, monitoring_group=None, vpn_profile=None, mtu=0, ttl=0, pmtu_discovery=True, enabled=True, comment=None, ): group = monitoring_group or RouteVPNTunnelMonitoringGroup( "Uncategorized") profile = vpn_profile or VPNProfile("VPN-A Suite") json = { "name": name, "mtu": mtu, "ttl": ttl, "preshared_key": preshared_key, "pmtu_discovery": pmtu_discovery, "monitoring_group_ref": group.href, "rbvpn_tunnel_side_a": local_endpoint.data, "rbvpn_tunnel_side_b": remote_endpoint.data, "tunnel_encryption": "transport_mode", "vpn_profile_ref": profile.href, "tunnel_mode": "gre", "enabled": enabled, "comment": comment, } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) @classmethod def _create_gre_transport_mode_66( cls, name, local_endpoint, remote_endpoint, preshared_key, monitoring_group=None, vpn_profile=None, mtu=0, ttl=0, pmtu_discovery=True, enabled=True, comment=None, ): group = monitoring_group or TunnelMonitoringGroup("Uncategorized") profile = vpn_profile or VPNProfile("VPN-A Suite") json = { "name": name, "mtu": mtu, "ttl": ttl, "preshared_key": preshared_key, "pmtu_discovery": pmtu_discovery, "tunnel_group_ref": group.href, "rbvpn_tunnel_side_a": local_endpoint.data, "rbvpn_tunnel_side_b": remote_endpoint.data, "tunnel_encryption": "transport_mode", "vpn_profile_ref": profile.href, "tunnel_mode": "gre", "enabled": enabled, "comment": comment, } try: return ElementCreator(cls, json) except CreateElementFailed as err: raise CreateVPNFailed(err) def enable(self): """ Enable this route based VPN :return: None """ if not self.enabled: self.update(enabled=True) def disable(self): """ Disable this route based VPN :return: None """ if self.enabled: self.update(enabled=False) def set_preshared_key(self, new_key): """ Set the preshared key for this VPN. A pre-shared key is only present when the tunnel type is 'VPN' or the encryption mode is 'transport'. :return: None """ if self.data.get("preshared_key"): self.update(preshared_key=new_key) @property def local_endpoint(self): """ The local endpoint for this RBVPN :rtype: TunnelEndpoint """ return TunnelEndpoint(**self.rbvpn_tunnel_side_a) @property def remote_endpoint(self): """ The remote endpoint for this RBVPN :rtype: TunnelEndpoint """ return TunnelEndpoint(**self.rbvpn_tunnel_side_b) @property def tunnel_mode(self): """ The tunnel mode for this RBVPN :rtype: str """ return self.data.get("tunnel_mode") @property def tunnels(self): """ Return all tunnels for this RBVPN in case of Tunnel Type 'VPN'. This provides access to enabling/disabling for the linked endpoints. List all tunnel mappings for this route vpn:: for tunnel in rb_vpn.tunnels: print(tunnel.enabled) :rtype: SubElementCollection(EndpointTunnel) """ return sub_collection(self.get_relation("gateway_endpoint_tunnel"), EndpointTunnel)