diff --git a/utils/he_ipv6/config.py b/utils/he_ipv6/config.py index 88feaa3..14d55b7 100644 --- a/utils/he_ipv6/config.py +++ b/utils/he_ipv6/config.py @@ -1,10 +1,163 @@ +import copy +import ipaddress import os import re ## +import netaddr import requests from lxml import etree +class IP(object): + type = None + version = None + _ip = ipaddress.ip_address + _net = ipaddress.ip_network + _net_ip = netaddr.IPAddress + _net_net = netaddr.IPNetwork + + def __init__(self, ip, prefix, *args, **kwargs): + self.str = ip + self.prefix = int(prefix) + self.net_ip = self._net_ip(self.str) + self.net_net = self._net_net('{0}/{1}'.format(self.str, self.prefix)) + + def _ext_init(self): + self.ip = self._ip(self.str) + self.net = self._net('{0}/{1}'.format(self.str, self.prefix), strict = False) + return(None) + + +class IP4(IP): + type = 'IPv4' + version = 4 + _ip = ipaddress.IPv4Address + _net = ipaddress.IPv4Network + + def __init__(self, ip, prefix, *args, **kwargs): + super().__init__(ip, prefix, *args, **kwargs) + self._ext_init() + + +class IP6(IP): + type = 'IPv6' + version = 6 + _ip = ipaddress.IPv6Address + _net = ipaddress.IPv6Network + + def __init__(self, ip, prefix, *args, **kwargs): + super().__init__(ip, prefix, *args, **kwargs) + self._ext_init() + + +class Allocation(object): + def __init__(self, alloc_xml): + self.xml = alloc_xml + self.prefix = None + self.ip = None + self.iface = None + self.parse() + + def _iface(self): + _iface_txt = self.xml.attrib['iface'] + self.iface = _iface_txt.strip() + return(None) + + def _ip(self): + _ip_txt = self.xml.text.strip() + _prefix_txt = self.xml.attrib['prefix'].strip() + self.ip = IP6(_ip_txt, _prefix_txt) + self.prefix = self.ip.prefix + return(None) + + def parse(self): + self._iface() + self._ip() + return(None) + + +class Tunnel(object): + def __init__(self, tun_xml): + self.xml = tun_xml + self.id = None + self.client = None + self.server = None + self.creds = None # This should be handled externally and map to a Cred obj + self.allocations = [] + self.parse() + + def _allocations(self): + for _allocation_xml in self.xml.findall('allocations'): + self.allocations.append(Allocation(_allocation_xml)) + return(None) + + def _client(self): + _client_xml = self.xml.find('client') + _ip_txt = _client_xml.text.strip() + _prefix_txt = _client_xml.attrib['prefix'].strip() + self.client = IP6(_ip_txt, _prefix_txt) + return(None) + + def _id(self): + self.id = int(self.xml.attrib['id'].strip()) + return(None) + + def _server(self): + _server_xml = self.xml.find('server') + _ip_text = _server_xml.text.strip() + self.server = IP4(_ip_text, 32) + return(None) + + def parse(self): + self._id() + self._client() + self._server() + self._allocations() + return(None) + + +class Credential(object): + def __init__(self, cred_xml): + self.xml = cred_xml + self.id = None + self.user = None + self.key = None + self.parse() + + def _id(self): + _id = self.xml.attrib.get('id') + if not _id: + raise ValueError('Missing required id attribute') + self.id = _id.strip() + return(None) + + def _update_key(self): + _key_xml = self.xml.find('updateKey') + if _key_xml is None: + raise ValueError('Missing required updateKey element') + _key_txt = _key_xml.text + if not _key_txt: + raise ValueError('updateKey element is empty') + self.key = _key_txt.strip() + return(None) + + def _user(self): + _user_xml = self.xml.find('user') + if _user_xml is None: + raise ValueError('Missing required user element') + _user_txt = _user_xml.text + if not _user_txt: + raise ValueError('user element is empty') + self.user = _user_txt.strip() + return(None) + + def parse(self): + self._id() + self._user() + self._update_key() + return(None) + + class Config(object): default_xsd = 'http://schema.xml.r00t2.io/projects/he_ipv6.xsd' @@ -22,10 +175,22 @@ class Config(object): self.obj = None self.tunnels = {} self.creds = {} - self.parse_raw() - self.get_xsd() - self.populate_defaults() - self.validate() + self.parse() + + def _creds(self): + creds_xml = self.xml.find('creds') + for cred_xml in creds_xml.findall('cred'): + cred = Credential(cred_xml) + self.creds[cred.id] = cred + return(None) + + def _tunnels(self): + tunnels_xml = self.xml.find('tunnels') + for tun_xml in tunnels_xml.findall('tunnel'): + tun = Tunnel(tun_xml) + tun.creds = self.creds.get(tun.creds) + self.tunnels[tun.id] = tun + return(None) def get_xsd(self): raw_xsd = None @@ -52,6 +217,14 @@ class Config(object): self.xsd = etree.XMLSchema(etree.XML(raw_xsd, base_url = base_url)) return(None) + def parse(self): + self.parse_raw() + self.get_xsd() + self.populate_defaults() + self.validate() + self.subparse() + return(None) + def parse_raw(self, parser = None): if not self.raw: with open(self.xml_path, 'rb') as fh: @@ -93,6 +266,11 @@ class Config(object): raise ValueError('Did not know how to parse obj parameter') return(None) + def subparse(self): + self._creds() + self._tunnels() + return(None) + def validate(self): if not self.xsd: self.get_xsd()