From e41ae4d952e276d8497d38f5761806c14ea542d2 Mon Sep 17 00:00:00 2001 From: DmitriyEshenko Date: Wed, 9 Sep 2020 06:45:40 +0000 Subject: openconnect: T2036: Move CLI commands under vpn openconnect --- data/templates/ocserv/ocserv_config.tmpl | 2 +- data/templates/ocserv/radius_conf.tmpl | 2 +- data/templates/ocserv/radius_servers.tmpl | 2 +- interface-definitions/vpn_anyconnect.xml.in | 258 -------------------------- interface-definitions/vpn_openconnect.xml.in | 258 ++++++++++++++++++++++++++ op-mode-definitions/anyconnect.xml | 20 -- op-mode-definitions/openconnect.xml | 20 ++ smoketest/scripts/cli/test_vpn_anyconnect.py | 58 ------ smoketest/scripts/cli/test_vpn_openconnect.py | 58 ++++++ src/conf_mode/vpn_anyconnect.py | 135 -------------- src/conf_mode/vpn_openconnect.py | 135 ++++++++++++++ src/op_mode/anyconnect-control.py | 67 ------- src/op_mode/openconnect-control.py | 67 +++++++ 13 files changed, 541 insertions(+), 541 deletions(-) delete mode 100644 interface-definitions/vpn_anyconnect.xml.in create mode 100644 interface-definitions/vpn_openconnect.xml.in delete mode 100644 op-mode-definitions/anyconnect.xml create mode 100644 op-mode-definitions/openconnect.xml delete mode 100755 smoketest/scripts/cli/test_vpn_anyconnect.py create mode 100755 smoketest/scripts/cli/test_vpn_openconnect.py delete mode 100755 src/conf_mode/vpn_anyconnect.py create mode 100755 src/conf_mode/vpn_openconnect.py delete mode 100755 src/op_mode/anyconnect-control.py create mode 100755 src/op_mode/openconnect-control.py diff --git a/data/templates/ocserv/ocserv_config.tmpl b/data/templates/ocserv/ocserv_config.tmpl index 6aaeff693..328af0c0d 100644 --- a/data/templates/ocserv/ocserv_config.tmpl +++ b/data/templates/ocserv/ocserv_config.tmpl @@ -1,4 +1,4 @@ -### generated by vpn_anyconnect.py ### +### generated by vpn_openconnect.py ### tcp-port = {{ listen_ports.tcp }} udp-port = {{ listen_ports.udp }} diff --git a/data/templates/ocserv/radius_conf.tmpl b/data/templates/ocserv/radius_conf.tmpl index 2d19306a0..1712d83ef 100644 --- a/data/templates/ocserv/radius_conf.tmpl +++ b/data/templates/ocserv/radius_conf.tmpl @@ -1,4 +1,4 @@ -### generated by cpn_anyconnect.py ### +### generated by vpn_openconnect.py ### nas-identifier VyOS {% for srv in server %} {% if not "disable" in server[srv] %} diff --git a/data/templates/ocserv/radius_servers.tmpl b/data/templates/ocserv/radius_servers.tmpl index ba21fa074..7bacac992 100644 --- a/data/templates/ocserv/radius_servers.tmpl +++ b/data/templates/ocserv/radius_servers.tmpl @@ -1,4 +1,4 @@ -### generated by cpn_anyconnect.py ### +### generated by vpn_openconnect.py ### # server key {% for srv in server %} {% if not "disable" in server[srv] %} diff --git a/interface-definitions/vpn_anyconnect.xml.in b/interface-definitions/vpn_anyconnect.xml.in deleted file mode 100644 index e74326986..000000000 --- a/interface-definitions/vpn_anyconnect.xml.in +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - - 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/interface-definitions/vpn_openconnect.xml.in b/interface-definitions/vpn_openconnect.xml.in new file mode 100644 index 000000000..16fe660a9 --- /dev/null +++ b/interface-definitions/vpn_openconnect.xml.in @@ -0,0 +1,258 @@ + + + + + + + SSL VPN OpenConnect, AnyConnect compatible server + 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 deleted file mode 100644 index 7e8cdd35b..000000000 --- a/op-mode-definitions/anyconnect.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - show anyconnect-server information - - - - - Show active anyconnect server sessions - - ${vyos_op_scripts_dir}/anyconnect-control.py --action="show_sessions" - - - - - - diff --git a/op-mode-definitions/openconnect.xml b/op-mode-definitions/openconnect.xml new file mode 100644 index 000000000..9b82b114e --- /dev/null +++ b/op-mode-definitions/openconnect.xml @@ -0,0 +1,20 @@ + + + + + + + show openconnect-server information + + + + + Show active openconnect server sessions + + ${vyos_op_scripts_dir}/openconnect-control.py --action="show_sessions" + + + + + + diff --git a/smoketest/scripts/cli/test_vpn_anyconnect.py b/smoketest/scripts/cli/test_vpn_anyconnect.py deleted file mode 100755 index dd8ab1609..000000000 --- a/smoketest/scripts/cli/test_vpn_anyconnect.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/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 re -import os -import unittest - -from psutil import process_iter -from vyos.configsession import ConfigSession, ConfigSessionError -from vyos.util import read_file - -OCSERV_CONF = '/run/ocserv/ocserv.conf' -base_path = ['vpn', 'anyconnect'] -cert = '/etc/ssl/certs/ssl-cert-snakeoil.pem' -cert_key = '/etc/ssl/private/ssl-cert-snakeoil.key' - -class TestVpnAnyconnect(unittest.TestCase): - def setUp(self): - self.session = ConfigSession(os.getpid()) - - def tearDown(self): - # Delete vpn anyconnect configuration - self.session.delete(base_path) - self.session.commit() - - del self.session - - def test_vpn(self): - user = 'vyos_user' - password = 'vyos_pass' - self.session.delete(base_path) - self.session.set(base_path + ["authentication", "local-users", "username", user, "password", password]) - self.session.set(base_path + ["authentication", "mode", "local"]) - self.session.set(base_path + ["network-settings", "client-ip-settings", "subnet", "192.0.2.0/24"]) - self.session.set(base_path + ["ssl", "ca-cert-file", cert]) - self.session.set(base_path + ["ssl", "cert-file", cert]) - self.session.set(base_path + ["ssl", "key-file", cert_key]) - - self.session.commit() - - # Check for running process - self.assertTrue("ocserv-main" in (p.name() for p in process_iter())) - -if __name__ == '__main__': - unittest.main() diff --git a/smoketest/scripts/cli/test_vpn_openconnect.py b/smoketest/scripts/cli/test_vpn_openconnect.py new file mode 100755 index 000000000..d2b82d686 --- /dev/null +++ b/smoketest/scripts/cli/test_vpn_openconnect.py @@ -0,0 +1,58 @@ +#!/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 re +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +OCSERV_CONF = '/run/ocserv/ocserv.conf' +base_path = ['vpn', 'openconnect'] +cert = '/etc/ssl/certs/ssl-cert-snakeoil.pem' +cert_key = '/etc/ssl/private/ssl-cert-snakeoil.key' + +class TestVpnOpenconnect(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + + def tearDown(self): + # Delete vpn openconnect configuration + self.session.delete(base_path) + self.session.commit() + + del self.session + + def test_vpn(self): + user = 'vyos_user' + password = 'vyos_pass' + self.session.delete(base_path) + self.session.set(base_path + ["authentication", "local-users", "username", user, "password", password]) + self.session.set(base_path + ["authentication", "mode", "local"]) + self.session.set(base_path + ["network-settings", "client-ip-settings", "subnet", "192.0.2.0/24"]) + self.session.set(base_path + ["ssl", "ca-cert-file", cert]) + self.session.set(base_path + ["ssl", "cert-file", cert]) + self.session.set(base_path + ["ssl", "key-file", cert_key]) + + self.session.commit() + + # Check for running process + self.assertTrue("ocserv-main" in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() diff --git a/src/conf_mode/vpn_anyconnect.py b/src/conf_mode/vpn_anyconnect.py deleted file mode 100755 index 158e1a117..000000000 --- a/src/conf_mode/vpn_anyconnect.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/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'] - if not conf.exists(base): - return None - - 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/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py new file mode 100755 index 000000000..af8604972 --- /dev/null +++ b/src/conf_mode/vpn_openconnect.py @@ -0,0 +1,135 @@ +#!/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', 'openconnect'] + if not conf.exists(base): + return None + + 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('openconnect 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('openconnect authentication mode required') + else: + raise ConfigError('openconnect 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('openconnect ssl {0} required'.format(cert.replace('_', '-'))) + else: + raise ConfigError('openconnect 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('openconnect 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/op_mode/anyconnect-control.py b/src/op_mode/anyconnect-control.py deleted file mode 100755 index 6382016b7..000000000 --- a/src/op_mode/anyconnect-control.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/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() diff --git a/src/op_mode/openconnect-control.py b/src/op_mode/openconnect-control.py new file mode 100755 index 000000000..ef9fe618c --- /dev/null +++ b/src/op_mode/openconnect-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 openconnect 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 openconnect sessions") + +def is_ocserv_configured(): + if not Config().exists_effective('vpn openconnect'): + print("vpn openconnect 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 Openconnect server 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