Beispiel #1
0
    def enum_group_members(self, groups, group_types):
        """
        Check group membership. Groups reference only the type of element and
        the names of those members. If the element is being created, skip the
        existence check. If the member is not being created, attempt to fetch
        the member and save to cache. Return the cache. Check cache.missing
        before continuing to ensure all required elements are found.
        
        :param list groups: list of groups extracted from elements
        :param list group_types: all supported group types by name
        :rtype: Cache
        """
        to_be_created = {
        }  # dict of element by type: set([names]) to be created.

        # If groups reference elements that are to be created, skip validating.
        # Otherwise check for existence
        for element in self.elements:
            for typeof, values in element.items():
                if typeof not in group_types:
                    to_be_created.setdefault(typeof,
                                             set()).add(values.get('name'))

        cache = Cache()
        for group in groups:
            for _, values in group.items():
                members = {} if values.get(
                    'members') is None else values['members']
                for typeof, member in members.items():
                    for name in member:
                        if name not in to_be_created.get(typeof, set()):
                            cache._add_entry(typeof, name)
        return cache
Beispiel #2
0
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)

        changed = False

        route_map = self.fetch_element(RouteMap)

        if state == 'present':
            cache = Cache()
            # Validate rule structure
            cache_ready = self.check_rules()
            cache.add_many(cache_ready)
            if cache.missing:
                self.fail(msg='Missing specified match condition elements',
                          results=cache.missing)

            self.cache = cache

        try:

            if state == 'present':
                if not route_map:
                    route_map = RouteMap.create(self.name,
                                                comment=self.comment)

                rules = []
                for rule in self.rules:

                    rule.pop('tag', None)
                    compiled_rule = dict(**rule)

                    if 'match_condition' in rule:
                        compiled_rule.update(
                            match_condition=self.serialize_match_condition(
                                rule.get('match_condition', [])))

                    rules.append(compiled_rule)

                if self.delete_undefined_rules:
                    names = [rule.get('name') for rule in rules]
                    for rule in route_map.route_map_rules:
                        if rule.name not in names:
                            rule.delete()

                for rule in rules:
                    route_map.route_map_rules.create(**rule)
                    changed = True

            elif state == 'absent':
                if route_map:
                    route_map.delete()
                    changed = True

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())

        self.results['changed'] = changed
        return self.results
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)
        
        changed = False
        engine = self.fetch_element(FirewallCluster)
        
        if state == 'present':
            # Resolve dependencies
            if not engine:
                if not self.interfaces:
                    self.fail(msg='You must provide at least one interface '
                        'configuration to create a cluster.')
                
                if not self.primary_mgt:
                    self.fail(msg='You must provide a primary_mgt interface to create '
                        'an engine.')
                
                if not self.cluster_mode:
                    self.fail(msg='You must define a cluster mode to create an engine')
                
                itf = self.check_interfaces()
                
                # Management interface
                if not self.primary_mgt in itf:
                    self.fail(msg='Management interface is not defined. Management was '
                        'specified on interface: %s' % self.primary_mgt)
            
            if engine and self.interfaces and not self.skip_interfaces:
                itf = self.check_interfaces()
            
            cache = Cache()
            
            # SNMP settings
            if self.snmp and self.snmp.get('enabled', True):
                cache._add_entry('snmp_agent', self.snmp.get('snmp_agent', None))
                if cache.missing:
                    self.fail(msg='SNMP configured but the SNMP Agent specified is not '
                        'found: %s' % cache.missing)

            # Only validate BGP if it's specifically set to enabled    
            if self.bgp and self.bgp.get('enabled', True):
                # BGP Profile if specified
                if self.bgp.get('bgp_profile', None):
                    cache._add_entry('bgp_profile', self.bgp['bgp_profile'])
                    if cache.missing:
                        self.fail(msg='A BGP Profile was specified that does not exist: '
                            '%s' % self.bgp['bgp_profile'])
                
                # Get external bgp peers, can be type 'engine' or 'external_bgp_peer'
                # Can also be empty if you don't want to attach a peer.
                peerings = self.bgp.get('bgp_peering', [])
                for peer in peerings:
                    if 'name' not in peer:
                        self.fail(msg='BGP Peering requires a name field to identify the '
                            'BGP Peering element. Peer info provided: %s' % peer)
                    if 'external_bgp_peer' not in peer and 'engine' not in peer:
                        self.fail(msg='Missing the external_bgp_peer or engine parameter '
                            'which defines the next hop for the BGP Peering')
                    if 'external_bgp_peer' in peer:
                        cache._add_entry('external_bgp_peer', peer['external_bgp_peer'])
                    elif 'engine' in peer:
                        cache._add_entry('fw_cluster', peer['engine'])
        
                if cache.missing:
                    self.fail(msg='Missing external BGP Peering elements: %s' % cache.missing)
                
                as_system = self.bgp.get('autonomous_system', {})
                if not engine:
                    # We are trying to enable BGP on a new engine, Autonomous System
                    # is required
                    if not as_system:
                        self.fail(msg='You must specify an Autonomous System when enabling '
                            'BGP on a newly created engine.')
                if as_system:
                    if 'name' not in as_system or 'as_number' not in as_system:
                        self.fail(msg='Autonomous System requires a name and and '
                            'as_number value.')

                spoofing = self.bgp.get('antispoofing_network', {})
                self.validate_antispoofing_network(spoofing)
                cache.add(spoofing)
                if cache.missing:
                    self.fail(msg='Missing elements in antispoofing configuration: %s' %
                        cache.missing)
                    
                networks = self.bgp.get('announced_network', [])
                announced_networks = self.validate_and_extract_announced(networks)
                cache.add(announced_networks)
                if cache.missing:
                    self.fail(msg='Missing elements in announced configuration: %s' % cache.missing)
                
            self.cache = cache
        
        try:
            
            if state == 'present':
                if not engine:

                    interfaces = [vars(intf) for intf in itf]
                    
                    cluster = {'interfaces': interfaces}
                    cluster.update(
                        name=self.name,
                        cluster_mode=self.cluster_mode,
                        primary_mgt=self.primary_mgt,
                        backup_mgt=self.backup_mgt,
                        primary_heartbeat=self.primary_heartbeat,
                        log_server_ref=self.log_server,
                        domain_server_address=self.domain_server_address,
                        default_nat=self.default_nat,
                        enable_antivirus=self.antivirus,
                        enable_gti=self.file_reputation,
                        location_ref=self.location,
                        snmp=self.snmp,
                        comment=self.comment)
                    
                    if self.check_mode:
                        return self.results
                    
                    engine = FirewallCluster.create_bulk(**cluster)
                    changed = True
                    
                else: # Engine exists, check for modifications
                    
                    # Changes made up to check mode are done on the
                    # cached instance of the engine and not sent to SMC
                    if self.update_general(engine):
                        changed = True
                    
                    if self.update_snmp(engine):
                        changed = True
                    
                    if self.cluster_mode and engine.cluster_mode != self.cluster_mode:
                        engine.data.update(cluster_mode=self.cluster_mode)
                        changed = True

                    if self.check_mode:
                        return self.results
                    
                    # Check engine location value
                    if self.update_location(engine):
                        changed = True
                    
                    # First actual engine update happens here
                    if changed:
                        engine.update()
                    
                    # Reset management interfaces before operating on interfaces
                    # in case interfaces are removed that might have previously
                    # been used as interface options (primary mgt, etc)
                    if self.reset_management(engine):
                        changed = True

                    # Set skip interfaces to bypass interface checks
                    if not self.skip_interfaces:
                        self.update_interfaces(engine)
                    
                    # Lastly, delete top level interfaces that are not defined in 
                    # the YAML or added while looping. Only delete if skip_interfaces
                    # was not provided and that delete_undefined_interfaces is set to True
                    if not self.skip_interfaces and self.delete_undefined_interfaces:
                        self.check_for_deletes(engine)
                
                ######                
                # Check for BGP configuration on either newly created engine
                # or on the existing
                ######
                if self.bgp:
                    bgp = engine.bgp
                    enabled = self.bgp.get('enabled', True)
                    if not enabled and bgp.status:
                        bgp.disable()
                        changed = True
                    
                    elif enabled:
                        
                        if self.update_bgp(bgp):

                            autonomous_system, created = get_or_create_asystem(
                                self.bgp.get('autonomous_system'))
                            
                            if created:
                                changed = True
                            
                            bgp.disable() # Reset BGP configuration
                            bgp.enable(
                                autonomous_system,
                                announced_networks=[],
                                antispoofing_networks=self.antispoofing_format(),
                                router_id=self.bgp.get('router_id', ''),
                                bgp_profile=self.cache.get('bgp_profile',
                                    self.bgp.get('bgp_profile', None)))
                            
                            for network in self.announced_network_format():
                                bgp.advertise_network(**network)
                            changed = True
                    
                    if changed:
                        engine.update()
                
                    if enabled:
                        # BGP Peering is last since the BGP configuration may be placed
                        # on interfaces that might have been modified or added. It is
                        # possible that this could fail 
                        peerings = self.bgp.get('bgp_peering', None)
                        if peerings:
                            for peer in peerings:
                                peering, created = get_or_create_bgp_peering(
                                    peer.pop('name'))
                                if created:
                                    changed = True
                                # Update the peering on the interface
                                if self.update_bgp_peering(engine, peering, peer):
                                    changed = True
                    
                if self.tags:
                    if self.add_tags(engine, self.tags):
                        changed = True
                else:
                    if self.clear_tags(engine):
                        changed = True

                self.results['engine'] = engine.data.data
                
            elif state == 'absent':
                if engine:
                    engine.delete()
                    changed = True
        
        except SMCException as err:
                self.fail(msg=str(err), exception=traceback.format_exc())
        
        if not changed and self.results.get('state'):
            changed = True
        self.results['changed'] = changed    
        return self.results
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)

        changed = False
        engine = self.fetch_element(Engine)

        if state == 'present':
            if not engine:
                # Find interface designated as management
                if not self.interfaces:
                    self.fail(msg='You must provide at least one interface '
                              'configuration to create a firewall.')

                if not self.primary_mgt:
                    self.fail(
                        msg='You must provide a primary_mgt interface to create '
                        'an engine.')

                if not self.type:
                    self.fail(
                        msg='You must specify an engine by type when creating a '
                        'new engine. Types: %s' % engine_types())

                if 'fw_cluster' in self.type and not self.cluster_mode:
                    self.fail(
                        msg='You must define a cluster mode to create an engine'
                    )

                itf = self.check_interfaces()

                # Management interface
                if not self.primary_mgt in itf:
                    self.fail(
                        msg=
                        'Management interface is not defined. Management was '
                        'specified on interface: %s' % self.primary_mgt)

            else:
                self.type = engine.type
                if self.interfaces and not self.skip_interfaces:
                    itf = self.check_interfaces()
                else:
                    itf = []

            cache = Cache()

            # SNMP settings
            if self.snmp and self.snmp.get('enabled', True):
                cache._add_entry('snmp_agent',
                                 self.snmp.get('snmp_agent', None))
                if cache.missing:
                    self.fail(
                        msg=
                        'SNMP configured but the SNMP Agent specified is not '
                        'found: %s' % cache.missing)

            # Only validate BGP if it's specifically set to enabled
            if self.bgp and self.bgp.get('enabled', True):
                # BGP Profile if specified
                if self.bgp.get('bgp_profile', None):
                    cache._add_entry('bgp_profile', self.bgp['bgp_profile'])
                    if cache.missing:
                        self.fail(
                            msg=
                            'A BGP Profile was specified that does not exist: '
                            '%s' % self.bgp['bgp_profile'])

                # Get external bgp peers, can be type 'engine' or 'external_bgp_peer'
                # Can also be empty if you don't want to attach a peer.
                peerings = self.bgp.get('bgp_peering', [])
                for peer in peerings:
                    if 'name' not in peer or 'interface_id' not in peer:
                        self.fail(
                            msg=
                            'BGP Peering requires a name and interface_id for the '
                            'BGP Peering element. Info provided: %s' % peer)
                    # The specified interface ID must exist for the BGP Peering to succeed. If
                    # the interface is defined in yaml, we'll assume it will be created. If the
                    # engine exists, check if it's defined or if it already exists
                    peer_id = str(peer['interface_id'])
                    if peer_id not in itf and not engine:
                        self.fail(
                            msg=
                            'Interface ID: %s specified for BGP Peering does not '
                            'exist. You must specify a valid interface to bind the peer '
                            % peer_id)
                    elif engine and (peer_id not in engine.interface
                                     and peer_id not in itf):
                        self.fail(
                            msg=
                            'BGP Peering interface id: %s specified does not exist '
                            'on the current engine: %s' %
                            (peer_id, engine.name))
                    if 'external_bgp_peer' not in peer and 'engine' not in peer:
                        self.fail(
                            msg=
                            'Missing the external_bgp_peer or engine parameter '
                            'which defines the next hop for the BGP Peering')
                    if 'external_bgp_peer' in peer:
                        cache._add_entry('external_bgp_peer',
                                         peer['external_bgp_peer'])
                    elif 'engine' in peer:
                        cache._add_entry('fw_cluster', peer['engine'])

                if cache.missing:
                    self.fail(msg='Missing external BGP Peering elements: %s' %
                              cache.missing)

                as_system = self.bgp.get('autonomous_system', {})
                if not engine:
                    # We are trying to enable BGP on a new engine, Autonomous System
                    # is required
                    if not as_system:
                        self.fail(
                            msg=
                            'You must specify an Autonomous System when enabling '
                            'BGP on a newly created engine.')
                if as_system:
                    if 'name' not in as_system or 'as_number' not in as_system:
                        self.fail(
                            msg='Autonomous System requires a name and and '
                            'as_number value.')

                spoofing = self.bgp.get('antispoofing_network', {})
                self.validate_antispoofing_network(spoofing)
                cache.add(spoofing)
                if cache.missing:
                    self.fail(
                        msg='Missing elements in antispoofing configuration: %s'
                        % cache.missing)

                networks = self.bgp.get('announced_network', [])
                announced_networks = self.validate_and_extract_announced(
                    networks)
                cache.add(announced_networks)
                if cache.missing:
                    self.fail(
                        msg='Missing elements in announced configuration: %s' %
                        cache.missing)

            if self.netlinks:
                # Netlinks can be specified on an interface along with destination elements
                # 'behind' these netlinks. Netlinks can only be placed on physical interface
                # types and not tunnel interfaces
                for netlink in self.netlinks:
                    if 'name' not in netlink or 'interface_id' not in netlink:
                        self.fail(
                            msg=
                            'Netlink requires a name and interface_id for the '
                            'Netlink element. Info provided: %s' % netlink)
                    int_id = str(netlink['interface_id'])
                    if int_id not in itf and not engine:
                        self.fail(
                            msg=
                            'Interface ID: %s specified for netlink does not '
                            'exist. You must specify a valid interface to bind the netlink'
                            % int_id)
                    elif engine and (int_id not in engine.physical_interface
                                     and int_id not in itf):
                        self.fail(
                            msg=
                            'Netlink interface id: %s specified does not exist '
                            'on the current engine: %s' %
                            (int_id, engine.name))

                    # Get required elements specified for configuration
                    cache._add_entry('netlink', netlink['name'])
                    # Destination elements for netlink are optional
                    if netlink.get('destination', []) and isinstance(
                            netlink['destination'], list):
                        for dest in netlink['destination']:
                            if 'name' not in dest or 'type' not in dest:
                                self.fail(
                                    msg=
                                    'Netlink destination element reference must '
                                    'contain name and type key values. Provided: %s'
                                    % dest)
                            cache._add_entry(dest['type'], dest['name'])
                if cache.missing:
                    self.fail(
                        msg='Missing elements in netlink configuration: %s' %
                        cache.missing)

            self.cache = cache

        try:

            if state == 'present':
                if not engine:

                    interfaces = [vars(intf) for intf in itf]

                    firewall = {'interfaces': interfaces}
                    firewall.update(
                        name=self.name,
                        primary_mgt=self.primary_mgt,
                        backup_mgt=self.backup_mgt,
                        log_server_ref=self.log_server,
                        domain_server_address=self.domain_server_address,
                        default_nat=self.default_nat,
                        enable_antivirus=self.antivirus,
                        enable_gti=self.file_reputation,
                        location_ref=self.location,
                        snmp=self.snmp,
                        comment=self.comment)

                    if self.check_mode:
                        return self.results

                    if 'fw_cluster' in self.type:
                        firewall.update(
                            cluster_mode=self.cluster_mode,
                            primary_heartbeat=self.primary_heartbeat)

                        engine = FirewallCluster.create_bulk(**firewall)
                    else:
                        engine = Layer3Firewall.create_bulk(**firewall)

                    self.results['state'].append({
                        'name': engine.name,
                        'type': engine.type,
                        'action': 'created'
                    })
                    changed = True

                else:  # Engine exists, check for modifications

                    # Changes made up to check mode are done on the
                    # cached instance of the engine and not sent to SMC
                    if self.update_general(engine):
                        changed = True

                    if self.update_snmp(engine):
                        changed = True

                    if 'fw_cluster' in self.type and \
                        (self.cluster_mode and engine.cluster_mode != self.cluster_mode):
                        engine.data.update(cluster_mode=self.cluster_mode)
                        changed = True

                    if self.check_mode:
                        return self.results

                    # Check engine location value
                    if self.update_location(engine):
                        changed = True

                    # First actual engine update happens here
                    if changed:
                        engine.update()

                    # Reset management interfaces before operating on interfaces
                    # in case interfaces are removed that might have previously
                    # been used as interface options (primary mgt, etc)
                    if self.reset_management(engine):
                        changed = True

                    # Set skip interfaces to bypass interface checks
                    if not self.skip_interfaces:
                        self.update_interfaces(engine)

                    # Lastly, delete top level interfaces that are not defined in
                    # the YAML or added while looping. Only delete if skip_interfaces
                    # was not provided and that delete_undefined_interfaces is set to True
                    if not self.skip_interfaces and self.delete_undefined_interfaces:
                        self.check_for_deletes(engine)

                ######
                # Check for BGP configuration on either newly created engine
                # or on the existing
                ######
                if self.bgp:
                    bgp = engine.bgp
                    enabled = self.bgp.get('enabled', True)
                    if not enabled and bgp.status:
                        bgp.disable()
                        changed = True

                    elif enabled:

                        if self.update_bgp(bgp):

                            autonomous_system, created = get_or_create_asystem(
                                self.bgp.get('autonomous_system'))

                            if created:
                                changed = True

                            bgp.disable()  # Reset BGP configuration
                            bgp.enable(autonomous_system,
                                       announced_networks=[],
                                       antispoofing_networks=self.
                                       antispoofing_format(),
                                       router_id=self.bgp.get('router_id', ''),
                                       bgp_profile=self.cache.get(
                                           'bgp_profile',
                                           self.bgp.get('bgp_profile', None)))

                            for network in self.announced_network_format():
                                bgp.advertise_network(**network)
                            changed = True

                    if changed:
                        engine.update()

                    if enabled:
                        # BGP Peering is last since the BGP configuration may be placed
                        # on interfaces that might have been modified or added.
                        peerings = self.bgp.get('bgp_peering', None)
                        if peerings:
                            for peer in peerings:
                                peering, created = get_or_create_bgp_peering(
                                    peer.pop('name'))
                                if created:
                                    changed = True
                                # Update the peering on the interface
                                if self.update_bgp_peering(
                                        engine, peering, peer):
                                    changed = True

                if self.netlinks:
                    if self.update_netlinks(engine):
                        changed = True

                if self.tags:
                    if self.add_tags(engine, self.tags):
                        changed = True
                else:
                    if self.clear_tags(engine):
                        changed = True

            elif state == 'absent':
                if engine:
                    engine.delete()
                    self.results['state'].append({
                        'name': engine.name,
                        'type': engine.type,
                        'action': 'deleted'
                    })
                    changed = True

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())

        if not changed and self.results.get('state'):
            changed = True
        self.results['changed'] = changed
        return self.results
Beispiel #5
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(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()
                    action.action = rule.get('action', 'allow')

                    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
Beispiel #6
0
class FirewallRule(StonesoftModuleBase):
    def __init__(self):

        self.module_args = dict(policy=dict(type='str'),
                                sub_policy=dict(type='str'),
                                template=dict(type='str'),
                                rules=dict(type='list', default=[]),
                                inspection_policy=dict(type='str'),
                                state=dict(default='present',
                                           type='str',
                                           choices=['present', 'absent']))

        self.policy = None
        self.sub_policy = None
        self.template = None
        self.rules = None
        self.inspection_policy = None
        self.use_search_hints = None

        mutually_exclusive = [
            ['policy', 'sub_policy'],
        ]

        required_one_of = [['policy', 'sub_policy']]

        self.results = dict(changed=False, state=[])

        super(FirewallRule,
              self).__init__(self.module_args,
                             mutually_exclusive=mutually_exclusive,
                             required_one_of=required_one_of,
                             supports_check_mode=True)

    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(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()
                    action.action = rule.get('action', 'allow')

                    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

    def rule_by_tag(self, policy, tag):
        """
        Get the rule referenced by it's tag. Tag will be in format
        '1234566.0'. When doing a search_rule, you must omit the part
        after the dot(.) to find the rule.
        
        :param FirewallPolicy policy: policy reference
        :param str tag: tag
        :rtype: Rule or None
        """
        resolved_tag = get_tag(tag)
        rule = policy.search_rule('@{}'.format(resolved_tag))
        if rule:
            return rule[0]

    def field_resolver(self, elements, types):
        """
        Field resolver, specific to retrieving network or service level
        elements in different formats. If elements are referencing existing
        elements, they will be loaded in the cache for retrieval.
        
        Format #1, as list (elements are expected to exist):
            - tcp_service:
                - service1
                - service2
        
        Format #2, as dict, only used for specifying any:
            any: true
        
        Format #3, if you have retrieved the rule and the sources, services,
        and destinations are in href format, pass through.
        
            - sources:
                - http://1.1.1.1/elements/host/1
                - http://1.1.1.1/elements/host/2
                ...
    
        .. note:: This is optimal if sources, destinations or services are
            not being changed as it will not result in queries to SMC. This
            is accomplished by not setting `expand` when running the facts
            module as_yaml.
            
        :param list elements: list of elements as parsed from YAML file
        :param dict type_dict: type dictionary for elements that should be
            supported for this run.
        """
        if isinstance(elements, dict):
            if 'any' in elements or 'none' in elements:
                return

            for name, value in elements.items():
                if name not in types:
                    self.fail(msg='Invalid element type specified: %s. Valid '
                              'types are: %s' % (name, list(types)))
                if not isinstance(value, list):
                    self.fail(
                        msg='Elements specified for type: %s should be in list '
                        'format, got: %s' % (name, type(value)))

            self.cache.add_many([elements])

        elif isinstance(elements, list):
            for entry in elements:
                if not entry.startswith('http'):
                    self.fail(
                        msg='List entry is expected to be the raw href of '
                        'the element. Received: %s' % entry)

    def get_value(self, typeof, element):
        """
        Get single value from cache
        
        :param str typeof: typeof element by key
        :param str element to fetch
        """
        return self.cache.get(typeof, element)

    def get_values(self, elements):
        """
        Get the values for source, destination and service cells. If these
        are not provided, return 'any'.
        """
        if not elements:
            return 'any'

        if isinstance(elements, dict):
            if 'any' in elements:
                return 'any'
            elif 'none' in elements:
                return None

            # Resolve out of cache, return as Element
            return [
                self.cache.get(typeof, value)
                for typeof, values in elements.items() for value in values
            ]

        elif isinstance(elements, list):
            return elements
Beispiel #7
0
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)

        ELEMENT_TYPES = element_type_dict()

        try:
            if state == 'present':
                deferred_elements = ('group', 'netlink')
                # Validate elements before proceeding.
                groups, netlinks = [], []
                for element in self.elements:
                    self.is_element_valid(element, ELEMENT_TYPES)
                    if 'group' in element:
                        groups.append(element)
                    elif 'netlink' in element:
                        netlinks.append(element)

                if groups or netlinks:
                    to_be_created = self.to_be_created_elements()
                    self.cache = Cache()

                if groups:
                    self.enum_group_members(groups, to_be_created)
                    if self.cache.missing:
                        self.fail(
                            msg=
                            'Group members referenced are missing and are not being '
                            'created in this playbook: %s' %
                            self.cache.missing)

                if netlinks:
                    self.enum_netlink_members(netlinks, to_be_created)
                    if self.cache.missing:
                        self.fail(
                            msg=
                            'Netlink elements referenced are missing and are not being '
                            'created in this playbook: %s' %
                            self.cache.missing)

                for element in self.elements:
                    for typeof, _ in element.items():
                        if typeof not in deferred_elements:
                            result = update_or_create(
                                element,
                                ELEMENT_TYPES,
                                check_mode=self.check_mode)
                            self.results['state'].append(result)

                for group in groups:
                    # Run through cache again, entries that exist will not be
                    # added twice but this captures elements that might have been
                    # added earlier by the playbook run
                    _group = copy.deepcopy(group)
                    members = _group.get('group', {}).get('members', {})
                    if members:
                        self.cache.add_many([members])
                        # Add to new members list
                        _members = [
                            self.cache.get(typeof, value)
                            for typeof, member in members.items()
                            for value in member
                        ]
                    else:  # No members defined
                        _members = []

                    _group.setdefault('group', {}).update(members=_members)

                    result = update_or_create(_group,
                                              ELEMENT_TYPES,
                                              check_mode=self.check_mode)
                    self.results['state'].append(result)

                for netlink in netlinks:
                    _netlink = copy.deepcopy(netlink)
                    gateway = _netlink.get('netlink', {}).get('gateway')
                    self.cache._add_entry(gateway.get('type'),
                                          gateway.get('name'))
                    _netlink.setdefault('netlink').update(
                        gateway=self.cache.get(gateway.get('type'),
                                               gateway.get('name')))

                    # Update networks
                    networks = _netlink.get('netlink').get('network')
                    for net in networks:
                        self.cache._add_entry('network', net)
                    _netlink.setdefault('netlink').update(network=[
                        self.cache.get('network', net) for net in networks
                    ])

                    result = update_or_create(_netlink,
                                              ELEMENT_TYPES,
                                              check_mode=self.check_mode)
                    self.results['state'].append(result)

                if self.check_mode:
                    return self.results

            else:
                for element in self.elements:
                    for typeof in element:
                        if typeof not in ELEMENT_TYPES:
                            self.fail(
                                msg=
                                'Element specified is not valid, got: {}, valid: {}'
                                .format(typeof, ELEMENT_TYPES.keys()))
                        else:
                            if not self.check_mode:
                                for elements in element[typeof]:
                                    result = delete_element(
                                        ELEMENT_TYPES.get(typeof)['type'](
                                            elements),
                                        self.ignore_err_if_not_found)
                                    self.results['state'].append(result)

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())

        for results in self.results['state']:
            if 'action' in results:
                self.results['changed'] = True
                break
        return self.results
Beispiel #8
0
class NetworkElement(StonesoftModuleBase):
    def __init__(self):

        self.module_args = dict(elements=dict(type='list', required=True),
                                ignore_err_if_not_found=dict(type='bool',
                                                             default=True),
                                state=dict(default='present',
                                           type='str',
                                           choices=['present', 'absent']))

        self.elements = None
        self.ignore_err_if_not_found = None

        self.results = dict(changed=False, state=[])
        super(NetworkElement, self).__init__(self.module_args,
                                             supports_check_mode=True)

    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)

        ELEMENT_TYPES = element_type_dict()

        try:
            if state == 'present':
                deferred_elements = ('group', 'netlink')
                # Validate elements before proceeding.
                groups, netlinks = [], []
                for element in self.elements:
                    self.is_element_valid(element, ELEMENT_TYPES)
                    if 'group' in element:
                        groups.append(element)
                    elif 'netlink' in element:
                        netlinks.append(element)

                if groups or netlinks:
                    to_be_created = self.to_be_created_elements()
                    self.cache = Cache()

                if groups:
                    self.enum_group_members(groups, to_be_created)
                    if self.cache.missing:
                        self.fail(
                            msg=
                            'Group members referenced are missing and are not being '
                            'created in this playbook: %s' %
                            self.cache.missing)

                if netlinks:
                    self.enum_netlink_members(netlinks, to_be_created)
                    if self.cache.missing:
                        self.fail(
                            msg=
                            'Netlink elements referenced are missing and are not being '
                            'created in this playbook: %s' %
                            self.cache.missing)

                for element in self.elements:
                    for typeof, _ in element.items():
                        if typeof not in deferred_elements:
                            result = update_or_create(
                                element,
                                ELEMENT_TYPES,
                                check_mode=self.check_mode)
                            self.results['state'].append(result)

                for group in groups:
                    # Run through cache again, entries that exist will not be
                    # added twice but this captures elements that might have been
                    # added earlier by the playbook run
                    _group = copy.deepcopy(group)
                    members = _group.get('group', {}).get('members', {})
                    if members:
                        self.cache.add_many([members])
                        # Add to new members list
                        _members = [
                            self.cache.get(typeof, value)
                            for typeof, member in members.items()
                            for value in member
                        ]
                    else:  # No members defined
                        _members = []

                    _group.setdefault('group', {}).update(members=_members)

                    result = update_or_create(_group,
                                              ELEMENT_TYPES,
                                              check_mode=self.check_mode)
                    self.results['state'].append(result)

                for netlink in netlinks:
                    _netlink = copy.deepcopy(netlink)
                    gateway = _netlink.get('netlink', {}).get('gateway')
                    self.cache._add_entry(gateway.get('type'),
                                          gateway.get('name'))
                    _netlink.setdefault('netlink').update(
                        gateway=self.cache.get(gateway.get('type'),
                                               gateway.get('name')))

                    # Update networks
                    networks = _netlink.get('netlink').get('network')
                    for net in networks:
                        self.cache._add_entry('network', net)
                    _netlink.setdefault('netlink').update(network=[
                        self.cache.get('network', net) for net in networks
                    ])

                    result = update_or_create(_netlink,
                                              ELEMENT_TYPES,
                                              check_mode=self.check_mode)
                    self.results['state'].append(result)

                if self.check_mode:
                    return self.results

            else:
                for element in self.elements:
                    for typeof in element:
                        if typeof not in ELEMENT_TYPES:
                            self.fail(
                                msg=
                                'Element specified is not valid, got: {}, valid: {}'
                                .format(typeof, ELEMENT_TYPES.keys()))
                        else:
                            if not self.check_mode:
                                for elements in element[typeof]:
                                    result = delete_element(
                                        ELEMENT_TYPES.get(typeof)['type'](
                                            elements),
                                        self.ignore_err_if_not_found)
                                    self.results['state'].append(result)

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())

        for results in self.results['state']:
            if 'action' in results:
                self.results['changed'] = True
                break
        return self.results

    def to_be_created_elements(self):
        """
        Get a dict of all elements that are to be created by this playbook.
        This is used when nested elements are being created that have
        requirements on other elements. This allows nested elements to be
        created alongside of their dependency.
        
        :return: dict of element by type: set([names]) to be created
        :rtype: dict
        """
        nested_element = ('netlink', 'group')
        to_be_created = {
        }  # dict of element by type: set([names]) to be created.
        for element in self.elements:
            for typeof, values in element.items():
                if typeof not in nested_element:
                    to_be_created.setdefault(typeof,
                                             set()).add(values.get('name'))
        return to_be_created

    def enum_group_members(self, groups, pending_elements):
        """
        Check group membership. Groups reference only the type of element and
        the names of those members. If the element is being created, skip the
        existence check. If the member is not being created, attempt to fetch
        the member and save to cache. Return the cache. Check cache.missing
        before continuing to ensure all required elements are found.
        
        :param list groups: list of groups extracted from elements
        :param dict pending_elements: elements waiting to be created
        :return: None
        """
        for group in groups:
            members = group.get('group', {}).get('members', {})
            members = {} if members is None else members
            for typeof, member in members.items():
                for name in member:
                    if name not in pending_elements.get(typeof, set()):
                        self.cache._add_entry(typeof, name)

    def enum_netlink_members(self, netlinks, pending_elements):
        """
        Netlinks reference nested elements gateway and networks. Attempt to
        locate these either in definitions to be created by this playbook or
        existing already in SMC. Populate cache with href and name map and
        catch any missing before continuing.
        
        :return: None
        """
        for netlink in netlinks:
            values = netlink.get('netlink', [])
            for req in ('gateway', 'network'):
                if req not in values:
                    self.fail(
                        msg='Netlink requires a gateway and list of networks, '
                        'received: %s' % values)
            # Add requirements to cache
            gateway = values['gateway']
            if not isinstance(
                    gateway,
                    dict) or 'name' not in gateway or 'type' not in gateway:
                self.fail(
                    msg=
                    'Netlink gateway must be a dict with a name and type key value: %s'
                    % gateway)
            if gateway.get('type') not in ('engine', 'router'):
                self.fail(
                    msg=
                    'Netlink types can only be of type engine or router, got: %s'
                    % gateway.get('type'))

            networks = values['network']
            if not isinstance(networks, list):
                self.fail(
                    msg='Netlink networks must be defined as a list, got: %s' %
                    type(networks))

            if gateway.get('name') not in pending_elements.get(
                    gateway.get('type'), set()):
                self.cache._add_entry(gateway.get('type'), gateway.get('name'))

            for network in networks:
                if network not in pending_elements.get('network', set()):
                    self.cache._add_entry('network', network)
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)

        rbvpn = self.fetch_element(RouteVPN)
        changed = False

        if state == 'present':

            # Short circuit disable
            if rbvpn and self.enabled is not None and (rbvpn.enabled
                                                       and not self.enabled):
                rbvpn.disable()
                self.results['changed'] = True
                return self.results

            local_engine = self.get_managed_gateway(self.local_gw)
            local_tunnel_interface = self.get_tunnel_interface(
                local_engine, self.local_gw.get('tunnel_interface'))
            local_internal_endpoint = self.get_ipsec_endpoint(
                local_engine,
                self.local_gw.get('interface_id'),
                address=self.local_gw.get('address'))

            if self.remote_gw.get('type', None) != 'external_gateway':
                remote_engine = self.get_managed_gateway(self.remote_gw)
                remote_tunnel_interface = self.get_tunnel_interface(
                    remote_engine, self.remote_gw.get('tunnel_interface'))
                remote_internal_endpoint = self.get_ipsec_endpoint(
                    remote_engine,
                    self.remote_gw.get('interface_id'),
                    address=self.remote_gw.get('address'))
            else:
                # External Gateway
                req = ('name', 'preshared_key', 'external_endpoint')
                for required in req:
                    if required not in self.remote_gw:
                        self.fail(
                            msg=
                            'Missing required field for the external endpoint '
                            'configuration: %s' % required)

                external_gateway = dict(name=self.remote_gw['name'])
                # External Endpoints are defined in the External Gateway.
                # Build the data structures for a call to ExternalGateway.update_or_create
                external_endpoint = []
                for endpoint in self.remote_gw['external_endpoint']:
                    if 'name' not in endpoint or 'address' not in endpoint:
                        self.fail(
                            msg='An external endpoint must have at least a '
                            'name and an address definition.')
                    external_endpoint.append(endpoint)
                external_gateway.update(external_endpoint=external_endpoint)

                # Verify specified VPN Sites exist before continuing
                if 'vpn_site' in self.remote_gw:
                    site_name = self.remote_gw.get('vpn_site',
                                                   {}).pop('name', None)
                    if not site_name:
                        self.fail(msg='A VPN site requires a name to continue')

                    # Get the elements
                    cache = Cache()
                    cache.add(self.remote_gw.get('vpn_site', {}))
                    if cache.missing:
                        self.fail(
                            msg='Could not find the specified elements for the '
                            'VPN site configuration: %s' % cache.missing)
                    site_element = [
                        value.href for _, values in cache.cache.items()
                        for value in values
                    ]
                    external_gateway.update(vpn_site=[
                        dict(name=site_name, site_element=site_element)
                    ])

        try:
            if state == 'present':

                if self.check_mode:
                    return self.results

                # Create the tunnel endpoints
                if not rbvpn:
                    local_gateway = TunnelEndpoint.create_ipsec_endpoint(
                        local_engine.vpn.internal_gateway,
                        local_tunnel_interface)

                    # Enable the IPSEC listener on specified interface/s
                    if self.update_ipsec_listener(local_internal_endpoint):
                        changed = True

                    is_external = self.remote_gw.get(
                        'type', None) == 'external_gateway'
                    if not is_external:
                        remote_gateway = TunnelEndpoint.create_ipsec_endpoint(
                            remote_engine.vpn.internal_gateway,
                            remote_tunnel_interface)

                        if self.update_ipsec_listener(
                                remote_internal_endpoint):
                            changed = True

                    else:  # Update or Create
                        gw, updated, created = ExternalGateway.update_or_create(
                            with_status=True, **external_gateway)
                        remote_gateway = TunnelEndpoint.create_ipsec_endpoint(
                            gw)
                        if created or updated:
                            changed = True

                    vpn = dict(name=self.name,
                               local_endpoint=local_gateway,
                               remote_endpoint=remote_gateway)

                    if is_external:
                        vpn.update(
                            preshared_key=self.remote_gw['preshared_key'])

                    rbvpn = RouteVPN.create_ipsec_tunnel(**vpn)
                    changed = True

                else:
                    #TODO: Update or create from top level RBVPN
                    #rbvpn.update_or_create()

                    if rbvpn and self.enabled is not None and (
                            not rbvpn.enabled and self.enabled):
                        rbvpn.enable()
                        changed = True

                    if self.remote_gw.get('type') == 'external_gateway':
                        gw, updated, created = ExternalGateway.update_or_create(
                            with_status=True, **external_gateway)

                        if updated or created:
                            changed = True

                self.results['state'] = rbvpn.data.data
                self.results['changed'] = changed

            elif state == 'absent':
                if rbvpn:
                    rbvpn.delete()
                    changed = True

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())

        self.results['changed'] = changed
        return self.results
Beispiel #10
0
    def exec_module(self, **kwargs):
        state = kwargs.pop('state', 'present')
        for name, value in kwargs.items():
            setattr(self, name, value)

        changed = False

        if state == 'present':
            external_gateway = {'name': self.name}

            # External Endpoints are defined in the External Gateway.
            # Build the data structures for a call to ExternalGateway.update_or_create
            external_endpoint = []
            for endpoint in self.external_endpoint:
                if 'name' not in endpoint or 'address' not in endpoint:
                    self.fail(msg='An external endpoint must have at least a '
                              'name and an address definition.')
                external_endpoint.append(endpoint)
            external_gateway.update(external_endpoint=external_endpoint)

            if self.vpn_site:
                site_name = self.vpn_site.pop('name', None)
                if not site_name:
                    self.fail(msg='VPN site requires a name attribute')

                cache = Cache()
                cache.add(self.vpn_site)
                if cache.missing:
                    self.fail(
                        msg='Could not find the specified elements for the '
                        'VPN site configuration: %s' % cache.missing)

                site_element = [
                    value.href for _, values in cache.cache.items()
                    for value in values
                ]
                external_gateway.update(
                    vpn_site=[dict(name=site_name, site_element=site_element)])

        try:
            if state == 'present':

                gateway, updated, created = ExternalGateway.update_or_create(
                    with_status=True, **external_gateway)

                if created or updated:
                    self.results['state'].append({
                        'name':
                        gateway.name,
                        'type':
                        gateway.typeof,
                        'action':
                        'created' if created else 'modified'
                    })
                    changed = True

                if self.tags:
                    if self.add_tags(gateway, self.tags):
                        changed = True

            elif state == 'absent':
                result = delete_element(ExternalGateway(self.name),
                                        self.ignore_err_if_not_found)

                if 'action' in result:
                    changed = True
                self.results['state'].append(result)

        except SMCException as err:
            self.fail(msg=str(err), exception=traceback.format_exc())

        self.results['changed'] = changed
        return self.results