def ElementCreator(cls): """ Helper method for create classmethods. Returns the href if creation is successful """ result = SMCRequest(href=search.element_entry_point(cls.typeof), json=cls.json).create() if result.msg: raise CreateElementFailed(result.msg) return result.href
def update_or_create(cls, name, 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 """ updated, created = False, False try: ad = ActiveDirectoryServer.get(name) except ElementNotFound: try: ad = ActiveDirectoryServer.create(name, **kwargs) created = True except TypeError: raise CreateElementFailed( '%s: %r not found and missing ' 'constructor arguments to properly create.' % (cls.__name__, name)) if not created: if 'domain_controller' in kwargs: #TODO: Workaround for SMC bug ad.data.pop('domain_controller', None) for dc in kwargs.pop('domain_controller', []): if dc not in ad.domain_controller: ad.data.setdefault('domain_controller', []).append(dc.data) updated = True for method in kwargs.pop('supported_method', []): if method.href not in ad.data.get('supported_method', []): ad.data.setdefault('supported_method', []).append( element_resolver(method.href)) updated = True #TODO: update with brand new list leaves original attributes for strlist in ('group_object_class', 'user_object_class'): value = kwargs.pop(strlist, []) if value and set(value) ^ set(getattr(ad, strlist, [])): ad.data[strlist] = value updated = True for name, value in kwargs.items(): if getattr(ad, name) != value: ad.data[name] = value updated = True if updated: ad.update() if with_status: return ad, updated, created return ad
def create( cls, name, situation_context, attacker=None, target=None, severity="information", situation_type=None, description=None, comment=None, ): """ Create an inspection situation. :param str name: name of the situation :param InspectionSituationContext situation_context: The situation context type used to define this situation. Identifies the proper parameter that identifies how the situation is defined (i.e. regex, etc). :param str attacker: Attacker information, used to identify last packet the triggers attack and is only used for blacklisting. Values can be packet_source, packet_destination, connection_source, or connection_destination :param str target: Target information, used to identify the last packet that triggers the attack and is only used for blacklisting. Values can be packet_source, packet_destination, connection_source, or connection_destination :param str severity: severity for this situation. Valid values are critical, high, low, information :param str description: optional description :param str comment: optional comment """ try: json = { "name": name, "comment": comment, "description": description, "situation_context_ref": situation_context.href, "attacker": attacker, "victim": target, "severity": _severity_by_name(severity), } element = ElementCreator(cls, json) tag = situation_type or SituationTag("User Defined Situations") tag.add_element(element) return element except ElementNotFound as e: raise CreateElementFailed( "{}. Inspection Situation Contexts require SMC " "version 6.5 and above.".format(str(e)) )
def update_or_create(cls, with_status=False, **kwargs): """ Update or create static netlink. :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 """ updated, created = False, False name = kwargs.pop('name', None) try: element = cls.get(name) gateway = kwargs.pop('gateway', None) if gateway is not None and gateway != element.gateway: element.gateway = gateway updated = True for net in kwargs.pop('network', []): if net not in element.network: element.data['ref'].append(element_resolver(net)) updated = True current_dns = len(element.domain_server_address) element.domain_server_address.append( kwargs.pop('domain_server_address', [])) if len(element.domain_server_address) != current_dns: updated = True for name, value in kwargs.items(): if getattr(element, name, None) != value: #setattr(element, name, value) element.data[name] = value updated = True if updated: element.update() except ElementNotFound: try: element = cls.create(name=name, **kwargs) created = True except TypeError: raise CreateElementFailed( '%s: %r not found and missing ' 'constructor arguments to properly create.' % (cls.__name__, name)) if with_status: return element, updated, created return element
def ElementCreator(cls, json): """ Helper method for create classmethods. Returns the href if creation is successful. This is a lazy load that will provide only the meta for the element. Additional attribute access will load the full data. :return: instance of type Element with meta :rtype: Element """ result = SMCRequest(href=cls.href, json=json).create() if result.msg: raise CreateElementFailed(result.msg) return cls(json.get('name'), type=cls.typeof, href=result.href)
def create(self, name, site_element): """ Create a VPN site for an internal or test_external gateway :param str name: name of site :param list site_element: list of protected networks/hosts :return: str href: href of new element :raises: :py:class: `smc.api.exceptions.CreateElementFailed` """ json = {'name': name, 'site_element': site_element} result = prepared_request(href=self.href, json=json).create() if result.msg: raise CreateElementFailed(result.msg) else: return result.href
def create(cls, name, trust_all_cas=True): """ Create new External Gateway :param str name: name of test_external gateway :param boolean trust_all_cas: whether to trust all internal CA's (default: True) :return: :py:class:`smc.vpn.elements.ExternalGateway` """ cls.json = {'name': name, 'trust_all_cas': trust_all_cas} try: ElementCreator(cls) return ExternalGateway(name) except CreateElementFailed as err: raise CreateElementFailed('Failed creating test_external gateway, ' 'reason: {}'.format(err))
def update_or_create(cls, name, with_status=False, **kwargs): """ Update or create LDAP User Domain :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 :raises ElementNotFound: referenced elements are not found :return: element instance by type or 3-tuple if with_status set """ updated, created = False, False try: element = ExternalLdapUserDomain.get(name) except ElementNotFound: try: element = ExternalLdapUserDomain.create(name, **kwargs) created = True except TypeError: raise CreateElementFailed( '%s: %r not found and missing ' 'constructor arguments to properly create.' % (cls.__name__, name)) if not created: for ldap_server in kwargs.pop('ldap_server', []): if ldap_server.href not in element.data.get('ldap_server', []): element.data.setdefault('ldap_server', []).append(ldap_server.href) updated = True if kwargs.get('auth_method') and kwargs['auth_method'].href != \ element.data.get('auth_method'): element.data['auth_method'] = kwargs.pop('auth_method').href updated = True if kwargs.get('comment') and kwargs['comment'] != element.comment: element.data['comment'] = kwargs['comment'] updated = True if updated: element.update() if with_status: return element, updated, created return element
def create_regular_expression(self, regexp): """ Create a regular expression for this inspection situation context. The inspection situation must be using an inspection context that supports regex. :param str regexp: regular expression string :raises CreateElementFailed: failed to modify the situation """ for parameter in self.situation_context.situation_parameters: if parameter.type == 'regexp': return self.add_parameter_value( 'reg_exp_situation_parameter_values', **{ 'parameter_ref': parameter.href, 'reg_exp': regexp }) # Treat as raw string raise CreateElementFailed('The situation does not support a regular ' 'expression as a context value.')
def create(self, name, address, enabled=True, balancing_mode='active', ipsec_vpn=True, nat_t=False, dynamic=False): """ Create an test_external endpoint. Define common settings for that specify the address, enabled, nat_t, name, etc. :param str name: name of test_external endpoint :param str address: address of remote host :param boolean enabled: True|False (default: True) :param str balancing_mode: active :param boolean ipsec_vpn: True|False (default: True) :param boolean nat_t: True|False (default: False) :param boolean dynamic: is a dynamic VPN (default: False) :return: str href: href of new element :raises: :py:class: `smc.api.exceptions.CreateElementFailed` """ json = { 'name': name, 'address': address, 'balancing_mode': balancing_mode, 'dynamic': dynamic, 'enabled': enabled, 'nat_t': nat_t, 'ipsec_vpn': ipsec_vpn } result = prepared_request(href=self.href, json=json).create() if result.msg: raise CreateElementFailed(result.msg) else: return result.href
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)
def get_or_create(cls, filter_key=None, with_status=False, **kwargs): """ Convenience method to retrieve an Element or create if it does not exist. If an element does not have a `create` classmethod, then it is considered read-only and the request will be redirected to :meth:`~get`. Any keyword arguments passed except the optional filter_key will be used in a create() call. If filter_key is provided, this should define an attribute and value to use for an exact match on the element. Valid attributes are ones required on the elements ``create`` method or can be viewed by the elements class docs. If no filter_key is provided, the name field will be used to find the element. :: >>> Network.get_or_create( filter_key={'ipv4_network': '123.123.123.0/24'}, name='mynetwork', ipv4_network='123.123.123.0/24') Network(name=mynetwork) The kwargs should be used to satisfy the elements ``create`` classmethod parameters to create in the event it cannot be found. :param dict filter_key: filter key represents the data attribute and value to use to find the element. If none is provided, the name field will be used. :param kwargs: keyword arguments mapping to the elements ``create`` method. :param bool with_status: if set to True, a tuple is returned with (Element, created), where the second tuple item indicates if the element has been created or not. :raises CreateElementFailed: could not create element with reason :raises ElementNotFound: if read-only element does not exist :return: element instance by type :rtype: Element """ was_created = False if not hasattr(cls, 'create'): return cls.get(kwargs.get('name')) elif 'name' not in kwargs: raise ElementNotFound( 'Name field is a required parameter ' 'for all create type operations on an element') if filter_key: elements = cls.objects.filter(**filter_key) element = elements.first() else: try: element = cls.get(kwargs.get('name')) except ElementNotFound: element = None if not element: try: element = cls.create(**kwargs) was_created = True except TypeError: raise CreateElementFailed( '%s: %r not found and missing ' 'constructor arguments to properly create.' % (cls.__name__, kwargs['name'])) if with_status: return element, was_created return element
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)