From e73df13288c5a0f9e0e629a72b640b8281fbe093 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Mon, 7 Nov 2016 21:03:48 +0100 Subject: [PATCH] (tinc) work in progress --- net/tinc/Makefile | 7 + .../OPNsense/Tinc/Api/ServiceController.php | 56 ++++ .../OPNsense/Tinc/Api/SettingsController.php | 250 ++++++++++++++++++ .../OPNsense/Tinc/IndexController.php | 48 ++++ .../OPNsense/Tinc/forms/dialogHost.xml | 44 +++ .../OPNsense/Tinc/forms/dialogNetwork.xml | 60 +++++ .../mvc/app/models/OPNsense/Tinc/Tinc.php | 39 +++ .../mvc/app/models/OPNsense/Tinc/Tinc.xml | 99 +++++++ .../mvc/app/views/OPNsense/Tinc/index.volt | 155 +++++++++++ .../scripts/OPNsense/Tinc/generate_keypair.py | 55 ++++ .../scripts/OPNsense/Tinc/lib/__init__.py | 0 .../scripts/OPNsense/Tinc/lib/objects.py | 116 ++++++++ .../opnsense/scripts/OPNsense/Tinc/tincd.py | 65 +++++ .../service/templates/OPNsense/Tinc/+TARGETS | 1 + .../templates/OPNsense/Tinc/tinc_deploy.xml | 34 +++ 15 files changed, 1029 insertions(+) create mode 100644 net/tinc/Makefile create mode 100644 net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/ServiceController.php create mode 100644 net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/SettingsController.php create mode 100644 net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/IndexController.php create mode 100644 net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogHost.xml create mode 100644 net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogNetwork.xml create mode 100644 net/tinc/src/opnsense/mvc/app/models/OPNsense/Tinc/Tinc.php create mode 100644 net/tinc/src/opnsense/mvc/app/models/OPNsense/Tinc/Tinc.xml create mode 100644 net/tinc/src/opnsense/mvc/app/views/OPNsense/Tinc/index.volt create mode 100755 net/tinc/src/opnsense/scripts/OPNsense/Tinc/generate_keypair.py create mode 100644 net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/__init__.py create mode 100644 net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/objects.py create mode 100755 net/tinc/src/opnsense/scripts/OPNsense/Tinc/tincd.py create mode 100644 net/tinc/src/opnsense/service/templates/OPNsense/Tinc/+TARGETS create mode 100644 net/tinc/src/opnsense/service/templates/OPNsense/Tinc/tinc_deploy.xml diff --git a/net/tinc/Makefile b/net/tinc/Makefile new file mode 100644 index 000000000..9eee4f70f --- /dev/null +++ b/net/tinc/Makefile @@ -0,0 +1,7 @@ +PLUGIN_NAME= tinc +PLUGIN_VERSION= 0.1 +PLUGIN_COMMENT= Tinc VPN +PLUGIN_DEPENDS= tinc +PLUGIN_MAINTAINER= ad@opnsense.org + +.include "../../Mk/plugins.mk" diff --git a/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/ServiceController.php b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/ServiceController.php new file mode 100644 index 000000000..1ed8d1916 --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/ServiceController.php @@ -0,0 +1,56 @@ +request->isPost()) { + // close session for long running action + $this->sessionClose(); + $backend = new Backend(); + $backend->configdRun('template reload OPNsense/Tinc'); + return array("status" => "ok"); + } else { + return array("status" => "failed"); + } + } +} diff --git a/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/SettingsController.php b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/SettingsController.php new file mode 100644 index 000000000..341d0c030 --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/Api/SettingsController.php @@ -0,0 +1,250 @@ +getModel()->networks->network->Add(); + return array("network" => $node->getNodes()); + } else { + $node = $this->getModel()->getNodeByReference('networks.network.'.$uuid); + if ($node != null) { + // return node + return array("network" => $node->getNodes()); + } + } + return array() ; + } + + /** + * set network action + * @param string $uuid item unique id + * @return array + */ + public function setNetworkAction($uuid = null) + { + if ($this->request->isPost() && $this->request->hasPost("network")) { + if ($uuid != null) { + $node = $this->getModel()->getNodeByReference('networks.network.'.$uuid); + } else { + $node = $this->getModel()->networks->network->Add(); + } + $node->setNodes($this->request->getPost("network")); + if (empty((string)$node->pubkey) || empty((string)$node->privkey)){ + // generate new keypair + $backend = new Backend(); + $keys = json_decode(trim($backend->configdRun("tinc gen-key")), true); + $node->pubkey = (string)$keys['pub']; + $node->privkey = $keys['priv']; + } + return $this->validateAndSave($node, 'network'); + } + return array("result"=>"failed"); + } + + + /** + * search user defined rules + * @return array list of found user rules + */ + public function searchNetworkAction() + { + $this->sessionClose(); + $grid = new UIModelGrid($this->getModel()->networks->network); + return $grid->fetchBindRequest( + $this->request, + array("enabled", "name"), + "name" + ); + } + + /** + * del network action + * @param string $uuid item unique id + * @return array + */ + public function delNetworkAction($uuid) + { + $result = array('result' => 'failed'); + if ($this->request->isPost()) { + if ($this->getModel()->networks->network->del($uuid)) { + $result = $this->validateAndSave(); + } + } + return $result ; + } + + /** + * toggle network item action + * @param string $uuid item unique id + * @param boolean $enabled + * @return array + */ + public function toggleNetworkAction($uuid, $enabled = null) + { + $result = array("result" => "failed"); + if ($this->request->isPost()) { + if ($uuid != null) { + $node = $this->getModel()->getNodeByReference('networks.network.' . $uuid); + if ($node != null) { + if ($enabled == "0" || $enabled == "1") { + $node->enabled = (string)$enabled; + } elseif ((string)$node->enabled == "1") { + $node->enabled = "0"; + } else { + $node->enabled = "1"; + } + $result['result'] = $node->enabled; + $this->save(); + } + } + } + return $result; + } + + /** + * get host action + * @param string $uuid item unique id + * @return array + */ + public function getHostAction($uuid = null) + { + if ($uuid == null) { + // generate new node, but don't save to disc + $node = $this->getModel()->hosts->host->Add(); + return array("host" => $node->getNodes()); + } else { + $node = $this->getModel()->getNodeByReference('hosts.host.'.$uuid); + if ($node != null) { + // return node + return array("host" => $node->getNodes()); + } + } + return array() ; + } + + /** + * set host action + * @param string $uuid item unique id + * @return array + */ + public function setHostAction($uuid = null) + { + if ($this->request->isPost() && $this->request->hasPost("host")) { + if ($uuid != null) { + $node = $this->getModel()->getNodeByReference('hosts.host.'.$uuid); + } else { + $node = $this->getModel()->hosts->host->Add(); + } + $node->setNodes($this->request->getPost("host")); + return $this->validateAndSave($node, 'host'); + } + return array("result"=>"failed"); + } + + + /** + * search user defined rules + * @return array list of found user rules + */ + public function searchHostAction() + { + $this->sessionClose(); + $grid = new UIModelGrid($this->getModel()->hosts->host); + return $grid->fetchBindRequest( + $this->request, + array("enabled", "hostname", 'network'), + "name" + ); + } + + /** + * del host action + * @param string $uuid item unique id + * @return array + */ + public function delHostAction($uuid) + { + $result = array('result' => 'failed'); + if ($this->request->isPost()) { + if ($this->getModel()->hosts->host->del($uuid)) { + $result = $this->validateAndSave(); + } + } + return $result ; + } + + /** + * toggle host item action + * @param string $uuid item unique id + * @param boolean $enabled + * @return array + */ + public function toggleHostAction($uuid, $enabled = null) + { + $result = array("result" => "failed"); + if ($this->request->isPost()) { + if ($uuid != null) { + $node = $this->getModel()->getNodeByReference('hosts.host.' . $uuid); + if ($node != null) { + if ($enabled == "0" || $enabled == "1") { + $node->enabled = (string)$enabled; + } elseif ((string)$node->enabled == "1") { + $node->enabled = "0"; + } else { + $node->enabled = "1"; + } + $result['result'] = $node->enabled; + $this->save(); + } + } + } + return $result; + } +} diff --git a/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/IndexController.php b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/IndexController.php new file mode 100644 index 000000000..b284d1be3 --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/IndexController.php @@ -0,0 +1,48 @@ +view->title = gettext('Tinc VPN'); + // link dialogs + $this->view->formDialogNetwork = $this->getForm("dialogNetwork"); + $this->view->formDialogHost = $this->getForm("dialogHost"); + // choose template + $this->view->pick('OPNsense/Tinc/index'); + } +} diff --git a/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogHost.xml b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogHost.xml new file mode 100644 index 000000000..91e55e420 --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogHost.xml @@ -0,0 +1,44 @@ +
+ + host.enabled + + checkbox + Enable this network + + + host.network + + dropdown + The network for this host + + + host.hostname + + text + The hostname for the selected machine in the network + + + host.extaddress + + text + This machines external address to use + + + host.subnet + + text + This machines part of the network + + + host.pubkey + + textbox + Public key for this host in the network + + + host.connectTo + + checkbox + Connect to this host + +
diff --git a/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogNetwork.xml b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogNetwork.xml new file mode 100644 index 000000000..52f6b9725 --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/controllers/OPNsense/Tinc/forms/dialogNetwork.xml @@ -0,0 +1,60 @@ +
+ + network.enabled + + checkbox + Enable this network + + + network.name + + text + Name used for this network + + + network.network + + text + Network for this VPN, where all hosts should fit in. + + + + header + + + network.hostname + + text + The hostname for this machine in the network + + + network.extaddress + + text + This machines external address to use + + + network.intaddress + + text + This machines internal address to use (within specified subnet) + + + network.subnet + + text + This machines part of the network + + + network.privkey + + textbox + Private key for this host in the network (leave empty to generate) + + + network.pubkey + + textbox + Public key for this host in the network (leave empty to generate) + +
diff --git a/net/tinc/src/opnsense/mvc/app/models/OPNsense/Tinc/Tinc.php b/net/tinc/src/opnsense/mvc/app/models/OPNsense/Tinc/Tinc.php new file mode 100644 index 000000000..a4fb850fe --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/models/OPNsense/Tinc/Tinc.php @@ -0,0 +1,39 @@ + + //OPNsense/Tinc + 1.0.0 + + OPNsense Tinc VPN + + + + + + ID should be a number. + Y + + + Y + /^([0-9a-zA-Z]){1,50}$/u + The name should contain only alphanumeric characters. + + + Y + /^([0-9a-zA-Z\.]){1,1024}$/u + Please specify a valid hostname. + + + Y + N + , + + + Y + N + + + Y + N + Y + , + + + Y + N + Y + + + Y + + + Y + + + 1 + Y + + + + + + + + + OPNsense.Tinc.Tinc + networks.network + name + + + Related pipe or queue not found + Y + + + Y + /^([0-9a-zA-Z\.]){1,1024}$/u + Please specify a valid hostname. + + + Y + N + , + + + Y + N + Y + , + + + Y + + + 1 + Y + + + 1 + Y + + + + + diff --git a/net/tinc/src/opnsense/mvc/app/views/OPNsense/Tinc/index.volt b/net/tinc/src/opnsense/mvc/app/views/OPNsense/Tinc/index.volt new file mode 100644 index 000000000..54f806f02 --- /dev/null +++ b/net/tinc/src/opnsense/mvc/app/views/OPNsense/Tinc/index.volt @@ -0,0 +1,155 @@ +{# + +OPNsense® is Copyright © 2014 – 2016 by Deciso B.V. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +#} + + + + +
+
+ + + + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('ID') }}{{ lang._('Name') }}{{ lang._('Commands') }}{{ lang._('ID') }}
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('Network') }}{{ lang._('Hostname') }}{{ lang._('Commands') }}{{ lang._('ID') }}
+ + +
+ +
+
+
+
+ +

+
+
+ + +{# include dialogs #} +{{ partial("layout_partials/base_dialog",['fields':formDialogNetwork,'id':'DialogNetwork','label':'Edit Network'])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogHost,'id':'DialogHost','label':'Edit Host'])}} diff --git a/net/tinc/src/opnsense/scripts/OPNsense/Tinc/generate_keypair.py b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/generate_keypair.py new file mode 100755 index 000000000..879661ea9 --- /dev/null +++ b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/generate_keypair.py @@ -0,0 +1,55 @@ +#!/usr/local/bin/python2.7 + +""" + Copyright (c) 2016 Deciso B.V. - Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------------- + generate new keypair +""" +import os +import tempfile +import glob +import ujson + +# create temp directory +temp_dir = tempfile.mkdtemp() +# generate certs +os.system('echo | /usr/local/sbin/tincd -K --config=%s 2>/dev/null' % (temp_dir)) + +# read and remove certs +response=dict() +for filename in glob.glob('%s/*'%temp_dir): + data = open(filename,'r').read().strip() + if filename.endswith('.priv'): + response['priv'] = data + elif filename.endswith('.pub'): + response['pub'] = data + os.remove(filename) + +# cleanup +os.rmdir(temp_dir) + +# output generated keys +print(ujson.dumps(response)) diff --git a/net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/__init__.py b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/objects.py b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/objects.py new file mode 100644 index 000000000..19cce73bd --- /dev/null +++ b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/lib/objects.py @@ -0,0 +1,116 @@ +""" + Copyright (c) 2016 Deciso B.V. - Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +""" + +class NetwConfObject(object): + def __init__(self): + self._payload = dict() + self._payload['hostname'] = None + self._payload['network'] = None + + def is_valid(self): + for key in self._payload: + if self._payload[key] is None: + return False + return True + + def set(self, prop, value): + if ('set_%s' % prop) in dir(self): + getattr(self,'set_%s' % prop)(value) + else: + # default copy propery to _payload + self._payload[prop] = value.text + + def get_hostname(self): + return self._payload['hostname'] + + def get_basepath(self): + return '/usr/local/etc/tinc/%(network)s' % self._payload + +class Network(NetwConfObject): + def __init__(self): + super(Network, self).__init__() + self._payload['id'] = None + self._payload['privkey'] = None + self._hosts = list() + + def set_id(self, value): + self._payload['id'] = value.text + + def set_hosts(self, hosts): + for host in hosts: + hostObj = Host() + for host_prop in host: + hostObj.set(host_prop.tag, host_prop) + self._hosts.append(hostObj) + + def config_text(self): + result = list() + result.append('AddressFamily=any') + for host in self._hosts: + if host.connect_to_this_host(): + result.append('ConnectTo = %s' % (host.get_hostname(),)) + result.append('Device=/dev/tinc%(id)s' % self._payload) + result.append('Name=%(hostname)s' % self._payload) + return '\n'.join(result) + + def filename(self): + return self.get_basepath() + '/tinc.conf' + + def privkey(self): + return {'filename': self.get_basepath() + '/rsa_key.priv', 'content': self._payload['privkey']} + + def all(self): + yield self + for host in self._hosts: + yield host + +class Host(NetwConfObject): + def __init__(self): + super(Host, self).__init__() + self._connectTo = "0" + self._payload['address'] = None + self._payload['subnet'] = None + self._payload['pubkey'] = None + + def connect_to_this_host(self): + if self.is_valid() and self._connectTo == "1": + return True + else: + return False + + def set_connectto(self, value): + self._connectTo = value.text + + def config_text(self): + result = list() + result.append('Address=%(address)s'%self._payload) + result.append('Subnet=%(subnet)s'%self._payload) + result.append(self._payload['pubkey']) + return '\n'.join(result) + + def filename(self): + return '%s/hosts/%s' % (self.get_basepath(), self._payload['hostname']) diff --git a/net/tinc/src/opnsense/scripts/OPNsense/Tinc/tincd.py b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/tincd.py new file mode 100755 index 000000000..331b84f9e --- /dev/null +++ b/net/tinc/src/opnsense/scripts/OPNsense/Tinc/tincd.py @@ -0,0 +1,65 @@ +#!/usr/local/bin/python2.7 + +""" + Copyright (c) 2016 Deciso B.V. - Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------------- + reconfigure tincd, using the supplied configuration +""" +import os +import tempfile +import glob +import xml.etree.ElementTree +from lib import objects + +def write_file(filename, content): + dirname = '/'.join(filename.split('/')[0:-1]) + if not os.path.isdir(dirname): + os.makedirs(dirname) + open(filename, 'w').write(content) + +def deploy(config_filename): + # collect file info + config_files=dict() + if os.path.isfile(config_filename): + for network in xml.etree.ElementTree.parse(config_filename).getroot(): + Network_obj = objects.Network() + for network_prop in network: + Network_obj.set(network_prop.tag, network_prop) + # check if config is complete before collecting output files + if Network_obj.is_valid(): + for conf_obj in Network_obj.all(): + if conf_obj.is_valid(): + config_files[conf_obj.filename()] = conf_obj.config_text() + # private key + tmp = Network_obj.privkey() + config_files[tmp['filename']] = tmp['content'] + # remove previous configuration + os.system('rm -rf /usr/local/etc/tinc') + # write output + for filename in config_files: + write_file(filename, config_files[filename]) + +deploy('/usr/local/etc/tinc_deploy.xml') diff --git a/net/tinc/src/opnsense/service/templates/OPNsense/Tinc/+TARGETS b/net/tinc/src/opnsense/service/templates/OPNsense/Tinc/+TARGETS new file mode 100644 index 000000000..fd832e540 --- /dev/null +++ b/net/tinc/src/opnsense/service/templates/OPNsense/Tinc/+TARGETS @@ -0,0 +1 @@ +tinc_deploy.xml:/usr/local/etc/tinc_deploy.xml diff --git a/net/tinc/src/opnsense/service/templates/OPNsense/Tinc/tinc_deploy.xml b/net/tinc/src/opnsense/service/templates/OPNsense/Tinc/tinc_deploy.xml new file mode 100644 index 000000000..3d11b8739 --- /dev/null +++ b/net/tinc/src/opnsense/service/templates/OPNsense/Tinc/tinc_deploy.xml @@ -0,0 +1,34 @@ + +{% if helpers.exists('OPNsense.Tinc.networks.network') %} +{% for network in helpers.toList('OPNsense.Tinc.networks.network', 'id') %} + + {{network.id}} + {{network.hostname}} + {{network.name}} + + + + {{network.hostname}} + {{network.name}} +
{{network.extaddress}}
+ {{network.subnet}} + + 0 +
+{% for host in helpers.toList('OPNsense.Tinc.hosts.host', 'hostname') %} +{% if helpers.getUUID(host.network).id == network.id %} + + {{host.hostname}} + {{network.name}} +
{{host.extaddress}}
+ {{host.subnet}} + + {{host.connectTo}} +
+{% endif %} +{% endfor %} +
+
+{% endfor %} +{% endif %} +
\ No newline at end of file