def allowed_addresses(self): if self._values['allowed_addresses'] is None: return None result = [] addresses = self._values['allowed_addresses'] if isinstance(addresses, string_types): if addresses in ['', 'none']: return [] else: addresses = [addresses] if len(addresses) == 1 and addresses[0] in ['default', '']: result = ['127.0.0.0/8'] return result for address in addresses: try: # Check for valid IPv4 or IPv6 entries ip_network(u'%s' % str(address)) result.append(address) except ValueError: # else fallback to checking reasonably well formatted hostnames if is_valid_hostname(address): result.append(str(address)) continue raise F5ModuleError( "The provided 'allowed_address' value {0} is not a valid IP or hostname" .format(address)) result = list(set(result)) result.sort() return result
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)
def netmask(self): if self._values['netmask'] is None: return None try: result = int(self._values['netmask']) # CIDRs between 0 and 128 are allowed if 0 <= result <= 128: return result else: raise F5ModuleError( "The provided netmask must be between 0 and 32 for IPv4, or " "0 and 128 for IPv6.") except ValueError: # not a number, but that's ok. Further processing necessary pass if not is_valid_ip(self._values['netmask']): raise F5ModuleError( 'The provided netmask {0} is neither in IP or CIDR format'. format(result)) # Create a temporary address to check if the netmask IP is v4 or v6 addr = ip_address(u'{0}'.format(str(self._values['netmask']))) if addr.version == 4: # Create a more real v4 address using a wildcard, so that we can determine # the CIDR value from it. ip = ip_network(u'0.0.0.0/%s' % str(self._values['netmask'])) result = ip.prefixlen else: result = ipv6_netmask_to_cidr(self._values['netmask']) return result
def _convert_address(self, item): if item == '0.0.0.0/0': return 'any', None result = ip_network(u'{0}'.format(item)) if result.prefixlen == 32: return str(result.network_address), None else: return str(result.network_address), str(result.netmask)
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
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))
def network(self): if self._values['network'] is None: return None if self._values['network'] == 'default': return 'default' try: addr = ip_network(u"{0}".format(str(self._values['network']))) return str(addr) except ValueError: raise F5ModuleError( "The 'network' must either be a network address (with CIDR) or the word 'default'." )
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
def destination_ip(self): if self._values['destination'] is None: return None destination = self.destination_to_network() try: pattern = r'(?P<rd>%[0-9]+)' addr = re.sub(pattern, '', destination) ip = ip_network(u'%s' % str(addr)) return '{0}/{1}'.format(str(ip.network_address), ip.prefixlen) except ValueError: raise F5ModuleError( "The provided destination is not an IP address.")
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
def _convert_netmask(self, item): result = -1 try: result = int(item) if 0 < result < 256: pass except ValueError: if is_valid_ip(item): ip = ip_network(u'0.0.0.0/%s' % str(item)) result = ip.prefixlen if result < 0: raise F5ModuleError( 'The provided netmask {0} is neither in IP or CIDR format'.format(result) ) return result
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
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
def destination(self): if self._values['destination'] is None: return None if self._values['destination'].startswith('default'): self._values['destination'] = '0.0.0.0/0' if self._values['destination'].startswith('default-inet6'): self._values['destination'] = '::/0' try: ip = ip_network(u'%s' % str(self.destination_ip)) if self.route_domain: return '{0}%{1}/{2}'.format(str(ip.network_address), self.route_domain, ip.prefixlen) else: return '{0}/{1}'.format(str(ip.network_address), ip.prefixlen) except ValueError: raise F5ModuleError( "The provided destination is not an IP address")
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 netmask(self): if self._values['netmask'] is None: return None result = -1 try: result = int(self._values['netmask']) if 0 < result < 256: pass except ValueError: if is_valid_ip(self._values['netmask']): addr = ip_address(u'{0}'.format(str(self._values['netmask']))) if addr.version == 4: ip = ip_network(u'0.0.0.0/%s' % str(self._values['netmask'])) result = ip.prefixlen else: result = ipv6_netmask_to_cidr(self._values['netmask']) if result < 0: raise F5ModuleError( 'The provided netmask {0} is neither in IP or CIDR format'.format(result) ) return result
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))
def is_valid_ip_network(address): try: ip_network(u'{0}'.format(address)) return True except ValueError: return False
def destination_ip(self): if self._values['destination']: ip = ip_network(u'{0}/{1}'.format(self._values['destination'], self.netmask)) return '{0}/{1}'.format(str(ip.network_address), ip.prefixlen)
def netmask(self): destination = self.destination_to_network() ip = ip_network(u'%s' % str(destination)) return int(ip.prefixlen)
def get_netmask(address): addr = ip_network(u'{0}'.format(address)) netmask = addr.netmask.compressed return netmask
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)
def compress_address(address): addr = ip_network(u'{0}'.format(address)) result = addr.compressed.split('/')[0] return result