From 35a429c4ca1923b3e87531f34ca64133d4a82efc Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Tue, 2 Jul 2019 22:34:59 +0200 Subject: Add Debian packaging and LGPL license. --- debian/control | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 debian/control (limited to 'debian/control') diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..97f8b27ea --- /dev/null +++ b/debian/control @@ -0,0 +1,23 @@ +Source: vyos-smoketest +Section: contrib/net +Priority: extra +Maintainer: VyOS Package Maintainers +Build-Depends: debhelper (>= 9), + quilt, + python3, + python3-setuptools, + quilt, + python3-lxml, + python3-nose, + python3-coverage +Standards-Version: 3.9.6 + +Package: vyos-smoketest +Architecture: all +Depends: python3, + ${python3:Depends}, + ${shlibs:Depends}, + ${misc:Depends}, + vyos-1x +Description: VyOS build sanity checking toolkit + VyOS build sanity checking toolkit -- cgit v1.2.3 From a9eb356dd479330d23e598ac76521cc67356b963 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 5 Feb 2020 22:33:05 +0100 Subject: user: add test for adding/deleting system users --- debian/control | 1 + scripts/cli/test_system_login.py | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 scripts/cli/test_system_login.py (limited to 'debian/control') diff --git a/debian/control b/debian/control index 97f8b27ea..7dde84d3e 100644 --- a/debian/control +++ b/debian/control @@ -9,6 +9,7 @@ Build-Depends: debhelper (>= 9), quilt, python3-lxml, python3-nose, + python3-paramiko, python3-coverage Standards-Version: 3.9.6 diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py new file mode 100755 index 000000000..c804a6117 --- /dev/null +++ b/scripts/cli/test_system_login.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import re +import unittest + +from paramiko import SSHClient, WarningPolicy + +import vyos.config +import vyos.configsession +import vyos.util as util + +base_path = ['system', 'login'] +users = ['vyos1', 'vyos2'] + +class TestSystemLoginServer(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + + def tearDown(self): + # Delete SNNP configuration + for user in users: + self.session.delete(base_path + ['user', user]) + + self.session.commit() + + def test_user(self): + """ Check if user can be created and we can SSH to localhost """ + + for user in users: + name = "VyOS Roxx " + user + home_dir = "/tmp/" + user + + self.session.set(base_path + ['user', user, 'authentication', 'plaintext-password', user]) + self.session.set(base_path + ['user', user, 'full-name', 'VyOS Roxx']) + self.session.set(base_path + ['user', user, 'home-directory', home_dir]) + + self.session.commit() + + # check if we can login via SSH + for user in users: + # check if homedir has been created + self.assertTrue(os.path.isdir("/tmp/" + user)) + + ssh = SSHClient() + ssh.set_missing_host_key_policy(WarningPolicy) + + try: + ssh.connect('localhost', username=user, password=user) + stdin, stdout, stderr = ssh.exec_command('who') + print(stdout.read().decode()) + except Exception as e: + print(e) + self.assertTrue(False) + + ssh.close() + + # check if homedir has been created + # this can only be done after we have connected via ssh and + # pam_mkhomedir was executes + self.assertTrue(os.path.isdir("/tmp/" + user)) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 6aea18a15f96c733505fc7587ac35e263c165549 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 7 Feb 2020 19:07:35 +0100 Subject: Debian: move python3-paramiko from Build-Depends to Depends Commit a9eb356 ("user: add test for adding/deleting system users") added python3-paramiko to the list of build dependencies, but its a runtime dependency. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 7dde84d3e..41a0338db 100644 --- a/debian/control +++ b/debian/control @@ -9,13 +9,13 @@ Build-Depends: debhelper (>= 9), quilt, python3-lxml, python3-nose, - python3-paramiko, python3-coverage Standards-Version: 3.9.6 Package: vyos-smoketest Architecture: all Depends: python3, + python3-paramiko, ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, -- cgit v1.2.3 From 189b724dd7e5f4a5be4137809376127298bf9d25 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 13:00:07 +0100 Subject: login: remove ssh test --- debian/control | 1 - scripts/cli/test_system_login.py | 25 ------------------------- 2 files changed, 26 deletions(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 41a0338db..97f8b27ea 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,6 @@ Standards-Version: 3.9.6 Package: vyos-smoketest Architecture: all Depends: python3, - python3-paramiko, ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index c804a6117..b14b52603 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -18,8 +18,6 @@ import os import re import unittest -from paramiko import SSHClient, WarningPolicy - import vyos.config import vyos.configsession import vyos.util as util @@ -53,28 +51,5 @@ class TestSystemLoginServer(unittest.TestCase): self.session.commit() - # check if we can login via SSH - for user in users: - # check if homedir has been created - self.assertTrue(os.path.isdir("/tmp/" + user)) - - ssh = SSHClient() - ssh.set_missing_host_key_policy(WarningPolicy) - - try: - ssh.connect('localhost', username=user, password=user) - stdin, stdout, stderr = ssh.exec_command('who') - print(stdout.read().decode()) - except Exception as e: - print(e) - self.assertTrue(False) - - ssh.close() - - # check if homedir has been created - # this can only be done after we have connected via ssh and - # pam_mkhomedir was executes - self.assertTrue(os.path.isdir("/tmp/" + user)) - if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 23257105b68cb26fe16638928ab490fe3ea99164 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:13:24 +0200 Subject: Debian: cleanup runtime dependencies Depends field of package vyos-smoketest: substitution variable ${shlibs:Depends} used, but is not defined --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 97f8b27ea..ada46a4c1 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,6 @@ Package: vyos-smoketest Architecture: all Depends: python3, ${python3:Depends}, - ${shlibs:Depends}, ${misc:Depends}, vyos-1x Description: VyOS build sanity checking toolkit -- cgit v1.2.3 From 909152a69e0844ad0cdd2b05467cd7fe379a5347 Mon Sep 17 00:00:00 2001 From: jack9603301 Date: Mon, 10 Aug 2020 21:40:57 +0800 Subject: tcptraceroute: T2723: Fix the problem that tcptraceroute6 cannot be executed --- debian/control | 3 ++- op-mode-definitions/traceroute.xml | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 3a441b47b..34ba4be8e 100644 --- a/debian/control +++ b/debian/control @@ -106,7 +106,8 @@ Depends: python3, conntrack, libatomic1, fastnetmon, - libndp-tools + libndp-tools, + tcptraceroute Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything diff --git a/op-mode-definitions/traceroute.xml b/op-mode-definitions/traceroute.xml index efbaaeb2f..b562eb2e6 100644 --- a/op-mode-definitions/traceroute.xml +++ b/op-mode-definitions/traceroute.xml @@ -26,7 +26,7 @@ /usr/bin/traceroute -4 "$3" - + Route tracing and port detection using TCP @@ -38,10 +38,10 @@ 0-65535 - sudo /usr/sbin/tcptraceroute "$3" $6 + sudo /usr/bin/tcptraceroute "$3" $6 - + @@ -53,7 +53,7 @@ /usr/bin/traceroute -6 "$3" - + Use TCP/IPv6 packets to perform a traceroute @@ -65,10 +65,10 @@ 0-65535 - sudo /usr/sbin/tcptraceroute6 "$3" $6 + sudo /usr/bin/tcptraceroute6 "$3" $6 - + -- cgit v1.2.3 From 865cba395223afaa263ff7581fb53ee509f36266 Mon Sep 17 00:00:00 2001 From: Eshenko Dmitriy Date: Wed, 19 Aug 2020 00:37:00 +0300 Subject: anyconnect: T2036: add anyconnect VPN support --- data/templates/ocserv/ocserv_config.tmpl | 82 +++++++ data/templates/ocserv/ocserv_passwd.tmpl | 6 + data/templates/ocserv/radius_conf.tmpl | 22 ++ data/templates/ocserv/radius_servers.tmpl | 7 + debian/control | 1 + interface-definitions/vpn_anyconnect.xml.in | 258 +++++++++++++++++++++ op-mode-definitions/anyconnect.xml | 20 ++ src/conf_mode/vpn_anyconnect.py | 132 +++++++++++ .../systemd/system/ocserv.service.d/override.conf | 14 ++ src/op_mode/anyconnect-control.py | 67 ++++++ 10 files changed, 609 insertions(+) create mode 100644 data/templates/ocserv/ocserv_config.tmpl create mode 100644 data/templates/ocserv/ocserv_passwd.tmpl create mode 100644 data/templates/ocserv/radius_conf.tmpl create mode 100644 data/templates/ocserv/radius_servers.tmpl create mode 100644 interface-definitions/vpn_anyconnect.xml.in create mode 100644 op-mode-definitions/anyconnect.xml create mode 100755 src/conf_mode/vpn_anyconnect.py create mode 100644 src/etc/systemd/system/ocserv.service.d/override.conf create mode 100755 src/op_mode/anyconnect-control.py (limited to 'debian/control') diff --git a/data/templates/ocserv/ocserv_config.tmpl b/data/templates/ocserv/ocserv_config.tmpl new file mode 100644 index 000000000..6aaeff693 --- /dev/null +++ b/data/templates/ocserv/ocserv_config.tmpl @@ -0,0 +1,82 @@ +### generated by vpn_anyconnect.py ### + +tcp-port = {{ listen_ports.tcp }} +udp-port = {{ listen_ports.udp }} + +run-as-user = nobody +run-as-group = daemon + +{% if "radius" in authentication.mode %} +auth = "radius [config=/run/ocserv/radiusclient.conf]" +{% else %} +auth = "plain[/run/ocserv/ocpasswd]" +{% endif %} + +{% if ssl.cert_file %} +server-cert = {{ ssl.cert_file }} +{% endif %} + +{% if ssl.key_file %} +server-key = {{ ssl.key_file }} +{% endif %} + +{% if ssl.ca_cert_file %} +ca-cert = {{ ssl.ca_cert_file }} +{% endif %} + +socket-file = /run/ocserv/ocserv.socket +occtl-socket-file = /run/ocserv/occtl.socket +use-occtl = true +isolate-workers = true +keepalive = 300 +dpd = 60 +mobile-dpd = 300 +switch-to-tcp-timeout = 30 +tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128" +auth-timeout = 240 +idle-timeout = 1200 +mobile-idle-timeout = 1800 +min-reauth-time = 3 +cookie-timeout = 300 +rekey-method = ssl +try-mtu-discovery = true +cisco-client-compat = true +dtls-legacy = true + + +# The name to use for the tun device +device = sslvpn + +# An alternative way of specifying the network: +{% if network_settings %} +# DNS settings +{% if network_settings.name_server is string %} +dns = {{ network_settings.name_server }} +{% else %} +{% for dns in network_settings.name_server %} +dns = {{ dns }} +{% endfor %} +{% endif %} +# IPv4 network pool +{% if network_settings.client_ip_settings %} +{% if network_settings.client_ip_settings.subnet %} +ipv4-network = {{ network_settings.client_ip_settings.subnet }} +{% endif %} +{% endif %} +# IPv6 network pool +{% if network_settings.client_ipv6_pool %} +{% if network_settings.client_ipv6_pool.prefix %} +ipv6-network = {{ network_settings.client_ipv6_pool.prefix }} +ipv6-subnet-prefix = {{ network_settings.client_ipv6_pool.mask }} +{% endif %} +{% endif %} +{% endif %} + +{% if network_settings.push_route is string %} +route = {{ network_settings.push_route }} +{% else %} +{% for route in network_settings.push_route %} +route = {{ route }} +{% endfor %} +{% endif %} + diff --git a/data/templates/ocserv/ocserv_passwd.tmpl b/data/templates/ocserv/ocserv_passwd.tmpl new file mode 100644 index 000000000..ffadb4860 --- /dev/null +++ b/data/templates/ocserv/ocserv_passwd.tmpl @@ -0,0 +1,6 @@ +#:: +{% for user in username if username is defined %} +{% if not "disable" in username[user] %} +{{ user }}:*:{{ username[user].hash }} +{% endif %} +{% endfor %} \ No newline at end of file diff --git a/data/templates/ocserv/radius_conf.tmpl b/data/templates/ocserv/radius_conf.tmpl new file mode 100644 index 000000000..2d19306a0 --- /dev/null +++ b/data/templates/ocserv/radius_conf.tmpl @@ -0,0 +1,22 @@ +### generated by cpn_anyconnect.py ### +nas-identifier VyOS +{% for srv in server %} +{% if not "disable" in server[srv] %} +{% if "port" in server[srv] %} +authserver {{ srv }}:{{server[srv]["port"]}} +{% else %} +authserver {{ srv }} +{% endif %} +{% endif %} +{% endfor %} +radius_timeout {{ timeout }} +{% if source_address %} +bindaddr {{ source_address }} +{% else %} +bindaddr * +{% endif %} +servers /run/ocserv/radius_servers +dictionary /etc/radcli/dictionary +default_realm +radius_retries 3 +# \ No newline at end of file diff --git a/data/templates/ocserv/radius_servers.tmpl b/data/templates/ocserv/radius_servers.tmpl new file mode 100644 index 000000000..ba21fa074 --- /dev/null +++ b/data/templates/ocserv/radius_servers.tmpl @@ -0,0 +1,7 @@ +### generated by cpn_anyconnect.py ### +# server key +{% for srv in server %} +{% if not "disable" in server[srv] %} +{{ srv }} {{ server[srv].key }} +{% endif %} +{% endfor %} diff --git a/debian/control b/debian/control index 34ba4be8e..520401d57 100644 --- a/debian/control +++ b/debian/control @@ -107,6 +107,7 @@ Depends: python3, libatomic1, fastnetmon, libndp-tools, + ocserv, tcptraceroute Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything diff --git a/interface-definitions/vpn_anyconnect.xml.in b/interface-definitions/vpn_anyconnect.xml.in new file mode 100644 index 000000000..e74326986 --- /dev/null +++ b/interface-definitions/vpn_anyconnect.xml.in @@ -0,0 +1,258 @@ + + + + + + + SSL VPN AnyConnect + 901 + + + + + Authentication for remote access SSL VPN Server + + + + + Authentication mode used by this server + + local + Use local username/password configuration + + + radius + Use RADIUS server for user autentication + + + (local|radius) + + + local radius + + + + + + Local user authentication for SSL VPN server + + + + + User name for authentication + + + + + Option to disable a SSL VPN Server user + + + + + + Password for authentication + + + + + + + #include + + + + + Session timeout + + 1-30 + Session timeout in seconds (default: 2) + + + + + Timeout must be between 1 and 30 seconds + + 2 + + + + + + + + SSL Certificate, SSL Key and CA (/config/auth) + + + + + tcp port number to accept connections (default: 443) + + 1-65535 + Numeric IP port (default: 443) + + + + + + 443 + + + + udp port number to accept connections (default: 443) + + 1-65535 + Numeric IP port (default: 443) + + + + + + 443 + + + + + + SSL Certificate, SSL Key and CA (/config/auth) + + + + + Certificate Authority certificate + + + + + file + File in /config/auth directory + + + + + + + + + Server Certificate + + file + File in /config/auth directory + + + + + + + + + Privat Key of the Server Certificate + + file + File in /config/auth directory + + + + + + + + + + + Network settings + + + + + Route to be pushed to the client + + ipv4net + IPv4 network and prefix length + + + ipv6net + IPv6 network and prefix length + + + + + + + + + + Client IP pools settings + + + + + Client IP subnet (CIDR notation) + + ipv4net + IPv4 address and prefix length + + + + + Not a valid CIDR formatted prefix + + + + + + + Pool of client IPv6 addresses + + + + + Pool of addresses used to assign to clients + + ipv6net + IPv6 address and prefix length + + + + + + + + + Prefix length used for individual client + + <48-128> + Client prefix length (default: 64) + + + + + + 64 + + + + + + Domain Name Server (DNS) propagated to client + + ipv4 + Domain Name Server (DNS) IPv4 address + + + ipv6 + Domain Name Server (DNS) IPv6 address + + + + + + + + + + + + + + + diff --git a/op-mode-definitions/anyconnect.xml b/op-mode-definitions/anyconnect.xml new file mode 100644 index 000000000..7e8cdd35b --- /dev/null +++ b/op-mode-definitions/anyconnect.xml @@ -0,0 +1,20 @@ + + + + + + + show anyconnect-server information + + + + + Show active anyconnect server sessions + + ${vyos_op_scripts_dir}/anyconnect-control.py --action="show_sessions" + + + + + + diff --git a/src/conf_mode/vpn_anyconnect.py b/src/conf_mode/vpn_anyconnect.py new file mode 100755 index 000000000..45c06bffa --- /dev/null +++ b/src/conf_mode/vpn_anyconnect.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +from sys import exit + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.xml import defaults +from vyos.template import render +from vyos.util import call +from vyos import ConfigError +from crypt import crypt, mksalt, METHOD_SHA512 + +from vyos import airbag +airbag.enable() + +cfg_dir = '/run/ocserv' +ocserv_conf = cfg_dir + '/ocserv.conf' +ocserv_passwd = cfg_dir + '/ocpasswd' +radius_cfg = cfg_dir + '/radiusclient.conf' +radius_servers = cfg_dir + '/radius_servers' + + +# Generate hash from user cleartext password +def get_hash(password): + return crypt(password, mksalt(METHOD_SHA512)) + + +def get_config(): + conf = Config() + base = ['vpn', 'anyconnect'] + ocserv = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + default_values = defaults(base) + ocserv = dict_merge(default_values, ocserv) + return ocserv + + +def verify(ocserv): + if ocserv is None: + return None + + # Check authentication + if "authentication" in ocserv: + if "mode" in ocserv["authentication"]: + if "local" in ocserv["authentication"]["mode"]: + if not ocserv["authentication"]["local_users"] or not ocserv["authentication"]["local_users"]["username"]: + raise ConfigError('Anyconect mode local required at leat one user') + else: + for user in ocserv["authentication"]["local_users"]["username"]: + if not "password" in ocserv["authentication"]["local_users"]["username"][user]: + raise ConfigError(f'password required for user {user}') + else: + raise ConfigError('anyconnect authentication mode required') + else: + raise ConfigError('anyconnect authentication credentials required') + + # Check ssl + if "ssl" in ocserv: + req_cert = ['ca_cert_file', 'cert_file', 'key_file'] + for cert in req_cert: + if not cert in ocserv["ssl"]: + raise ConfigError('anyconnect ssl {0} required'.format(cert.replace('_', '-'))) + else: + raise ConfigError('anyconnect ssl required') + + # Check network settings + if "network_settings" in ocserv: + if "push_route" in ocserv["network_settings"]: + # Replace default route + if "0.0.0.0/0" in ocserv["network_settings"]["push_route"]: + ocserv["network_settings"]["push_route"].remove("0.0.0.0/0") + ocserv["network_settings"]["push_route"].append("default") + else: + ocserv["network_settings"]["push_route"] = "default" + else: + raise ConfigError('anyconnect network settings required') + + +def generate(ocserv): + if not ocserv: + return None + + if "radius" in ocserv["authentication"]["mode"]: + # Render radius client configuration + render(radius_cfg, 'ocserv/radius_conf.tmpl', ocserv["authentication"]["radius"], trim_blocks=True) + # Render radius servers + render(radius_servers, 'ocserv/radius_servers.tmpl', ocserv["authentication"]["radius"], trim_blocks=True) + else: + if "local_users" in ocserv["authentication"]: + for user in ocserv["authentication"]["local_users"]["username"]: + ocserv["authentication"]["local_users"]["username"][user]["hash"] = get_hash(ocserv["authentication"]["local_users"]["username"][user]["password"]) + # Render local users + render(ocserv_passwd, 'ocserv/ocserv_passwd.tmpl', ocserv["authentication"]["local_users"], trim_blocks=True) + + # Render config + render(ocserv_conf, 'ocserv/ocserv_config.tmpl', ocserv, trim_blocks=True) + + + +def apply(ocserv): + if not ocserv: + call('systemctl stop ocserv.service') + for file in [ocserv_conf, ocserv_passwd]: + if os.path.exists(file): + os.unlink(file) + else: + call('systemctl restart ocserv.service') + + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) diff --git a/src/etc/systemd/system/ocserv.service.d/override.conf b/src/etc/systemd/system/ocserv.service.d/override.conf new file mode 100644 index 000000000..89dbb153f --- /dev/null +++ b/src/etc/systemd/system/ocserv.service.d/override.conf @@ -0,0 +1,14 @@ +[Unit] +RequiresMountsFor=/run +ConditionPathExists=/run/ocserv/ocserv.conf +After= +After=vyos-router.service +After=dbus.service + +[Service] +WorkingDirectory=/run/ocserv +PIDFile= +PIDFile=/run/ocserv/ocserv.pid +ExecStart= +ExecStart=/usr/sbin/ocserv --foreground --pid-file /run/ocserv/ocserv.pid --config /run/ocserv/ocserv.conf + diff --git a/src/op_mode/anyconnect-control.py b/src/op_mode/anyconnect-control.py new file mode 100755 index 000000000..6382016b7 --- /dev/null +++ b/src/op_mode/anyconnect-control.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import sys +import argparse +import json + +from vyos.config import Config +from vyos.util import popen, run, DEVNULL +from tabulate import tabulate + +occtl = '/usr/bin/occtl' +occtl_socket = '/run/ocserv/occtl.socket' + +def show_sessions(): + out, code = popen("sudo {0} -j -s {1} show users".format(occtl, occtl_socket),stderr=DEVNULL) + if code: + sys.exit('Cannot get anyconnect users information') + else: + headers = ["interface", "username", "ip", "remote IP", "RX", "TX", "state", "uptime"] + sessions = json.loads(out) + ses_list = [] + for ses in sessions: + ses_list.append([ses["Device"], ses["Username"], ses["IPv4"], ses["Remote IP"], ses["_RX"], ses["_TX"], ses["State"], ses["_Connected at"]]) + if len(ses_list) > 0: + print(tabulate(ses_list, headers)) + else: + print("No active anyconnect sessions") + +def is_ocserv_configured(): + if not Config().exists_effective('vpn anyconnect'): + print("vpn anyconnect server is not configured") + sys.exit(1) + +def main(): + #parese args + parser = argparse.ArgumentParser() + parser.add_argument('--action', help='Control action', required=True) + parser.add_argument('--selector', help='Selector username|ifname|sid', required=False) + parser.add_argument('--target', help='Target must contain username|ifname|sid', required=False) + args = parser.parse_args() + + + # Check is IPoE configured + is_ocserv_configured() + + if args.action == "restart": + run("systemctl restart ocserv") + sys.exit(0) + elif args.action == "show_sessions": + show_sessions() + +if __name__ == '__main__': + main() -- cgit v1.2.3 From 20e66514c00cf6495370bac6bbbe45a505afe242 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 20 Aug 2020 22:27:30 +0200 Subject: lcd: T2564: remove lcdproc-extra-drivers package --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 520401d57..9be41df33 100644 --- a/debian/control +++ b/debian/control @@ -74,7 +74,6 @@ Depends: python3, udp-broadcast-relay, pdns-recursor, lcdproc, - lcdproc-extra-drivers, openvpn, openvpn-auth-ldap, openvpn-auth-radius, -- cgit v1.2.3 From 50a7544ad69cb7b631a499299f9ab32b2e8918a0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 20 Aug 2020 22:54:50 +0200 Subject: Debian: alphabetically sort (build-)dependencies --- debian/control | 169 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 86 insertions(+), 83 deletions(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 9be41df33..d6b4420c7 100644 --- a/debian/control +++ b/debian/control @@ -2,112 +2,115 @@ Source: vyos-1x Section: contrib/net Priority: extra Maintainer: VyOS Package Maintainers -Build-Depends: debhelper (>= 9), - quilt, +Build-Depends: + debhelper (>= 9), + fakeroot, + libvyosconfig0 (>= 0.0.7), python3, - python3-setuptools, - python3-xmltodict, + python3-coverage, python3-lxml, python3-nose, - python3-coverage, - whois, - fakeroot, - libvyosconfig0 (>= 0.0.7) + python3-setuptools, + python3-xmltodict, + quilt, + whois Standards-Version: 3.9.6 Package: vyos-1x Architecture: all -Depends: python3, - ${python3:Depends}, - python3-netifaces, - python3-jinja2, - python3-pystache, - python3-psutil, - python3-tabulate, - python3-six, - python3-isc-dhcp-leases, - python3-hurry.filesize, - python3-vici (>= 5.7.2), - python3-flask, - python3-waitress, - python3-netaddr, - python3-zmq, - python3-jmespath, - python3-xmltodict, - python3-pyudev, - python3-voluptuous, +Depends: + accel-ppp, + beep, + bmon, bsdmainutils, + conntrack, + conserver-client, + conserver-server, + crda, cron, - etherwake, - systemd, + dbus, + dropbear, easy-rsa, + etherwake, + fastnetmon, + file, + frr, + frr-pythontools, + hostapd (>= 0.6.8), + hvinfo, + igmpproxy, ipaddrcheck, - tcpdump, + iperf, + iperf3, + iputils-arping, isc-dhcp-client, - wide-dhcpv6-client, - bmon, - hvinfo, + isc-dhcp-relay, + isc-dhcp-server, + iw, + keepalived (>=2.0.5), + lcdproc, + libatomic1, + libndp-tools, + libpam-radius-auth (>= 1.5.0), + libvyosconfig0, + lldpd, lm-sensors, - file, lsscsi, - pciutils, - usbutils, - procps, - snmp, snmpd, - openssh-server, + mdns-repeater, + mtr-tiny, + nftables (>= 0.9.3), + nginx-light, ntp, ntpdate, - iputils-arping, - libvyosconfig0, - beep, - dropbear, - conserver-server, - conserver-client, - isc-dhcp-server, - isc-dhcp-relay, - keepalived (>=2.0.5), - wireguard, - tftpd-hpa, - igmpproxy, - accel-ppp, - mdns-repeater, - udp-broadcast-relay, - pdns-recursor, - lcdproc, + ocserv, + openssh-server, openvpn, openvpn-auth-ldap, openvpn-auth-radius, - libpam-radius-auth (>= 1.5.0), - mtr-tiny, - telnet, - traceroute, - ssl-cert, - nginx-light, - lldpd, - iperf, - iperf3, - frr, - frr-pythontools, - radvd, - dbus, - usb-modeswitch, - hostapd (>= 0.6.8), - wpasupplicant (>= 0.6.7), - iw, - crda, - wireless-regdb, + pciutils, + pdns-recursor, pmacct (>= 1.6.0), - python3-certbot-nginx, pppoe, + procps, + python3, + python3-certbot-nginx, + ${python3:Depends}, + python3-flask, + python3-hurry.filesize, + python3-isc-dhcp-leases, + python3-jinja2, + python3-jmespath, + python3-netaddr, + python3-netifaces, + python3-psutil, + python3-pystache, + python3-pyudev, + python3-six, + python3-tabulate, + python3-vici (>= 5.7.2), + python3-voluptuous, + python3-waitress, + python3-xmltodict, + python3-zmq, + radvd, salt-minion, + snmp, + snmpd, + ssl-cert, + systemd, + tcpdump, + tcptraceroute, + telnet, + tftpd-hpa, + traceroute, + udp-broadcast-relay, + usb-modeswitch, + usbutils, vyos-utils, - nftables (>= 0.9.3), - conntrack, - libatomic1, - fastnetmon, - libndp-tools, - ocserv, - tcptraceroute + wide-dhcpv6-client, + wireguard, + wireless-regdb, + wpasupplicant (>= 0.6.7) Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything -- cgit v1.2.3 From bab1534e0fc1e6da538414b8b032342eb2598f03 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 30 Aug 2020 16:09:37 +0200 Subject: WireGuard: T2842: switch to binary package from buster-backports --- debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index 65808de86..a628fa9c4 100644 --- a/debian/control +++ b/debian/control @@ -108,7 +108,8 @@ Depends: usbutils, vyos-utils, wide-dhcpv6-client, - wireguard, + wireguard-tools, + wireguard-modules, wireless-regdb, wpasupplicant (>= 0.6.7) Description: VyOS configuration scripts and data -- cgit v1.2.3 From bd076f694a763991a0b0d3a7bb0fa5d194d56d7c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 30 Aug 2020 21:41:27 +0200 Subject: Debian: T2843: drop wireguard-modules dependency with kernel 5.8 --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian/control') diff --git a/debian/control b/debian/control index a628fa9c4..65f3be228 100644 --- a/debian/control +++ b/debian/control @@ -109,7 +109,6 @@ Depends: vyos-utils, wide-dhcpv6-client, wireguard-tools, - wireguard-modules, wireless-regdb, wpasupplicant (>= 0.6.7) Description: VyOS configuration scripts and data -- cgit v1.2.3 From 88985dad133d5e85aca559dbfce53207a2292e0a Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 28 Aug 2020 15:49:55 -0500 Subject: configd: T2582: add config daemon and supporting files --- data/configd-include.json | 1 + data/vyos-configd-env-set | 2 + data/vyos-configd-env-unset | 2 + debian/control | 1 + debian/rules | 1 + src/services/vyos-configd | 224 +++++++++++++++++++++++++++++++++++++++ src/systemd/vyos-configd.service | 27 +++++ 7 files changed, 258 insertions(+) create mode 100644 data/configd-include.json create mode 100644 data/vyos-configd-env-set create mode 100644 data/vyos-configd-env-unset create mode 100755 src/services/vyos-configd create mode 100644 src/systemd/vyos-configd.service (limited to 'debian/control') diff --git a/data/configd-include.json b/data/configd-include.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/data/configd-include.json @@ -0,0 +1 @@ +[] diff --git a/data/vyos-configd-env-set b/data/vyos-configd-env-set new file mode 100644 index 000000000..d6d421eba --- /dev/null +++ b/data/vyos-configd-env-set @@ -0,0 +1,2 @@ +# +export vyshim=/usr/sbin/vyshim diff --git a/data/vyos-configd-env-unset b/data/vyos-configd-env-unset new file mode 100644 index 000000000..9616f9858 --- /dev/null +++ b/data/vyos-configd-env-unset @@ -0,0 +1,2 @@ +# +unset vyshim diff --git a/debian/control b/debian/control index 65f3be228..d9663d07b 100644 --- a/debian/control +++ b/debian/control @@ -6,6 +6,7 @@ Build-Depends: debhelper (>= 9), fakeroot, libvyosconfig0 (>= 0.0.7), + libzmq3-dev, python3, python3-coverage, python3-lxml, diff --git a/debian/rules b/debian/rules index 58bafd333..6b982fd8e 100755 --- a/debian/rules +++ b/debian/rules @@ -33,6 +33,7 @@ override_dh_auto_install: mkdir -p $(DIR)/$(VYOS_SBIN_DIR) mkdir -p $(DIR)/$(VYOS_BIN_DIR) cp -r src/utils/* $(DIR)/$(VYOS_BIN_DIR) + cp src/shim/vyshim $(DIR)/$(VYOS_SBIN_DIR) # Install conf mode scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/conf_mode diff --git a/src/services/vyos-configd b/src/services/vyos-configd new file mode 100755 index 000000000..75f84d3df --- /dev/null +++ b/src/services/vyos-configd @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# + +import os +import sys +import grp +import re +import json +import logging +import signal +import importlib.util +import zmq + +from vyos.defaults import directories +from vyos.configsource import ConfigSourceString +from vyos.config import Config +from vyos import ConfigError + +CFG_GROUP = 'vyattacfg' + +debug = True + +logger = logging.getLogger(__name__) +logs_handler = logging.StreamHandler() +logger.addHandler(logs_handler) + +if debug: + logger.setLevel(logging.DEBUG) +else: + logger.setLevel(logging.INFO) + +SOCKET_PATH = "ipc:///run/vyos-configd.sock" + +# Response error codes +R_SUCCESS = 1 +R_ERROR_COMMIT = 2 +R_ERROR_DAEMON = 4 +R_PASS = 8 + +vyos_conf_scripts_dir = directories['conf_mode'] +configd_include_file = os.path.join(directories['data'], 'configd-include.json') +configd_env_set_file = os.path.join(directories['data'], 'vyos-configd-env-set') +configd_env_unset_file = os.path.join(directories['data'], 'vyos-configd-env-unset') +# sourced on entering config session +configd_env_file = '/etc/default/vyos-configd-env' + +active_string = '' +session_string = '' + +def key_name_from_file_name(f): + return os.path.splitext(f)[0] + +def module_name_from_key(k): + return k.replace('-', '_') + +def path_from_file_name(f): + return os.path.join(vyos_conf_scripts_dir, f) + +# opt-in to be run by daemon +with open(configd_include_file) as f: + try: + include = json.load(f) + except OSError as e: + logger.critical(f"configd include file error: {e}") + sys.exit(1) + except json.JSONDecodeError as e: + logger.critical(f"JSON load error: {e}") + sys.exit(1) + +# import conf_mode scripts +(_, _, filenames) = next(iter(os.walk(vyos_conf_scripts_dir))) +filenames.sort() + +load_filenames = [f for f in filenames if f in include] +imports = [key_name_from_file_name(f) for f in load_filenames] +module_names = [module_name_from_key(k) for k in imports] +paths = [path_from_file_name(f) for f in load_filenames] +to_load = list(zip(module_names, paths)) + +modules = [] + +for x in to_load: + spec = importlib.util.spec_from_file_location(x[0], x[1]) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + modules.append(module) + +conf_mode_scripts = dict(zip(imports, modules)) + +exclude_set = {key_name_from_file_name(f) for f in filenames if f not in include} +include_set = {key_name_from_file_name(f) for f in filenames if f in include} + + +def run_script(script, config) -> int: + config.set_level([]) + try: + c = script.get_config(config) + script.verify(c) + script.generate(c) + script.apply(c) + except ConfigError as e: + logger.critical(e) + return R_ERROR_COMMIT + except Exception: + return R_ERROR_DAEMON + + return R_SUCCESS + +def initialization(socket): + # Reset config strings: + active_string = '' + session_string = '' + # zmq synchronous for ipc from single client: + active_string = socket.recv().decode() + resp = "active" + socket.send(resp.encode()) + session_string = socket.recv().decode() + resp = "session" + socket.send(resp.encode()) + + configsource = ConfigSourceString(running_config_text=active_string, + session_config_text=session_string) + + config = Config(config_source=configsource) + + return config + +def process_node_data(config, data) -> int: + if not config: + logger.critical(f"Empty config") + return R_ERROR_DAEMON + + script_name = None + + res = re.match(r'^.+\/([^/].+).py(VYOS_TAGNODE_VALUE=.+)?', data) + if res.group(1): + script_name = res.group(1) + if res.group(2): + env = res.group(2).split('=') + os.environ[env[0]] = env[1] + + if not script_name: + logger.critical(f"Missing script_name") + return R_ERROR_DAEMON + + if script_name in exclude_set: + return R_PASS + + result = run_script(conf_mode_scripts[script_name], config) + + return result + +def remove_if_file(f: str): + try: + os.remove(f) + except FileNotFoundError: + pass + except OSError: + raise + +def shutdown(): + remove_if_file(configd_env_file) + os.symlink(configd_env_unset_file, configd_env_file) + sys.exit(0) + +if __name__ == '__main__': + context = zmq.Context() + socket = context.socket(zmq.REP) + + # Set the right permissions on the socket, then change it back + o_mask = os.umask(0) + socket.bind(SOCKET_PATH) + os.umask(o_mask) + + cfg_group = grp.getgrnam(CFG_GROUP) + os.setgid(cfg_group.gr_gid) + + os.environ['SUDO_USER'] = 'vyos' + os.environ['SUDO_GID'] = str(cfg_group.gr_gid) + + def sig_handler(signum, frame): + shutdown() + + signal.signal(signal.SIGTERM, sig_handler) + signal.signal(signal.SIGINT, sig_handler) + + # Define the vyshim environment variable + remove_if_file(configd_env_file) + os.symlink(configd_env_set_file, configd_env_file) + + config = None + + while True: + # Wait for next request from client + msg = socket.recv().decode() + logger.debug(f"Received message: {msg}") + message = json.loads(msg) + + if message["type"] == "init": + resp = "init" + socket.send(resp.encode()) + config = initialization(socket) + elif message["type"] == "node": + res = process_node_data(config, message["data"]) + response = res.to_bytes(1, byteorder=sys.byteorder) + logger.debug(f"Sending response {res}") + socket.send(response) + else: + logger.critical(f"Unexpected message: {message}") diff --git a/src/systemd/vyos-configd.service b/src/systemd/vyos-configd.service new file mode 100644 index 000000000..274ccc787 --- /dev/null +++ b/src/systemd/vyos-configd.service @@ -0,0 +1,27 @@ +[Unit] +Description=VyOS configuration daemon + +# Without this option, lots of default dependencies are added, +# among them network.target, which creates a dependency cycle +DefaultDependencies=no + +# Seemingly sensible way to say "as early as the system is ready" +# All vyos-configd needs is read/write mounted root +After=systemd-remount-fs.service +Before=vyos-router.service + +[Service] +ExecStart=/usr/bin/python3 -u /usr/libexec/vyos/services/vyos-configd +Type=idle + +SyslogIdentifier=vyos-configd +SyslogFacility=daemon + +Restart=on-failure + +# Does't work in Jessie but leave it here +User=root +Group=vyattacfg + +[Install] +WantedBy=vyos.target -- cgit v1.2.3