adding some config stuff

This commit is contained in:
brent s. 2020-05-12 01:21:52 -04:00
parent 96d2d1ece5
commit 3f2d6be7dd
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
3 changed files with 156 additions and 35 deletions

View File

@ -1,31 +0,0 @@
# This is a sample INI file to use with he_ipv6.py.
# If you do not yet have an IPv6 Tunnelbroker.net allocation, you can get one (for free!) at:
# https://www.tunnelbroker.net/tunnel_detail.php?tid=584532
##
# This is the tunnel ID. To get it, log into your tunnelbroker.net account and click on the tunnel you wish to use.
# The tunnel ID is the numerical string in the URL. e.g.:
# https://www.tunnelbroker.net/tunnel_detail.php?tid=12345
# The tunnel ID would be 12345 in the above example.
[12345]
# This is your tunnelbroker.net username.
user = ipv6user
# This is your update key for the above user. You can find it in the "Advanced" tab.
update_key = xXxXxXxXxXxXxXXX
# This is the server IP ("IPv6 Tunnel Endpoints" section). *Be sure to use the IPv4 address!* ("Server IPv4 Address")
server = 192.0.2.1
# And these are all the allocations you wish to add to this machine. Be sure to add the prefix (e.g. /64, /48)!
# You can specify multiple allocations with a comma-separated list.
# ("Routed IPv6 Prefixes")
allocations = 2001:DB8:1::/64,2001:DB8:2::/64
# This is the address to actually set on the interface. There should be only one here. Be sure to include the prefix!
# ("Client IPv6 Address")
address = 2001:DB8:3::1/64

# You can specify multiple tunnel profiles for your machine.
[54321]
# And you can even reference values from other sections.
user = ${12345:user}
update_key = ${12345:update_key}
server = 192.0.2.2
allocations = 2001:DB8:4::/64
address = 2001:DB8:5::2/64

100
utils/he_ipv6/config.py Normal file
View File

@ -0,0 +1,100 @@
import os
import re
##
import requests
from lxml import etree


class Config(object):
default_xsd = 'http://schema.xml.r00t2.io/projects/he_ipv6.xsd'

def __init__(self, xml_path, *args, **kwargs):
self.xml_path = os.path.abspath(os.path.expanduser(xml_path))
if not os.path.isfile(self.xml_path):
raise ValueError('xml_path does not exist')
self.tree = None
self.ns_tree = None
self.xml = None
self.ns_xml = None
self.raw = None
self.xsd = None
self.defaults_parser = None
self.obj = None
self.tunnels = {}
self.creds = {}
self.parse_raw()
self.get_xsd()
self.populate_defaults()
self.validate()

def get_xsd(self):
raw_xsd = None
base_url = None
xsi = self.xml.nsmap.get('xsi', 'http://www.w3.org/2001/XMLSchema-instance')
schemaLocation = '{{{0}}}schemaLocation'.format(xsi)
schemaURL = self.xml.attrib.get(schemaLocation, self.default_xsd)
split_url = schemaURL.split()
if len(split_url) == 2: # a properly defined schemaLocation
schemaURL = split_url[1]
else:
schemaURL = split_url[0] # a LAZY schemaLocation
if schemaURL.startswith('file://'):
schemaURL = re.sub(r'^file://', r'', schemaURL)
with open(schemaURL, 'rb') as fh:
raw_xsd = fh.read()
base_url = os.path.dirname(schemaURL) + '/'
else:
req = requests.get(schemaURL)
if not req.ok:
raise RuntimeError('Could not download XSD')
raw_xsd = req.content
base_url = os.path.split(req.url)[0] + '/' # This makes me feel dirty.
self.xsd = etree.XMLSchema(etree.XML(raw_xsd, base_url = base_url))
return(None)

def parse_raw(self, parser = None):
if not self.raw:
with open(self.xml_path, 'rb') as fh:
self.raw = fh.read()
self.xml = etree.fromstring(self.raw, parser = parser)
self.ns_xml = etree.fromstring(self.raw, parser = parser)
self.tree = self.xml.getroottree()
self.ns_tree = self.ns_xml.getroottree()
self.tree.xinclude()
self.ns_tree.xinclude()
self.strip_ns()
return(None)

def populate_defaults(self):
if not self.xsd:
self.get_xsd()
if not self.defaults_parser:
self.defaults_parser = etree.XMLParser(schema = self.xsd, attribute_defaults = True)
self.parse_raw(parser = self.defaults_parser)
return(None)

def remove_defaults(self):
self.parse_raw()
return(None)

def strip_ns(self, obj = None):
# https://stackoverflow.com/questions/30232031/how-can-i-strip-namespaces-out-of-an-lxml-tree/30233635#30233635
xpathq = "descendant-or-self::*[namespace-uri()!='']"
if not obj:
for x in (self.tree, self.xml):
for e in x.xpath(xpathq):
e.tag = etree.QName(e).localname
elif isinstance(obj, (etree._Element, etree._ElementTree)):
obj = copy.deepcopy(obj)
for e in obj.xpath(xpathq):
e.tag = etree.QName(e).localname
return(obj)
else:
raise ValueError('Did not know how to parse obj parameter')
return(None)

def validate(self):
if not self.xsd:
self.get_xsd()
self.xsd.assertValid(self.ns_tree)
return(None)

View File

@ -2,7 +2,19 @@
<heIPv6 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://tunnelbroker.net/"
xsi:schemaLocation="https://tunnelbroker.net/ http://schema.xml.r00t2.io/projects/he_ipv6.xsd">
<!--
This is a sample XML configuration file to use with he_ipv6.py.
If you do not yet have an IPv6 Tunnelbroker.net allocation, you can get one (for free!) at:
https://www.tunnelbroker.net/tunnel_detail.php?tid=584532
I highly recommend their (free) certification as well if you're brand-new to IPv6:
https://ipv6.he.net/certification/
-->
<creds>
<!--
Credentials are kept separate from tunnel configuration because you can have multiple (up to 5) tunnels per user.
The updateKey is *not* your password! You can find it in the "Advanced" tab of your tunnel's configuration on
your tunnelbroker.net panel.
-->
<cred id="ipv6user">
<user>ipv6user</user>
<updateKey>xXxXxXxXxXxXxXXX</updateKey>
@ -13,19 +25,59 @@
</cred>
</creds>
<tunnels>
<!--
Each tunnel MUST have an "id" and a "creds" attribute. The "creds" attribute should reference an "id" of a
creds/cred object.
The tunnel ID can be found by logging into your tunnelbroker.net pannel, clicking on the tunnel you wish to use, and
looking at the URL in your browser.
It is in the format of https://www.tunnelbroker.net/tunnel_detail.php?tid=[TUNNEL ID]
So if it takes you to e.g. https://www.tunnelbroker.net/tunnel_detail.php?tid=12345, your tunnel ID would
be "12345".
The below directives give you a Section and Value Name. This refers to the tunnelbroker.net panel page for the
specific tunnel you're configuring. e.g. To use the above example, this information is found at
https://www.tunnelbroker.net/tunnel_detail.php?tid=12345
-->
<tunnel id="12345" creds="ipv6user">
<!--
The "server" element is the remote SIT endpoint.
Section: IPv6 Tunnel Endpoints
Value Name: Server IPv4 Address
-->
<server>192.0.2.1</server>
<!--
Allocations that are handed to your tunnel.
-->
<!--
Section: Routed IPv6 Prefixes
-->
<allocs>
<alloc prefix="64">2001:DB8:1:2:</alloc>
<alloc prefix="48">2001:DB8:2::</alloc>
<!--
Each alloc has (in addition to a "prefix" attribute) an "iface" attribute. This is the network interface on
this machine that the allocation should be added to.
Value Name: Routed /64
-->
<alloc prefix="64" iface="eth0">2001:DB8:1:2::</alloc>
<!--
You may not have a /48 as it's opt-in.
Value Name: Routed /48
-->
<alloc prefix="48" iface="eth0">2001:DB8:2::</alloc>
</allocs>
<!--
The "client" element is the local SIT endpoint.
Section: IPv6 Tunnel Endpoints
Value Name: Client IPv6 Address
-->
<client prefix="64">2001:DB8:3::2</client>
</tunnel>
<!--
And you can, of course, specify multiple tunnels.
-->
<tunnel id="54321" creds="ipv6user">
<server>192.0.2.1</server>
<allocs>
<alloc prefix="64">2001:DB8:4:2:</alloc>
<alloc prefix="48">2001:DB8:5::</alloc>
<alloc prefix="64" iface="eth1">2001:DB8:4:2:</alloc>
<alloc prefix="48" iface="eth1">2001:DB8:5::</alloc>
</allocs>
<client prefix="64">2001:DB8:6::2</client>
</tunnel>