예제 #1
0
    def is_ip_or_alias(self, address):
        """ return True if address is an ip or an alias """
        # Is it an alias?
        if (self.find_alias(address, 'host') is not None
                or self.find_alias(address, 'network') is not None
                or self.find_alias(address, 'urltable') is not None
                or self.find_alias(address, 'urltable_ports') is not None):
            return True

        # Is it an IP address?
        try:
            ip_address(u'{0}'.format(address))
            return True
        except ValueError:
            pass

        # Is it an IP network?
        try:
            ip_network(u'{0}'.format(address))
            return True
        except ValueError:
            pass

        # None of the above
        return False
예제 #2
0
    def _check_overlaps(self, ipfield, netfield):
        """ check new address does not overlaps with one existing """

        if not self.obj.get(ipfield) or self.obj.get(netfield) is None:
            return

        our_addr = ip_network(u'{0}/{1}'.format(self.obj[ipfield],
                                                self.obj[netfield]),
                              strict=False)

        for iface in self.root_elt:
            if iface == self.target_elt:
                continue

            ipaddr_elt = iface.find(ipfield)
            subnet_elt = iface.find(netfield)
            if ipaddr_elt is None or subnet_elt is None or ipaddr_elt.text in [
                    'dhcp', None
            ] or ipaddr_elt.text in ['dhcpv6', None]:
                continue

            other_addr = ip_network(u'{0}/{1}'.format(ipaddr_elt.text,
                                                      subnet_elt.text),
                                    strict=False)
            if our_addr.overlaps(other_addr):
                descr_elt = iface.find('descr')
                if descr_elt is not None and descr_elt.text:
                    ifname = descr_elt.text
                else:
                    ifname = iface.tag
                msg = 'IP address {0}/{1} is being used by or overlaps with: {2} ({3}/{4})'.format(
                    self.obj[ipfield], self.obj[netfield], ifname,
                    ipaddr_elt.text, subnet_elt.text)
                self.module.fail_json(msg=msg)
예제 #3
0
    def _check_overlaps(self, interface, interface_elt):
        """ check new address does not overlaps with one existing """

        if not interface.get('ipaddr'):
            return

        our_addr = ip_network(u'{0}/{1}'.format(interface['ipaddr'], interface['subnet']), strict=False)

        for iface in self.interfaces:
            if iface == interface_elt:
                continue

            ipaddr_elt = iface.find('ipaddr')
            subnet_elt = iface.find('subnet')
            if ipaddr_elt is None or subnet_elt is None:
                continue

            other_addr = ip_network(u'{0}/{1}'.format(ipaddr_elt.text, subnet_elt.text), strict=False)
            if our_addr.overlaps(other_addr):
                descr_elt = iface.find('descr')
                if descr_elt is not None and descr_elt.text:
                    ifname = descr_elt.text
                else:
                    ifname = iface.tag
                msg = 'IPv4 address {0}/{1} is being used by or overlaps with: {2} ({3}/{4})'.format(
                    interface['ipaddr'],
                    interface['subnet'],
                    ifname,
                    ipaddr_elt.text,
                    subnet_elt.text
                )
                self.module.fail_json(msg=msg)
예제 #4
0
 def is_ip_network(address, strict=True):
     """ test if address is a valid ip network """
     try:
         ip_network(u'{0}'.format(address), strict=strict)
         return True
     except ValueError:
         pass
     return False
 def normalize(self):
     """Normalizes a CIDR descriptor, e.g. 1.2.3.4/5 == 0.0.0.0/5."""
     # ipaddress is picky and needs inputs to be unicode, i.e. not bytes==str in py2
     normalized_cidr = ipaddress.ip_network(six.u(self.cidr),
                                            strict=False).compressed
     return self.__class__(cidr=normalized_cidr,
                           description=self.description)
예제 #6
0
def is_ipv6_network(address, strict=True):
    """ test if address is a valid ipv6 network """
    try:
        addr = ip_network(u'{0}'.format(address), strict=strict)
        return isinstance(addr, IPv6Network)
    except ValueError:
        pass
    return False
예제 #7
0
def _search_prefix(nb_endpoint, data):
    if data.get("prefix"):
        prefix = ipaddress.ip_network(data["prefix"])
    elif data.get("parent"):
        prefix = ipaddress.ip_network(data["parent"])

    network = to_text(prefix.network_address)
    mask = prefix.prefixlen

    if data.get("vrf"):
        if not isinstance(data["vrf"], int):
            raise ValueError("%s does not exist - Please create VRF" % (data["vrf"]))
        else:
            prefix = nb_endpoint.get(q=network, mask_length=mask, vrf_id=data["vrf"])
    else:
        prefix = nb_endpoint.get(q=network, mask_length=mask, vrf="null")

    return prefix
    def check_params(self):
        rules_by_host = {}
        for host in self.hosts:
            rules_by_host[host.name] = self.firewall_facts[host.name].keys()

        for rule_option in self.rule_options:
            rule_name = rule_option.get('name')
            if rule_name is None:
                self.module.fail_json(
                    msg="Please specify rule.name for rule set"
                    " as it is required parameter.")
            hosts_with_rule_name = [
                h for h, r in rules_by_host.items() if rule_name in r
            ]
            hosts_without_rule_name = set([i.name for i in self.hosts
                                           ]) - set(hosts_with_rule_name)
            if hosts_without_rule_name:
                self.module.fail_json(
                    msg="rule named '%s' wasn't found on hosts: %s" %
                    (rule_name, hosts_without_rule_name))

            if 'enabled' not in rule_option:
                self.module.fail_json(
                    msg="Please specify rules.enabled for rule set"
                    " %s as it is required parameter." % rule_name)

            allowed_hosts = rule_option.get('allowed_hosts', {})
            ip_addresses = allowed_hosts.get('ip_address', [])
            ip_networks = allowed_hosts.get('ip_network', [])
            for ip_address in ip_addresses:
                try:
                    ipaddress.ip_address(ip_address)
                except ValueError:
                    self.module.fail_json(
                        msg="The provided IP address %s is not a valid IP"
                        " for the rule %s" % (ip_address, rule_name))

            for ip_network in ip_networks:
                try:
                    ipaddress.ip_network(ip_network)
                except ValueError:
                    self.module.fail_json(
                        msg="The provided IP network %s is not a valid network"
                        " for the rule %s" % (ip_network, rule_name))
예제 #9
0
    def _check_subnet(self):
        """ check if addr lies into interface subnets """
        def _check_vips():
            virtualips = self.pfsense.get_element('virtualip')
            if virtualips is None:
                return False

            for vip_elt in virtualips:
                if vip_elt.find(
                        'interface'
                ).text != self.interface_elt.tag or vip_elt.find(
                        'mode').text != 'other' or vip_elt.find(
                            'type').text != 'network':
                    continue

                subnet = ip_network(u'{0}/{1}'.format(
                    vip_elt.find('subnet').text,
                    vip_elt.find('subnet_bits').text),
                                    strict=False)
                if addr in subnet:
                    return True
            return False

        if self.params['ipprotocol'] == 'inet':
            inet_type = 'IPv4'
            f1_elt = self.interface_elt.find('ipaddr')
            f2_elt = self.interface_elt.find('subnet')
        else:
            inet_type = 'IPv6'
            f1_elt = self.interface_elt.find('ipaddrv6')
            f2_elt = self.interface_elt.find('subnetv6')
        if f1_elt is None or f1_elt.text is None or f2_elt is None or f2_elt.text is None:
            self.module.fail_json(
                msg=
                'Cannot add {0} Gateway Address because no {0} address could be found on the interface.'
                .format(inet_type))

        try:
            if self.params['nonlocalgateway']:
                return

            addr = ip_address(u'{0}'.format(self.params['gateway']))
            subnet = ip_network(u'{0}/{1}'.format(f1_elt.text, f2_elt.text),
                                strict=False)
            if addr in subnet or _check_vips():
                return

            self.module.fail_json(
                msg=
                "The gateway address {0} does not lie within one of the chosen interface's subnets."
                .format(self.params['gateway']))
        except ValueError:
            self.module.fail_json(
                msg=
                'Cannot add {0} Gateway Address because no {0} address could be found on the interface.'
                .format(inet_type))
예제 #10
0
        def _check_vips():
            virtualips = self.pfsense.get_element('virtualip')
            if virtualips is None:
                return False

            for vip_elt in virtualips:
                if vip_elt.find('interface').text != self.interface_elt.tag or vip_elt.find('mode').text != 'other' or vip_elt.find('type').text != 'network':
                    continue

                subnet = ip_network(u'{0}/{1}'.format(vip_elt.find('subnet').text, vip_elt.find('subnet_bits').text), strict=False)
                if addr in subnet:
                    return True
            return False
예제 #11
0
def map_config_to_obj(module):
    obj = []

    out = get_config(module, flags='| include ip route')
    for line in out.splitlines():
        # Split by whitespace but do not split quotes, needed for description
        splitted_line = findall(r'[^"\s]\S*|".+?"', line)
        route = {}
        prefix_with_mask = splitted_line[2]
        prefix = None
        mask = None
        iface = None
        nhop = None
        if validate_ip_address(prefix_with_mask) is True:
            my_net = ipaddress.ip_network(prefix_with_mask)
            prefix = str(my_net.network_address)
            mask = str(my_net.netmask)
            route.update({
                'prefix': prefix,
                'mask': mask,
                'admin_distance': '1'
            })
        if splitted_line[3] is not None:
            if validate_ip_address(splitted_line[3]) is False:
                iface = str(splitted_line[3])
                route.update(interface=iface)
                if validate_ip_address(splitted_line[4]) is True:
                    nhop = str(splitted_line[4])
                    route.update(next_hop=nhop)
                    if splitted_line[5].isdigit():
                        route.update(admin_distance=str(splitted_line[5]))
                elif splitted_line[4].isdigit():
                    route.update(admin_distance=str(splitted_line[4]))
                else:
                    if splitted_line[6] is not None and splitted_line[
                            6].isdigit():
                        route.update(admin_distance=str(splitted_line[6]))
            else:
                nhop = str(splitted_line[3])
                route.update(next_hop=nhop)
                if splitted_line[4].isdigit():
                    route.update(admin_distance=str(splitted_line[4]))

        index = 0
        for word in splitted_line:
            if word in ('tag', 'description'):
                route.update(word=splitted_line[index + 1])
            index = index + 1
        obj.append(route)

    return obj
예제 #12
0
def parse_ip_network(address, strict=True, returns_ip=True):
    """ return cidr parts of address """
    try:
        addr = ip_network(u'{0}'.format(address), strict=strict)
        if strict or not returns_ip:
            return (str(addr.network_address), addr.prefixlen)
        else:
            # we parse the address with ipaddr just for type checking
            # but we use a regex to return the result as it dont kept the address bits
            group = re.match(r'(.*)/(.*)', address)
            if group:
                return (group.group(1), group.group(2))
    except ValueError:
        pass
    return None
예제 #13
0
def is_within_local_networks(self, address):
    """ test if address is contained in our local networks """
    networks = self.get_interfaces_networks()
    try:
        addr = ip_address(u'{0}'.format(address))
    except ValueError:
        return False

    for network in networks:
        try:
            net = ip_network(u'{0}'.format(network), strict=False)
            if addr in net:
                return True
        except ValueError:
            pass
    return False
예제 #14
0
def _get_prefix_id(nb_app, prefix, vrf_id=None):
    ipaddr_prefix = ipaddress.ip_network(prefix)
    network = to_text(ipaddr_prefix.network_address)
    mask = ipaddr_prefix.prefixlen

    prefix_query_params = {"prefix": network, "mask_length": mask}
    if vrf_id:
        prefix_query_params["vrf_id"] = vrf_id

    prefix_id = nb_app.prefixes.get(prefix_query_params)
    if not prefix_id:
        if vrf_id:
            raise ValueError(
                "Prefix %s does not exist in VRF %s - Please create it" %
                (prefix, vrf_id))
        else:
            raise ValueError("Prefix %s does not exist - Please create it" %
                             (prefix))

    return prefix_id
def main():
    argument_spec = scaleway_argument_spec()
    argument_spec.update(
        dict(
            state=dict(default='present', choices=['absent', 'present']),
            region=dict(required=True, choices=SCALEWAY_LOCATION.keys()),
            protocol=dict(required=True, choices=['TCP', 'UDP', 'ICMP']),
            port=dict(required=True, type=int),
            ip_range=dict(default='0.0.0.0/0',
                          type=lambda x: to_text(ip_network(to_text(x)))),
            direction=dict(required=True, choices=['inbound', 'outbound']),
            action=dict(required=True, choices=['accept', 'drop']),
            security_group=dict(required=True),
        ))
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    core(module)
def validate_ip_in_cidr(ip, cidr):
    address = ipaddress.ip_address(six.u(ip))
    network = ipaddress.ip_network(six.u(cidr), strict=False)
    if address not in network:
        raise errors.ValidationError("IP {0} not in subnet CIDR {1}.".format(
            ip, cidr))
예제 #17
0
    def ensure(self):
        """
        Function to ensure rule set configuration

        """
        fw_change_list = []
        enable_disable_changed = False
        allowed_ip_changed = False
        results = dict(changed=False, rule_set_state=dict())
        for host in self.hosts:
            firewall_system = host.configManager.firewallSystem
            if firewall_system is None:
                continue

            results['rule_set_state'][host.name] = dict()

            for rule_option in self.rule_options:
                rule_name = rule_option.get('name', None)
                if rule_name is None:
                    self.module.fail_json(
                        msg="Please specify rule.name for rule set"
                        " as it is required parameter.")
                if rule_name not in self.firewall_facts[host.name]:
                    self.module.fail_json(msg="rule named '%s' wasn't found." %
                                          rule_name)

                rule_enabled = rule_option.get('enabled', None)
                if rule_enabled is None:
                    self.module.fail_json(
                        msg="Please specify rules.enabled for rule set"
                        " %s as it is required parameter." % rule_name)

                # validate IP addresses are valid
                rule_config = rule_option.get('allowed_hosts', None)

                if 'ip_address' in rule_config[0].keys():
                    for ip_addr in rule_config[0]['ip_address']:
                        try:
                            ip = ipaddress.ip_address(ip_addr)
                        except ValueError:
                            self.module.fail_json(
                                msg=
                                "The provided IP address %s is not a valid IP"
                                " for the rule %s" % (ip_addr, rule_name))

                # validate provided subnets are valid networks
                if 'ip_network' in rule_config[0].keys():
                    for ip_net in rule_config[0]['ip_network']:
                        try:
                            network_validation = ipaddress.ip_network(ip_net)
                        except ValueError:
                            self.module.fail_json(
                                msg=
                                "The provided network %s is not a valid network"
                                " for the rule %s" % (ip_net, rule_name))

                current_rule_state = self.firewall_facts[
                    host.name][rule_name]['enabled']
                if current_rule_state != rule_enabled:
                    try:
                        if not self.module.check_mode:
                            if rule_enabled:
                                firewall_system.EnableRuleset(id=rule_name)
                            else:
                                firewall_system.DisableRuleset(id=rule_name)
                        # keep track of changes as we go
                        enable_disable_changed = True
                    except vim.fault.NotFound as not_found:
                        self.module.fail_json(
                            msg="Failed to enable rule set %s as"
                            " rule set id is unknown : %s" %
                            (rule_name, to_native(not_found.msg)))
                    except vim.fault.HostConfigFault as host_config_fault:
                        self.module.fail_json(
                            msg="Failed to enabled rule set %s as an internal"
                            " error happened while reconfiguring"
                            " rule set : %s" %
                            (rule_name, to_native(host_config_fault.msg)))

                # save variables here for comparison later and change tracking
                # also covers cases where inputs may be null
                permitted_networking = self.firewall_facts[
                    host.name][rule_name]
                rule_allows_all = permitted_networking['allowed_hosts'][
                    'all_ip']
                playbook_allows_all = rule_config[0]['all_ip']
                rule_allowed_ip = set(
                    permitted_networking['allowed_hosts']['ip_address'])
                playbook_allowed_ip = set(rule_config[0].get('ip_address', ''))
                rule_allowed_networks = set(
                    permitted_networking['allowed_hosts']['ip_network'])
                playbook_allowed_networks = set(rule_config[0].get(
                    'ip_network', ''))

                # compare what is configured on the firewall rule with what the playbook provides
                allowed_all_ips_different = bool(
                    rule_allows_all != playbook_allows_all)
                ip_list_different = bool(
                    rule_allowed_ip != playbook_allowed_ip)
                ip_network_different = bool(
                    rule_allowed_networks != playbook_allowed_networks)

                # apply everything here in one function call
                if allowed_all_ips_different is True or ip_list_different is True or ip_network_different is True:
                    try:
                        allowed_ip_changed = True
                        if not self.module.check_mode:
                            # setup spec
                            firewall_spec = vim.host.Ruleset.RulesetSpec()
                            firewall_spec.allowedHosts = vim.host.Ruleset.IpList(
                            )
                            firewall_spec.allowedHosts.allIp = rule_config[
                                0].get('all_ip', True)
                            firewall_spec.allowedHosts.ipAddress = rule_config[
                                0].get('ip_address', None)
                            firewall_spec.allowedHosts.ipNetwork = []

                            if 'ip_network' in rule_config[0].keys():
                                for allowed_network in rule_config[0].get(
                                        'ip_network', None):
                                    tmp_ip_network_spec = vim.host.Ruleset.IpNetwork(
                                    )
                                    tmp_ip_network_spec.network = allowed_network.split(
                                        "/")[0]
                                    tmp_ip_network_spec.prefixLength = int(
                                        allowed_network.split("/")[1])
                                    firewall_spec.allowedHosts.ipNetwork.append(
                                        tmp_ip_network_spec)

                            firewall_system.UpdateRuleset(id=rule_name,
                                                          spec=firewall_spec)
                    except vim.fault.NotFound as not_found:
                        self.module.fail_json(
                            msg="Failed to configure rule set %s as"
                            " rule set id is unknown : %s" %
                            (rule_name, to_native(not_found.msg)))
                    except vim.fault.HostConfigFault as host_config_fault:
                        self.module.fail_json(
                            msg="Failed to configure rule set %s as an internal"
                            " error happened while reconfiguring"
                            " rule set : %s" %
                            (rule_name, to_native(host_config_fault.msg)))
                    except vim.fault.RuntimeFault as runtime_fault:
                        self.module.fail_json(
                            msg=
                            "Failed to configure the rule set %s as a runtime"
                            " error happened while applying the reconfiguration:"
                            " %s" % (rule_name, to_native(runtime_fault.msg)))

                results['rule_set_state'][host.name][rule_name] = dict(
                    current_state=rule_enabled,
                    previous_state=current_rule_state,
                    desired_state=rule_enabled,
                    current_allowed_all=playbook_allows_all,
                    previous_allowed_all=permitted_networking['allowed_hosts']
                    ['all_ip'],
                    desired_allowed_all=playbook_allows_all,
                    current_allowed_ip=playbook_allowed_ip,
                    previous_allowed_ip=set(
                        permitted_networking['allowed_hosts']['ip_address']),
                    desired_allowed_ip=playbook_allowed_ip,
                    current_allowed_networks=playbook_allowed_networks,
                    previous_allowed_networks=set(
                        permitted_networking['allowed_hosts']['ip_network']),
                    desired_allowed_networks=playbook_allowed_networks)

        if enable_disable_changed or allowed_ip_changed:
            fw_change_list.append(True)

        if any(fw_change_list):
            results['changed'] = True
        self.module.exit_json(**results)
예제 #18
0
    def run(self):
        """
        This function should have all necessary code for endpoints within the application
        to create/update/delete the endpoint objects
        Supported endpoints:
        - aggregates
        - ipam_roles
        - ip_addresses
        - prefixes
        - rirs
        - vlans
        - vlan_groups
        - vrfs
        """
        # Used to dynamically set key when returning results
        endpoint_name = ENDPOINT_NAME_MAPPING[self.endpoint]

        self.result = {"changed": False}

        application = self._find_app(self.endpoint)
        nb_app = getattr(self.nb, application)
        nb_endpoint = getattr(nb_app, self.endpoint)

        data = self.data

        if self.endpoint == "ip_addresses":
            if data.get("address"):
                try:
                    data["address"] = to_text(
                        ipaddress.ip_network(data["address"]))
                except ValueError:
                    pass
            name = data.get("address")
        elif self.endpoint in ["aggregates", "prefixes"]:
            name = data.get("prefix")
        else:
            name = data.get("name")

        if self.endpoint in SLUG_REQUIRED:
            if not data.get("slug"):
                data["slug"] = self._to_slug(name)

        if self.module.params.get("first_available"):
            first_available = True
        else:
            first_available = False

        object_query_params = self._build_query_params(endpoint_name, data)
        if data.get("prefix") and self.endpoint == "ip_addresses":
            object_query_params = self._build_query_params("prefix", data)
            self.nb_object = self._nb_endpoint_get(nb_app.prefixes,
                                                   object_query_params, name)
        else:
            self.nb_object = self._nb_endpoint_get(nb_endpoint,
                                                   object_query_params, name)

        if self.state in ("new", "present") and endpoint_name == "ip_address":
            self._handle_state_new_present(nb_app, nb_endpoint, endpoint_name,
                                           name, data)
        elif self.state == "present" and first_available and data.get(
                "parent"):
            self._get_new_available_prefix(data, endpoint_name)
        elif self.state == "present":
            self._ensure_object_exists(nb_endpoint, endpoint_name, name, data)
        elif self.state == "absent":
            self._ensure_object_absent(endpoint_name, name)

        try:
            serialized_object = self.nb_object.serialize()
        except AttributeError:
            serialized_object = self.nb_object

        self.result.update({endpoint_name: serialized_object})

        self.module.exit_json(**self.result)