Source code for smc.elements.profiles

"""
Profiles are templates used in other parts of the system to provide default 
functionality for specific feature sets. For example, to enable DNS Relay on
an engine you must specify a DNSRelayProfile to use which defines the common
settings (or sub-settings) for that feature.

A DNS Relay Profile allows multiple DNS related mappings that can be configured.
Example usage::

    >>> from smc.elements.profiles import DNSRelayProfile
    >>> profile = DNSRelayProfile('mynewprofile')

.. note:: If the DNSRelayProfile does not exist, it will automatically be
    created when a DNS relay rule is added to the DNSRelayProfile instance.
    
Add a fixed domain answer rule::

    >>> profile.fixed_domain_answer.add([('microsoft3.com', 'foo.com'), ('microsoft4.com',)])
    >>> profile.fixed_domain_answer.all()
    [{u'domain_name': u'microsoft3.com', u'translated_domain_name': u'foo.com'}, {u'domain_name': u'microsoft4.com'}]
    
Translate hostnames (not fqdn) to a specific IP address::

    >>> profile.hostname_mapping.add([('hostname1,hostname2', '1.1.1.12')])
    >>> profile.hostname_mapping.all()
    [{u'hostnames': u'hostname1,hostname2', u'ipaddress': u'1.1.1.12'}]

Translate an IP address to another::

    >>> profile.dns_answer_translation.add([('12.12.12.12', '172.18.1.20')])
    >>> profile.dns_answer_translation.all()
    [{u'translated_ipaddress': u'172.18.1.20', u'original_ipaddress': u'12.12.12.12'}]

Specify a DNS server to handle specific domains::

    >>> profile.domain_specific_dns_server.add([('myfoo.com', '172.18.1.20')])
    >>> profile.domain_specific_dns_server.all()
    [{u'dns_server_addresses': u'172.18.1.20', u'domain_name': u'myfoo.com'}]

"""
from smc.base.model import Element, ElementCreator
from smc.api.exceptions import ElementNotFound
from smc.base.util import element_resolver


[docs]class DNSRule(object): """ DNSRule is the parent class for all DNS relay rules. """ __slots__ = ('profile') def __init__(self, profile): self.profile = profile def add(self, instance, answers): key, left, right = instance._attr json = [dict(zip([left, right], d)) for d in answers] try: self.profile.data[key].extend(json) self.profile.update() except ElementNotFound: j = {'name': self.profile.name, key: json} return ElementCreator(self.profile.__class__, j)
[docs] def all(self): """ Return all entries :rtype: list(dict) """ attribute = self._attr[0] return self.profile.data.get(attribute, [])
[docs]class FixedDomainAnswer(DNSRule): """ Direct requests for specific domains to IPv4 addresses, IPv6 addresses, fully qualified domain names (FQDNs), or empty DNS replies """ _attr = ('fixed_domain_answer', 'domain_name', 'translated_domain_name')
[docs] def add(self, answers): """ Add a fixed domain answer. This should be a list of two-tuples, the first entry is the domain name, and the second is the translated domain value:: profile = DNSRelayProfile('dnsrules') profile.fixed_domain_answer.add([ ('microsoft.com', 'foo.com'), ('microsoft2.com',)]) :param answers: (domain_name, translated_domain_name) :type answers: tuple[str, str] :raises UpdateElementFailed: failure to add to SMC :return: None .. note:: translated_domain_name can be none, which will cause the NGFW to return NXDomain for the specified domain. """ super(FixedDomainAnswer, self).add(self, answers)
[docs]class HostnameMapping(DNSRule): """ Statically map host names, aliases for host names, and unqualified names (a host name without the domain suffix) to IPv4 or IPv6 addresses """ _attr = ('hostname_mapping', 'hostnames', 'ipaddress')
[docs] def add(self, answers): """ Map specific hostname to specified IP address. Provide a list of two-tuples. The first entry is the hostname/s to translate (you can provide multiple comma separated values). The second entry should be the IP address to map the hostnames to:: profile = DNSRelayProfile('dnsrules') profile.hostname_mapping.add([('hostname1,hostname2', '1.1.1.1')]) :param answers: (hostnames, ipaddress), hostnames can be a comma separated list. :type answers: tuple[str, str] :raises UpdateElementFailed: failure to add to SMC :return: None """ super(HostnameMapping, self).add(self, answers)
[docs]class DomainSpecificDNSServer(DNSRule): """ Forward DNS requests to different DNS servers based on the requested domain. """ _attr = ('domain_specific_dns_server', 'domain_name', 'dns_server_addresses')
[docs] def add(self, answers): """ Relay specific domains to a specified DNS server. Provide a list of two-tuple with first entry the domain name to relay for. The second entry is the DNS server that should handle the query:: profile = DNSRelayProfile('dnsrules') profile.domain_specific_dns_server.add([('myfoo.com', '172.18.1.20')]) :param answers: (domain_name, dns_server_addresses), dns server addresses can be a comma separated string :type answers: tuple[str, str] :raises UpdateElementFailed: failure to add to SMC :return: None """ super(DomainSpecificDNSServer, self).add(self, answers)
[docs]class DNSAnswerTranslation(DNSRule): """ Map IPv4 addresses resolved by external DNS servers to IPv4 addresses in the internal network. """ _attr = ('dns_answer_translation', 'original_ipaddress', 'translated_ipaddress')
[docs] def add(self, answers): """ Takes an IPv4 address and translates to a specified IPv4 value. Provide a list of two-tuple with the first entry providing the original address and second entry specifying the translated address:: profile = DNSRelayProfile('dnsrules') profile.dns_answer_translation.add([('12.12.12.12', '172.18.1.20')]) :param answers: (original_ipaddress, translated_ipaddress) :type answers: tuple[str, str] :raises UpdateElementFailed: failure to add to SMC :return: None """ super(DNSAnswerTranslation, self).add(self, answers)
[docs]class DNSRelayProfile(Element): """ DNS Relay Settings specify a profile to handle how the engine will interpret DNS queries. Stonesoft can act as a DNS relay, rewrite DNS queries or redirect domains to the specified DNS servers. """ typeof = 'dns_relay_profile' @property def fixed_domain_answer(self): """ Add a fixed domain answer entry. :rtype: FixedDomainAnswer """ return FixedDomainAnswer(self) @property def hostname_mapping(self): """ Add a hostname to IP mapping :rtype: HostnameMapping """ return HostnameMapping(self) @property def domain_specific_dns_server(self): """ Add domain to DNS server mapping :rtype: DomainSpecificDNSServer """ return DomainSpecificDNSServer(self) @property def dns_answer_translation(self): """ Add a DNS answer translation :rtype: DNSAnswerTranslation """ return DNSAnswerTranslation(self)
[docs]class SNMPAgent(Element): """ SNMPAgent configuration for monitoring specifics on NGFW. """ typeof = 'snmp_agent'
[docs] @classmethod def create(cls, name, snmp_monitoring_contact=None, snmp_monitoring_user_name=None, snmp_user_name=None, snmp_monitoring_listening_port=161, snmp_version='v3', comment=None): """ Create a new SNMPAgent. If specifying v2c or v3, you can optionally specify snmp_user_name as a list along with snmp_authentication_protocol and snmp_privacy_protocol, otherwise defaults will be selected. The simplest way to create an SNMP Agent is as follows:: SNMPAgent.update_or_create(name='MyAgent') To customize v3 settings around authentication and privacy protocols you can do:: SNMPAgent.create(name='MyAgent123', snmp_monitoring_user_name=['myuser'], snmp_user_name=[{'name': 'myuser', 'snmp_authentication_password': 'abcd1234', 'snmp_authentication_protocol': 'md5', 'snmp_privacy_protocol': 'aes', 'snmp_private_password': 'abcd1234'}]) ..note:: Check the SMC documentation for additional valid fields. :param str name: name of agent :param str snmp_monitoring_contact: name of monitoring contact :param list snmp_monitoring_user_name: monitoring communities :param list snmp_user_name: SNMP username required when specifying v2c or v3 :param int snmp_monitoring_listening_port: default port 161 :param str snmp_version: version of snmp, v1, v2c, or v3, default v3 :param str comment: optional comment """ json = {'boot': False, 'go_offline': False, 'go_online': False, 'hardware_alerts': False, 'name': name, 'policy_applied': False, 'shutdown': False, 'snmp_monitoring_contact': snmp_monitoring_contact, 'snmp_monitoring_listening_port': snmp_monitoring_listening_port, 'snmp_monitoring_user_name': snmp_monitoring_user_name or ['public'], 'snmp_trap_destination': [], 'snmp_user_name': snmp_user_name or [], 'snmp_version': snmp_version, 'user_login': False, 'comment': comment} if not snmp_user_name: # Username not set, use defaults json.update(snmp_user_name=[{'name': 'public', 'snmp_authentication_protocol': 'none', 'snmp_privacy_protocol': 'none'}]) return ElementCreator(cls, json)
class SandboxService(Element): typeof = 'sandbox_service' @classmethod def create(cls, name, sandbox_data_center, portal_username=None, comment=None): """ Create a Sandbox Service element """ json = { 'name': name, 'sandbox_data_center': element_resolver(sandbox_data_center), 'portal_username': portal_username if portal_username else '', 'comment': comment} return ElementCreator(cls, json) class SandboxDataCenter(Element): typeof = 'sandbox_data_center'