Ejemplo n.º 1
0
    def test_dynamic_source_nat(self):

        options = LogOptions()

        rule_values = {}
        nat = DynamicSourceNAT(options.data)
        nat.translated_value = '12.12.12.12'
        nat.translated_ports = (2000, 60000)
        rule_values.update(options=nat.data)

        self.assertEqual(nat.translated_value, '12.12.12.12')
        self.assertEqual(nat.translated_ports, (2000, 60000))
        nat.translated_value = '13.13.13.13'
        nat.translated_ports = (1000, 10001)
        self.assertEqual(nat.translated_value, '13.13.13.13')
        self.assertEqual(nat.translated_ports, (1000, 10001))
        self.assertIsNone(nat.original_value)

        options = LogOptions()
        host = Host('test', href='http://1.1.1.1')
        nat = DynamicSourceNAT(options.data)
        nat.translated_ports = (6000, 10000)
        nat.translated_value = host
        self.assertEqual(nat.translated_ports, (6000, 10000))
        self.assertEqual(nat.translated_value, 'http://1.1.1.1')

        # Add bad host, translated value should not change
        with patch('smc.base.model.Element.href',
                   new_callable=PropertyMock) as foo:
            foo.side_effect = ElementNotFound
            nat.translated_value = Host('foo')
            # Still original value
            self.assertEqual(nat.translated_value, 'http://1.1.1.1')
Ejemplo n.º 2
0
 def test_automatic_proxy(self):
     options = LogOptions()
     nat = StaticDestNAT(options.data)
     self.assertIsNone(nat.automatic_proxy)  # NAT is not yet configured
     nat.translated_value = '1.1.1.1'
     nat.automatic_proxy = True
     self.assertTrue(nat.automatic_proxy)
Ejemplo n.º 3
0
    def options(self):
        """
        Rule based options for logging. Enabling and
        disabled specific log settings.

        :rtype: LogOptions
        """
        return LogOptions(self)
Ejemplo n.º 4
0
 def test_static_dst_nat_add_translated_then_ports(self):
     options = LogOptions()
     nat = StaticDestNAT(options.data)
     nat.translated_value = '55.55.55.55'
     self.assertEqual(nat.translated_value, '55.55.55.55')
     nat.translated_ports = ('6005-6007', '8001-8002')
     self.assertEqual(nat.translated_value, '55.55.55.55')
     self.assertEqual(nat.translated_ports, ('6005-6007', '8001-8002'))
Ejemplo n.º 5
0
 def options(self):
     """
     Rule based options for logging. Enabling and
     disabled specific log settings.
     
     :return: :py:class:`smc.policy.rule_elements.LogOptions`
     """
     return LogOptions(self.data.get('options'))
Ejemplo n.º 6
0
 def test_static_dst_nat_add_ports_first(self):
     options = LogOptions()
     nat = StaticDestNAT(options.data)
     self.assertIsNone(nat.translated_ports)
     nat.translated_ports = (6000, 7000)
     self.assertEquals(nat.translated_ports, (6000, 7000))
     nat.translated_value = 'http://1.1.1.1'
     self.assertEqual(nat.translated_ports, (6000, 7000))
     self.assertEqual(nat.translated_value, 'http://1.1.1.1')
Ejemplo n.º 7
0
    def test_static_dst_nat_add_translated_value_then_original(self):

        options = LogOptions()
        nat = StaticDestNAT(options.data)

        nat.translated_value = '2.2.2.2'
        self.assertEqual(nat.translated_value, '2.2.2.2')

        nat.original_value = 'http://1.1.1.1'
        self.assertEqual(nat.original_value, 'http://1.1.1.1')
        self.assertEqual(nat.translated_value, '2.2.2.2')
Ejemplo n.º 8
0
 def create(self, name, sources=None, destinations=None, 
            services=None, action='allow', is_disabled=False, 
            vpn_policy=None, **kwargs):
     """ 
     Create a layer 3 firewall rule
         
     :param str name: name of rule
     :param list source: source/s for rule, in href format
     :param list destination: destinations, in href format
     :param list service: service/s, in href format
     :param str action: allow|continue|discard|refuse|enforce_vpn|apply_vpn|blacklist 
            (default: allow)
     :param str: vpn_policy: vpn policy name; required for enforce_vpn and apply_vpn 
            actions 
     :raises: :py:class:`smc.api.exceptions.MissingRequiredInput` when options are
              specified the need additional setting, i.e. use_vpn action requires a
              vpn policy be specified.
     :raises: :py:class:`smc.api.exceptions.CreateRuleFailed`: rule creation failure
     :return: str href: href of new rule
     """
     rule_values = _rule_common(sources, destinations, services)
     rule_values.update(name=name)
    
     rule_action = Action(actions=self.actions)
     rule_action.action = action
     
     if rule_action.action in ['apply_vpn', 'enforce_vpn', 'forward_vpn']:
         if vpn_policy is None:
             raise MissingRequiredInput('A VPN policy must be specified when '
                                        'rule action has a VPN action')
         try:
             vpn = VPNPolicy(vpn_policy).href
             rule_action.vpn = vpn
         except ElementNotFound:
             raise MissingRequiredInput('Cannot find VPN policy specified: {}, '
                                        .format(vpn_policy))
     
     rule_values.update(rule_action())
     
     log_options = LogOptions()    
     auth_options = AuthenticationOptions()
     
     rule_values.update(log_options())
     rule_values.update(auth_options())
     rule_values.update(is_disabled=is_disabled)
     
     return prepared_request(CreateRuleFailed,
                             href=self.href,
                             json=rule_values).create().href
Ejemplo n.º 9
0
    def test_static_dst_nat_add_original_value_then_translated(self):

        options = LogOptions()
        nat = StaticDestNAT(options.data)

        nat.original_value = 'http://1.1.1.1'
        self.assertEqual(nat.original_value, 'http://1.1.1.1')
        # Add translated value
        nat.translated_value = '2.2.2.2'
        self.assertEqual(nat.translated_value, '2.2.2.2')

        self.assertEqual(nat.translated_value, '2.2.2.2')
        self.assertEqual(nat.original_value, 'http://1.1.1.1')

        # Simulate SMC resolving translated value
        nat.data['static_dst_nat']['original_value'].update(
            {'ip_descriptor': '1.1.1.1'})
        self.assertEqual(nat.original_value, '1.1.1.1')
Ejemplo n.º 10
0
    def test_static_src_nat(self):
        options = LogOptions()
        nat = StaticSourceNAT(options.data)
        self.assertIsNone(nat.translated_value)
        self.assertIsNone(nat.original_value)

        # Original value as an element
        host = Host('test', href='http://1.1.1.1')
        nat.original_value = host
        # as element href
        self.assertEqual(nat.original_value, 'http://1.1.1.1')

        # Translated address as element href
        nat.translated_value = host
        self.assertEqual(nat.translated_value, 'http://1.1.1.1')
        # Specify IP for translated address
        nat.translated_value = '2.2.2.2'
        self.assertEqual(nat.translated_value, '2.2.2.2')

        # Incorrect format, needs to be href or element
        nat.original_value = '10.10.10.10'
        # same as original
        self.assertEqual(nat.original_value, 'http://1.1.1.1')

        nat.original_value = 'http://2.2.2.2'
        self.assertEqual(nat.original_value, 'http://2.2.2.2')

        with patch('smc.base.model.Element.href',
                   new_callable=PropertyMock) as foo:
            foo.side_effect = ElementNotFound
            self.assertEqual(nat.translated_value, '2.2.2.2')  # Before
            nat.translated_value = Host('foo')  # Invalid host
            self.assertEqual(nat.translated_value, '2.2.2.2')  # After

            self.assertEqual(nat.original_value, 'http://2.2.2.2')  # Before
            nat.original_value = Host('foo')  # Invalid host
            self.assertEqual(nat.original_value, 'http://2.2.2.2')  # After
Ejemplo n.º 11
0
 def test_automatic_proxy_added_first(self):
     options = LogOptions()
     nat = StaticDestNAT(options.data)
     nat.automatic_proxy = True
     self.assertTrue(nat.automatic_proxy)
Ejemplo n.º 12
0
    def create(self,
               name,
               sources=None,
               destinations=None,
               services=None,
               dynamic_src_nat=None,
               dynamic_src_nat_ports=(1024, 65535),
               static_src_nat=None,
               static_dst_nat=None,
               static_dst_nat_ports=None,
               is_disabled=False,
               used_on=None):
        """
        Create a NAT rule.
        
        When providing sources/destinations or services, you can provide the
        element href, network element or service from
        :py:class:`smc.elements.network` and :py:class:`smc.elements.service`.
        You can also use both types of input for these fields. 
        
        :param str name: name of NAT rule
        :param list sources: list of sources by href or :py:class:`smc.elements.network`
        :param list destinations: list of destinations by href or :py:class:`smc.elements.network`
        :param list services: list of services by href or :py:class:`smc.elements.service`
        :param dynamic_src_nat: str ip or element from :py:class:`smc.elements.network` for dest NAT
        :param tuple dynamic_src_nat_ports: starting and ending ports for PAT. Default: (1024, 65535)
        :param static_src_nat: str ip or element href of used for source NAT
        :param static_dst_nat: destination NAT IP address or element href
        :param tuple static_dst_nat_ports: ports or port range used for original and destination ports 
               (only needed if a different destination port is used and does not match the rules service port)
        :param boolean is_disabled: whether to disable rule or not
        :param str used_on: element or href (of security engine) where this NAT rule applies, Default: Any
        :raises: :py:class:`smc.api.exceptions.InvalidRuleValue`: if rule requirements are not met
        :raises: :py:class:`smc.api.exceptions.CreateRuleFailed`: rule creation failure
        :return: None
        """
        rule_values = _rule_common(sources, destinations, services)
        rule_values.update(name=name)
        rule_values.update(is_disabled=is_disabled)

        options = LogOptions()

        if dynamic_src_nat:
            nat = DynamicSourceNAT(options.data)
            nat.translated_value = dynamic_src_nat
            nat.translated_ports = (dynamic_src_nat_ports)
            rule_values.update(options=nat.data)

        elif static_src_nat:
            nat = StaticSourceNAT(options.data)
            nat.translated_value = static_src_nat
            nat.original_value = sources[0].href
            rule_values.update(options=nat.data)

        if static_dst_nat:
            destination = Destination(rule_values['destinations'])
            if destination.is_any or destination.is_none:
                raise InvalidRuleValue(
                    'Destination field cannot be none or any for '
                    'destination NAT.')
            nat = StaticDestNAT(options.data)
            nat.translated_value = static_dst_nat
            nat.original_value = destination.all_as_href()[0]
            rule_values.update(options=nat.data)

        if 'options' not in rule_values:  # No NAT
            rule_values.update(options=options.data)

        rule_values.update(used_on=used_on)
        return prepared_request(CreateRuleFailed,
                                href=self.href,
                                json=rule_values).create()
Ejemplo n.º 13
0
    def create(self,
               name,
               sources=None,
               destinations=None,
               services=None,
               action='allow',
               log_options=None,
               authentication_options=None,
               connection_tracking=None,
               is_disabled=False,
               vpn_policy=None,
               mobile_vpn=False,
               add_pos=None,
               after=None,
               before=None,
               sub_policy=None,
               comment=None,
               **kw):
        """ 
        Create a layer 3 firewall rule

        :param str name: name of rule
        :param sources: source/s for rule
        :type sources: list[str, Element]
        :param destinations: destination/s for rule
        :type destinations: list[str, Element]
        :param services: service/s for rule
        :type services: list[str, Element]
        :param action: allow,continue,discard,refuse,enforce_vpn,
            apply_vpn,forward_vpn, blacklist (default: allow)
        :type action: Action or str
        :param LogOptions log_options: LogOptions object
        :param ConnectionTracking connection_tracking: custom connection tracking settings
        :param AuthenticationOptions authentication_options: options for auth if any
        :param PolicyVPN,str vpn_policy: policy element or str href; required for
            enforce_vpn, use_vpn and apply_vpn actions
        :param bool mobile_vpn: if using a vpn action, you can set mobile_vpn to True and
            omit the vpn_policy setting if you want this VPN to apply to any mobile VPN based
            on the policy VPN associated with the engine
        :param str,Element sub_policy: sub policy required when rule has an action of 'jump'.
            Can be the FirewallSubPolicy element or href.
        :param int add_pos: position to insert the rule, starting with position 1. If
            the position value is greater than the number of rules, the rule is inserted at
            the bottom. If add_pos is not provided, rule is inserted in position 1. Mutually
            exclusive with ``after`` and ``before`` params.
        :param str after: Rule tag to add this rule after. Mutually exclusive with ``add_pos``
            and ``before`` params.
        :param str before: Rule tag to add this rule before. Mutually exclusive with ``add_pos``
            and ``after`` params.
        :param str comment: optional comment for this rule
        :raises MissingRequiredInput: when options are specified the need additional 
            setting, i.e. use_vpn action requires a vpn policy be specified.
        :raises CreateRuleFailed: rule creation failure
        :return: the created ipv4 rule
        :rtype: IPv4Rule
        """
        rule_values = self.update_targets(sources, destinations, services)
        rule_values.update(name=name, comment=comment)

        if isinstance(action, Action):
            rule_action = action
        else:
            rule_action = Action()
            rule_action.action = action

        if not rule_action.action in self._actions:
            raise CreateRuleFailed('Action specified is not valid for this '
                                   'rule type; action: {}'.format(
                                       rule_action.action))

        if rule_action.action in ('apply_vpn', 'enforce_vpn', 'forward_vpn'):
            if vpn_policy is None and not mobile_vpn:
                raise MissingRequiredInput(
                    'You must either specify a vpn_policy or set '
                    'mobile_vpn when using a rule with a VPN action')
            if mobile_vpn:
                rule_action.mobile_vpn = True
            else:
                try:
                    vpn = element_resolver(vpn_policy)  # VPNPolicy
                    rule_action.vpn = vpn
                except ElementNotFound:
                    raise MissingRequiredInput(
                        'Cannot find VPN policy specified: {}, '.format(
                            vpn_policy))

        elif rule_action.action == 'jump':
            try:
                rule_action.sub_policy = element_resolver(sub_policy)
            except ElementNotFound:
                raise MissingRequiredInput(
                    'Cannot find sub policy specified: {} '.format(sub_policy))

        #rule_values.update(action=rule_action.data)

        log_options = LogOptions() if not log_options else log_options

        if connection_tracking is not None:
            rule_action.connection_tracking_options.update(
                **connection_tracking)

        auth_options = AuthenticationOptions() if not authentication_options \
            else authentication_options

        rule_values.update(action=rule_action.data,
                           options=log_options.data,
                           authentication_options=auth_options.data,
                           is_disabled=is_disabled)

        params = None
        href = self.href
        if add_pos is not None:
            href = self.add_at_position(add_pos)
        elif before or after:
            params = self.add_before_after(before, after)

        return ElementCreator(self.__class__,
                              exception=CreateRuleFailed,
                              href=href,
                              params=params,
                              json=rule_values)
Ejemplo n.º 14
0
    def add_policy(self):
        """
        If a client AMI was specified when building a new VPC, this will add
        rules to allow inbound access to the AMI. This could be extended to 
        more generically support VPN rules.
        """
        if not self.firewall_policy:
            self.firewall_policy = 'AWS_Default'
            # Policy not specified, use the default, or check if hidden setting was specified
            try:
                FirewallPolicy.create(name='AWS_Default',
                                      template='Firewall Inspection Template')
            except CreatePolicyFailed:
                pass  # Already exists

        policy = FirewallPolicy(self.firewall_policy)
        # Create the access rule for the network

        options = LogOptions()
        options.log_accounting_info_mode = True
        options.log_level = 'stored'
        options.application_logging = 'enforced'
        options.user_logging = 'enforced'

        action = Action()
        action.deep_inspection = True
        action.file_filtering = False

        outbound_rule = policy.search_rule('AWS outbound access rule')
        if not outbound_rule:
            # Generic outbound access rule
            policy.fw_ipv4_access_rules.create(
                name='AWS outbound access rule',
                sources=[Alias('$$ Interface ID 1.net')],
                destinations='any',
                services='any',
                action=action,
                log_options=options)

        if self.aws_ami_ip and self.nat_ports:
            dest_port = self.nat_ports.get('dest_port')
            redirect_port = self.nat_ports.get('redirect_port')

            services = list(
                TCPService.objects.filter(dest_port))  # @UndefinedVariable
            # Ignore services with protocol agents so we skip SSM
            service = next(
                ([service]
                 for service in services if not service.protocol_agent), [])

            if not service:
                service = [
                    TCPService.create(name='aws_tcp{}'.format(dest_port),
                                      min_dst_port=dest_port)
                ]

            # Create the access rule for the client
            policy.fw_ipv4_access_rules.create(
                name=self.name,
                sources='any',
                destinations=[Alias('$$ Interface ID 0.ip')],
                services=service,
                action='allow',
                log_options=options)
            policy.fw_ipv4_nat_rules.create(
                name=self.name,
                sources='any',
                destinations=[Alias('$$ Interface ID 0.ip')],
                services=service,
                static_dst_nat=self.aws_ami_ip,
                static_dst_nat_ports=(dest_port, redirect_port),
                used_on=self.engine.href)
Ejemplo n.º 15
0
 def __init__(self, rule=None):
     options = LogOptions().data if not rule else rule.data.get("options")
     self.rule = rule
     super(NATElement, self).__init__(data=options)
Ejemplo n.º 16
0
    def create(self,
               name,
               sources=None,
               destinations=None,
               services=None,
               action="allow",
               log_options=None,
               authentication_options=None,
               match_vpn_options=None,
               connection_tracking=None,
               is_disabled=False,
               vpn_policy=None,
               mobile_vpn=False,
               add_pos=None,
               after=None,
               before=None,
               sub_policy=None,
               comment=None,
               validate=True,
               **kw):
        """
        Create a layer 3 firewall rule

        .. versionchanged:: 0.7.0
            Action field now requires a list of actions as strings when using SMC
            version >= 6.6.0

        :param str name: name of rule
        :param sources: source/s for rule
        :type sources: list[str, Element]
        :param destinations: destination/s for rule
        :type destinations: list[str, Element]
        :param services: service/s for rule
        :type services: list[str, Element]
        :param action: allow,continue,discard,refuse,enforce_vpn,
            apply_vpn,forward_vpn, blacklist (default: allow)
        :type action: Action,str,list[str]
        :param LogOptions log_options: LogOptions object
        :param ConnectionTracking connection_tracking: custom connection tracking settings
        :param AuthenticationOptions authentication_options: options for auth if any
        :param SourceVpn match_vpn_options: rule matches traffic from specific VPNs
        :param PolicyVPN,str vpn_policy: policy element or str href; required for
            enforce_vpn, use_vpn and apply_vpn actions
        :param bool mobile_vpn: if using a vpn action, you can set mobile_vpn to True and
            omit the vpn_policy setting if you want this VPN to apply to any mobile VPN based
            on the policy VPN associated with the engine
        :param str,Element sub_policy: sub policy required when rule has an action of 'jump'.
            Can be the FirewallSubPolicy element or href.
        :param int add_pos: position to insert the rule, starting with position 1. If
            the position value is greater than the number of rules, the rule is inserted at
            the bottom. If add_pos is not provided, rule is inserted in position 1. Mutually
            exclusive with ``after`` and ``before`` params.
        :param str after: Rule tag to add this rule after. Mutually exclusive with ``add_pos``
            and ``before`` params.
        :param str before: Rule tag to add this rule before. Mutually exclusive with ``add_pos``
            and ``after`` params.
        :param str comment: optional comment for this rule
        :param bool validate: validate the inspection policy during rule creation. Default: True
        :raises MissingRequiredInput: when options are specified the need additional
            setting, i.e. use_vpn action requires a vpn policy be specified.
        :raises CreateRuleFailed: rule creation failure
        :return: the created ipv4 rule
        :rtype: IPv4Rule
        """
        rule_values = self.update_targets(sources, destinations, services)

        rule_action = self._get_action(action)

        if any(vpn in rule_action.action
               for vpn in ("apply_vpn", "enforce_vpn", "forward_vpn")):
            if vpn_policy is None and not mobile_vpn:
                raise MissingRequiredInput(
                    "You must either specify a vpn_policy or set "
                    "mobile_vpn when using a rule with a VPN action")
            if mobile_vpn:
                rule_action.mobile_vpn = True
            else:
                try:
                    vpn = element_resolver(vpn_policy)  # VPNPolicy
                    rule_action.vpn = vpn
                except ElementNotFound:
                    raise MissingRequiredInput(
                        "Cannot find VPN policy specified: {}, ".format(
                            vpn_policy))

        elif "jump" in rule_action.action:
            try:
                rule_action.sub_policy = element_resolver(sub_policy)
            except ElementNotFound:
                raise MissingRequiredInput(
                    "Cannot find sub policy specified: {} ".format(sub_policy))

        log_options = LogOptions() if not log_options else log_options

        if connection_tracking is not None:
            rule_action.connection_tracking_options.update(
                **connection_tracking)

        auth_options = (AuthenticationOptions() if not authentication_options
                        else authentication_options)

        match_vpn_data = None if not match_vpn_options else match_vpn_options.data

        rule_values.update(name=name,
                           comment=comment,
                           action=rule_action.data,
                           options=log_options.data,
                           authentication_options=auth_options.data,
                           match_vpn_options=match_vpn_data,
                           is_disabled=is_disabled,
                           **kw)

        params = {"validate": False} if not validate else {}
        href = self.href
        if add_pos is not None:
            href = self.add_at_position(add_pos)
        elif before or after:
            params.update(**self.add_before_after(before, after))

        return ElementCreator(self.__class__,
                              exception=CreateRuleFailed,
                              href=href,
                              params=params,
                              json=rule_values)
Ejemplo n.º 17
0
    def test_log_options(self):

        options = LogOptions()
        options.log_accounting_info_mode = False
        options.log_level = 'stored'
        options.application_logging = 'enforced'
        options.user_logging = 'enforced'
        options.comment = 'my new comment!!'
        options.log_closing_mode = True
        options.log_level = 'transient'
        options.log_payload_additional = True
        options.log_payload_excerpt = True
        options.log_payload_record = True

        self.assertTrue(options.log_accounting_info_mode)
        self.assertTrue(options.log_closing_mode)
        self.assertEqual(options.log_level, 'transient')
        self.assertTrue(options.log_payload_additional)
        self.assertTrue(options.log_payload_excerpt)
        self.assertTrue(options.log_payload_record)
        self.assertEqual(options.user_logging, 'enforced')
        self.assertEqual(options.log_severity, -1)
        self.assertEqual(options.application_logging, 'enforced')

        o = options()
        for k, v in o.items():
            self.assertEqual(k, 'options')
            self.assertDictEqual(v, options.data)
Ejemplo n.º 18
0
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)
        
        changed = False
        
        try:            
            # Now that we have valid option settings, we can hit the db
            if self.policy:
                policy = FirewallPolicy.get(self.policy)
            else:
                policy = FirewallSubPolicy.get(self.sub_policy)
            
            if state == 'present':
                
                for rule in self.rules:
                    try:
                        validate_rule_syntax(rule)
                    except Exception as e:
                        self.fail(msg=str(e))
        
                self.cache = Cache()

                for rule in self.rules:
                    # Resolve elements if they exist, calls to SMC could happen here
                    if 'sources' in rule:
                        self.field_resolver(rule.get('sources'), rule_targets)
                    
                    if 'destinations' in rule:
                        self.field_resolver(rule.get('destinations'), rule_targets)
                    
                    if 'services' in rule:
                        self.field_resolver(rule.get('services'), service_targets)
                    
                    if 'vpn_policy' in rule:
                        self.cache._add_entry('vpn', rule.get('vpn_policy'))
                        
                    if 'sub_policy' in rule:
                        self.cache._add_entry('sub_ipv4_fw_policy', rule.get('sub_policy'))
                    
                    if 'authentication_options' in rule:
                        auth = rule['authentication_options']
                        if auth.get('require_auth'):
                            for method in auth.get('methods'):
                                self.cache._add_entry('authentication_service', method)
                            
                            for accounts in ('users', 'groups'):
                                self.cache._add_user_entries(accounts, auth.get(accounts, []))

                if self.cache.missing:
                    self.fail(msg='Missing required elements that are referenced in this '
                        'configuration: %s' % self.cache.missing)
                
                if self.check_mode:
                    return self.results
                
                for rule in self.rules:
                    rule_dict = {}
                
                    if 'log_options' in rule:
                        log_options = LogOptions()
                        _log = rule['log_options']
                        for name, value in log_options.items():
                            if name not in _log:
                                log_options.pop(name)
            
                        log_options.update(rule.get('log_options', {}))
                        rule_dict.update(log_options=log_options)

                    if 'connection_tracking' in rule:
                        connection_tracking = ConnectionTracking()
                        _ct = rule['connection_tracking']
                        for name, value in connection_tracking.items():
                            if name not in _ct:
                                connection_tracking.pop(name)
            
                        connection_tracking.update(rule.get('connection_tracking',{}))
                        rule_dict.update(connection_tracking=connection_tracking)
                    
                    action = Action() # If no action, set to default based on version
                    if 'action' not in rule:
                        action.action = 'allow' if not is_sixdotsix_compat() else ['allow']
                    else:
                        action.action = rule.get('action')
                    
                    if 'inspection_options' in rule:
                        _inspection = rule['inspection_options']
                        for option in inspection_options:
                            if option in _inspection:
                                action[option] = _inspection.get(option)
                    
                    if 'authentication_options' in rule:
                        _auth_options = rule['authentication_options']
                        auth_options = AuthenticationOptions()
                        
                        if _auth_options.get('require_auth'):
                            auth_options.update(methods=[
                                self.get_value('authentication_service', m).href
                                for m in _auth_options.get('methods', [])],
                            require_auth=True)
                            
                            auth_options.update(users=[entry.href
                                for entry in self.cache.get_type('user_element')])

                        rule_dict.update(authentication_options=auth_options)
                    
                    rule_dict.update(action=action)
                    
                    for field in ('sources', 'destinations', 'services'):
                        rule_dict[field] = self.get_values(rule.get(field, None))

                    rule_dict.update(
                        vpn_policy=self.get_value('vpn', rule.get('vpn_policy')),
                        sub_policy=self.get_value('sub_ipv4_fw_policy', rule.get('sub_policy')),
                        mobile_vpn=rule.get('mobile_vpn', False))
                    
                    if 'comment' in rule:
                        rule_dict.update(comment=rule.get('comment'))
                    
                    rule_dict.update(
                        name=rule.get('name'),
                        is_disabled=rule.get('is_disabled', False))
                    
                    if 'tag' not in rule:
                        # If no tag is present, this is a create
                        rule_dict.update(
                            before=rule.get('add_before'),
                            after=rule.get('add_after'))
                        
                        rule = policy.fw_ipv4_access_rules.create(**rule_dict)
                        changed = True
                        self.results['state'].append({
                            'rule': rule.name,
                            'type': rule.typeof,
                            'action': 'created'})
                    
                    else:
                        # Modify as rule has 'tag' defined. Fetch the rule first
                        # by it's tag reference, skip if tag not found
                        target_rule = self.rule_by_tag(policy, rule.get('tag'))
                        if not target_rule:
                            continue

                        changes = compare_rules(target_rule, rule_dict)
                        # Changes have already been merged if any
                        if rule.get('add_after', None):
                            rule_at_pos = self.rule_by_tag(policy, rule.get('add_after'))
                            if rule_at_pos:
                                target_rule.move_rule_after(rule_at_pos)
                                changes.append('add_after')
                        elif rule.get('add_before', None):
                            rule_at_pos = self.rule_by_tag(policy, rule.get('add_before'))
                            if rule_at_pos:
                                target_rule.move_rule_before(rule_at_pos)
                                changes.append('add_before')
                        elif changes:
                            target_rule.save()
                        
                        if changes:
                            changed = True
                            self.results['state'].append({
                                'rule': target_rule.name,
                                'type': target_rule.typeof,
                                'action': 'modified',
                                'changes': changes})
    
            elif state == 'absent':
                for rule in self.rules:
                    if 'tag' in rule:
                        target_rule = self.rule_by_tag(policy, rule.get('tag'))
                        if target_rule:
                            target_rule.delete()
                            changed = True
                            self.results['state'].append({
                                'rule': target_rule.name,
                                'type': target_rule.typeof,
                                'action': 'deleted'})

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())
        
        self.results['changed'] = changed
        return self.results
Ejemplo n.º 19
0
    def create(self,
               name,
               sources=None,
               destinations=None,
               services=None,
               dynamic_src_nat=None,
               dynamic_src_nat_ports=(1024, 65535),
               static_src_nat=None,
               static_dst_nat=None,
               static_dst_nat_ports=None,
               is_disabled=False,
               used_on=None):
        """
        Create a NAT rule.

        When providing sources/destinations or services, you can provide the
        element href, network element or services from ``smc.elements``.
        You can also mix href strings with Element types in these fields. 

        :param str name: name of NAT rule
        :param list sources: list of sources by href or Element
        :type sources: list(str,Element)
        :param list destinations: list of destinations by href or Element
        :type destinations: list(str,Element)
        :param list services: list of services by href or Element
        :type services: list(str,Element)
        :param dynamic_src_nat: str ip or Element for dest NAT
        :type dynamic_src_nat: str,Element
        :param tuple dynamic_src_nat_ports: starting and ending ports for PAT.
            Default: (1024, 65535)
        :param str static_src_nat: ip or element href of used for source NAT
        :param str static_dst_nat: destination NAT IP address or element href
        :param tuple static_dst_nat_ports: ports or port range used for original
            and destination ports (only needed if a different destination port
            is used and does not match the rules service port)
        :param bool is_disabled: whether to disable rule or not
        :param str used_on: href or Element (of security engine) where this
            NAT rule applies, Default: Any
        :type used_on: str,Element
        :raises InvalidRuleValue: if rule requirements are not met
        :raises CreateRuleFailed: rule creation failure
        :return: newly created NAT rule
        :rtype: IPv4NATRule
        """
        rule_values = self.update_targets(sources, destinations, services)
        rule_values.update(name=name)
        rule_values.update(is_disabled=is_disabled)

        options = LogOptions()

        if dynamic_src_nat:
            nat = DynamicSourceNAT(options.data)
            nat.translated_value = dynamic_src_nat
            nat.translated_ports = (dynamic_src_nat_ports)
            rule_values.update(options=nat.data)

        elif static_src_nat:
            nat = StaticSourceNAT(options.data)
            nat.translated_value = static_src_nat
            nat.original_value = sources[0].href
            rule_values.update(options=nat.data)

        if static_dst_nat:
            destinations = rule_values['destinations']
            if 'any' in destinations or 'none' in destinations:
                raise InvalidRuleValue(
                    'Destination field cannot be none or any for '
                    'destination NAT.')
            destination = Destination()
            destination.add_many(destinations.get('dst'))

            nat = StaticDestNAT(options.data)
            nat.translated_value = static_dst_nat
            nat.original_value = destination.all_as_href()[0]
            if static_dst_nat_ports:
                nat.translated_ports = static_dst_nat_ports
            rule_values.update(options=nat.data)

        if 'options' not in rule_values:  # No NAT
            rule_values.update(options=options.data)

        rule_values.update(used_on=used_on)

        return SubElementCreator(self.__class__,
                                 CreateRuleFailed,
                                 href=self.href,
                                 json=rule_values)
Ejemplo n.º 20
0
    def create(
        self,
        name,
        sources=None,
        destinations=None,
        services=None,
        dynamic_src_nat=None,
        dynamic_src_nat_ports=(1024, 65535),
        static_src_nat=None,
        static_dst_nat=None,
        static_dst_nat_ports=None,
        is_disabled=False,
        used_on="ANY",
        add_pos=None,
        after=None,
        before=None,
        comment=None,
        validate=True,
    ):
        """
        Create a NAT rule.

        When providing sources/destinations or services, you can provide the
        element href, network element or services from ``smc.elements``.
        You can also mix href strings with Element types in these fields.

        :param str name: name of NAT rule
        :param list sources: list of sources by href or Element
        :type sources: list(str,Element)
        :param list destinations: list of destinations by href or Element
        :type destinations: list(str,Element)
        :param list services: list of services by href or Element
        :type services: list(str,Element)
        :param dynamic_src_nat: str ip or Element for dest NAT
        :type dynamic_src_nat: str,Element
        :param tuple dynamic_src_nat_ports: starting and ending ports for PAT.
            Default: (1024, 65535)
        :param str static_src_nat: ip or element href of used for source NAT
        :param str static_dst_nat: destination NAT IP address or element href
        :param tuple static_dst_nat_ports: ports or port range used for original
            and destination ports (only needed if a different destination port
            is used and does not match the rules service port)
        :param bool is_disabled: whether to disable rule or not
        :param str,Engine used_on: Can be None, 'ANY' or and Engine element. Default
            is 'ANY'.
        :type used_on: str,Element
        :param int add_pos: position to insert the rule, starting with position 1. If
            the position value is greater than the number of rules, the rule is inserted at
            the bottom. If add_pos is not provided, rule is inserted in position 1. Mutually
            exclusive with ``after`` and ``before`` params.
        :param str after: Rule tag to add this rule after. Mutually exclusive with ``add_pos``
            and ``before`` params.
        :param str before: Rule tag to add this rule before. Mutually exclusive with ``add_pos``
            and ``after`` params.
        :param str comment: optional comment for the NAT rule
        :param bool validate: validate the inspection policy during rule creation. Default: True
        :raises InvalidRuleValue: if rule requirements are not met
        :raises CreateRuleFailed: rule creation failure
        :return: newly created NAT rule
        :rtype: IPv4NATRule
        """
        rule_values = self.update_targets(sources, destinations, services)
        rule_values.update(name=name, comment=comment, is_disabled=is_disabled)

        rule_values.update(used_on={"any": True} if used_on ==
                           "ANY" else element_resolver(used_on))

        if dynamic_src_nat:
            nat = DynamicSourceNAT()
            start_port, end_port = dynamic_src_nat_ports
            nat.update_field(dynamic_src_nat,
                             start_port=start_port,
                             end_port=end_port)
            rule_values.update(options=nat)

        elif static_src_nat:
            sources = rule_values["sources"]
            if "any" in sources or "none" in sources:
                raise InvalidRuleValue(
                    "Source field cannot be none or any for "
                    "static source NAT.")

            nat = StaticSourceNAT()
            nat.update_field(static_src_nat,
                             original_value=sources.get("src")[0])
            rule_values.update(options=nat)

        if static_dst_nat:
            destinations = rule_values["destinations"]
            if "any" in destinations or "none" in destinations:
                raise InvalidRuleValue(
                    "Destination field cannot be none or any for "
                    "destination NAT.")

            nat = StaticDestNAT()
            original_port, translated_port = None, None
            if static_dst_nat_ports:
                original_port, translated_port = static_dst_nat_ports

            nat.update_field(
                static_dst_nat,
                original_value=destinations.get("dst")[0],
                original_port=original_port,
                translated_port=translated_port,
            )

            rule_values.setdefault("options", {}).update(nat)

        if "options" not in rule_values:  # No NAT
            rule_values.update(options=LogOptions())

        params = {"validate": False} if not validate else {}

        href = self.href
        if add_pos is not None:
            href = self.add_at_position(add_pos)
        elif before or after:
            params.update(**self.add_before_after(before, after))

        return ElementCreator(self.__class__,
                              exception=CreateRuleFailed,
                              href=href,
                              params=params,
                              json=rule_values)
Ejemplo n.º 21
0
    def create(self,
               name,
               sources=None,
               destinations=None,
               services=None,
               action='allow',
               log_options=None,
               is_disabled=False,
               vpn_policy=None,
               add_pos=None,
               after=None,
               before=None,
               sub_policy=None,
               comment=None,
               **kw):
        """ 
        Create a layer 3 firewall rule

        :param str name: name of rule
        :param sources: source/s for rule
        :type sources: list[str, Element]
        :param destinations: destination/s for rule
        :type destinations: list[str, Element]
        :param services: service/s for rule
        :type services: list[str, Element]
        :param action: allow,continue,discard,refuse,enforce_vpn,
            apply_vpn,blacklist (default: allow)
        :type action: Action or str
        :param LogOptions log_options: LogOptions object
        :param str: vpn_policy: vpn policy name; required for enforce_vpn and apply_vpn 
               actions
        :param str,Element sub_policy: sub policy required when rule has an action of 'jump'.
            Can be the FirewallSubPolicy element or href.
        :param int add_pos: position to insert the rule, starting with position 1. If
            the position value is greater than the number of rules, the rule is inserted at
            the bottom. If add_pos is not provided, rule is inserted in position 1. Mutually
            exclusive with ``after`` and ``before`` params.
        :param str after: Rule tag to add this rule after. Mutually exclusive with ``add_pos``
            and ``before`` params.
        :param str before: Rule tag to add this rule before. Mutually exclusive with ``add_pos``
            and ``after`` params.
        :param str comment: optional comment for this rule
        :raises MissingRequiredInput: when options are specified the need additional 
            setting, i.e. use_vpn action requires a vpn policy be specified.
        :raises CreateRuleFailed: rule creation failure
        :return: the created ipv4 rule
        :rtype: IPv4Rule
        """
        rule_values = self.update_targets(sources, destinations, services)
        rule_values.update(name=name, comment=comment)

        if isinstance(action, Action):
            rule_action = action
        else:
            rule_action = Action()
            rule_action.action = action

        if not rule_action.action in self._actions:
            raise CreateRuleFailed('Action specified is not valid for this '
                                   'rule type; action: {}'.format(
                                       rule_action.action))

        if rule_action.action in ['apply_vpn', 'enforce_vpn', 'forward_vpn']:
            if vpn_policy is None:
                raise MissingRequiredInput(
                    'A VPN policy must be specified when '
                    'rule action has a VPN action')
            try:
                vpn = PolicyVPN(vpn_policy).href
                rule_action.vpn = vpn
            except ElementNotFound:
                raise MissingRequiredInput(
                    'Cannot find VPN policy specified: {}, '.format(
                        vpn_policy))
        elif rule_action.action in ['jump']:
            try:
                rule_action.sub_policy = element_resolver(sub_policy)
            except ElementNotFound:
                raise MissingRequiredInput(
                    'Cannot find sub policy specified: {} '.format(sub_policy))

        rule_values.update(action=rule_action.data)

        if log_options is None:
            log_options = LogOptions()

        auth_options = AuthenticationOptions()

        rule_values.update(options=log_options.data)
        rule_values.update(authentication_options=auth_options.data)
        rule_values.update(is_disabled=is_disabled)

        params = None
        href = self.href
        if add_pos is not None:
            href = self.add_at_position(add_pos)
        elif before or after:
            params = self.add_before_after(before, after)

        return SubElementCreator(self.__class__,
                                 CreateRuleFailed,
                                 href=href,
                                 params=params,
                                 json=rule_values)