summaryrefslogtreecommitdiff
path: root/smoketest/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'smoketest/scripts')
-rw-r--r--smoketest/scripts/cli/base_vyostest_shim.py5
-rwxr-xr-xsmoketest/scripts/cli/test_configd_inspect.py110
-rw-r--r--smoketest/scripts/cli/test_service_stunnel.py624
-rwxr-xr-xsmoketest/scripts/cli/test_system_login.py10
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_openconnect.py52
5 files changed, 665 insertions, 136 deletions
diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py
index efaa74fe0..4bcc50453 100644
--- a/smoketest/scripts/cli/base_vyostest_shim.py
+++ b/smoketest/scripts/cli/base_vyostest_shim.py
@@ -74,6 +74,11 @@ class VyOSUnitTestSHIM:
print('del ' + ' '.join(config))
self._session.delete(config)
+ def cli_discard(self):
+ if self.debug:
+ print('DISCARD')
+ self._session.discard()
+
def cli_commit(self):
self._session.commit()
# during a commit there is a process opening commit_lock, and run() returns 0
diff --git a/smoketest/scripts/cli/test_configd_inspect.py b/smoketest/scripts/cli/test_configd_inspect.py
deleted file mode 100755
index af46c6148..000000000
--- a/smoketest/scripts/cli/test_configd_inspect.py
+++ /dev/null
@@ -1,110 +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 <http://www.gnu.org/licenses/>.
-
-import os
-import re
-import json
-import unittest
-import warnings
-import importlib.util
-from inspect import signature, getsource
-from functools import wraps
-
-from vyos.defaults import directories
-
-INC_FILE = '/usr/share/vyos/configd-include.json'
-CONF_DIR = directories['conf_mode']
-
-f_list = ['get_config', 'verify', 'generate', 'apply']
-
-def import_script(s):
- path = os.path.join(CONF_DIR, s)
- name = os.path.splitext(s)[0].replace('-', '_')
- spec = importlib.util.spec_from_file_location(name, path)
- module = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(module)
- return module
-
-# importing conf_mode scripts imports jinja2 with deprecation warning
-def ignore_deprecation_warning(f):
- @wraps(f)
- def decorated_function(*args, **kwargs):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore")
- f(*args, **kwargs)
- return decorated_function
-
-class TestConfigdInclude(unittest.TestCase):
- def setUp(self):
- with open(INC_FILE) as f:
- self.inc_list = json.load(f)
-
- @ignore_deprecation_warning
- def test_signatures(self):
- for s in self.inc_list:
- m = import_script(s)
- for i in f_list:
- f = getattr(m, i, None)
- if not f:
- continue
- sig = signature(f)
- par = sig.parameters
- l = len(par)
- self.assertEqual(l, 1,
- f"'{s}': '{i}' incorrect signature")
- if i == 'get_config':
- for p in par.values():
- self.assertTrue(p.default is None,
- f"'{s}': '{i}' incorrect signature")
-
- @ignore_deprecation_warning
- def test_function_instance(self):
- for s in self.inc_list:
- m = import_script(s)
- for i in f_list:
- f = getattr(m, i, None)
- if not f:
- continue
- str_f = getsource(f)
- # Regex not XXXConfig() T3108
- n = len(re.findall(r'[^a-zA-Z]Config\(\)', str_f))
- if i == 'get_config':
- self.assertEqual(n, 1,
- f"'{s}': '{i}' no instance of Config")
- if i != 'get_config':
- self.assertEqual(n, 0,
- f"'{s}': '{i}' instance of Config")
-
- @ignore_deprecation_warning
- def test_file_instance(self):
- for s in self.inc_list:
- m = import_script(s)
- str_m = getsource(m)
- # Regex not XXXConfig T3108
- n = len(re.findall(r'[^a-zA-Z]Config\(\)', str_m))
- self.assertEqual(n, 1,
- f"'{s}' more than one instance of Config")
-
- @ignore_deprecation_warning
- def test_config_modification(self):
- for s in self.inc_list:
- m = import_script(s)
- str_m = getsource(m)
- n = str_m.count('my_set')
- self.assertEqual(n, 0, f"'{s}' modifies config")
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_stunnel.py b/smoketest/scripts/cli/test_service_stunnel.py
new file mode 100644
index 000000000..3aeffd09e
--- /dev/null
+++ b/smoketest/scripts/cli/test_service_stunnel.py
@@ -0,0 +1,624 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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 <http://www.gnu.org/licenses/>.
+
+import re
+import unittest
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+
+from vyos.configsession import ConfigSessionError
+from vyos.utils.process import process_named_running
+from vyos.utils.file import read_file
+
+
+PROCESS_NAME = 'stunnel'
+STUNNEL_CONF = '/run/stunnel/stunnel.conf'
+base_path = ['service', 'stunnel']
+
+ca_certificate = """
+MIIDnTCCAoWgAwIBAgIUcSMo/zT/GUAyH3uM3Hr3qjCDmMUwDQYJKoZIhvcNAQELBQAwVzELMAkGA1U
+EBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVn
+lPUzEQMA4GA1UEAwwHdnlvcy5pbzAeFw0yNDA2MDQwNjU1MDFaFw0yOTA2MDMwNjU1MDFaMFcxCzAJB
+gNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQHDAlTb21lLUNpdHkxDTALBgNVBAoM
+BFZ5T1MxEDAOBgNVBAMMB3Z5b3MuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzN7B
+Zw0OBBgeGL7KCKdDIUfBEhh08+3V8Nm7K23mU/pYd3bR5WXt9VWkW5YWUw1hr1N3qEQ2AZX8TrIDj37
+zzy1jyDCvJHGWnKTOOAboNIInP+PvUQrSH8SDAw/+/KjKKgM069NFhGq9TTHg4BAYC0GsZL+JE3Ptee
+cIVmekf5Dw+vnD0Mlwx5Ouaf/9OwRcGhfwEkIORQLXDuMayOI/JdFbaDVlA6Z/d8GLp3Xlc8/l5XFtg
+fvMNQSB9B69Cs4qwU/yey8tPWeDBiW6Cx2XOnKqiNBaCY1BzvSH+hmHcos1DOLHgEZ3d2zaNn2mrhmB
+Ry7/5Ww7O5PoF00OB9WHFAgMBAAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB
+0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAdBgNVHQ4EFgQU4zgMpOMOweRZUbeNewJnh5xZL
+XwwDQYJKoZIhvcNAQELBQADggEBAAEK+jXvCKuC/n8qu9XFcLYfO3kUKPlXD30V61KRZilHyYGYu0MY
+sSNeX8+K7CpeAo06HHocrrDfCKltoLFuix7qblr2DEub+v3V21pllMfThkz9FsXWFGfmOyI7sXNXUg9
+cVQHzj2SvMj+IfnJoCIuYnigmlKVTuxV31iYv2RpML/PBw29xI0G/AsmXZK4wOQ0eA9gU+ggURE98hG
+8f4DRpGVnlyP1d+P2Va0bsl3Yek9QfrotnmE1EzwZzPZyCL9rv8oDjfJ98O3YqoNSRNvD+Glke2ZlTj
+WFw+uCj0GTki5+V40E9X9Rwcje+s/5zWDBfu0akufcI1nsu++rZz/s=
+"""
+
+ca_private_key = """
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCzN7BZw0OBBgeGL7KCKdDIUfBEhh0
+8+3V8Nm7K23mU/pYd3bR5WXt9VWkW5YWUw1hr1N3qEQ2AZX8TrIDj37zzy1jyDCvJHGWnKTOOAboNII
+nP+PvUQrSH8SDAw/+/KjKKgM069NFhGq9TTHg4BAYC0GsZL+JE3PteecIVmekf5Dw+vnD0Mlwx5Ouaf
+/9OwRcGhfwEkIORQLXDuMayOI/JdFbaDVlA6Z/d8GLp3Xlc8/l5XFtgfvMNQSB9B69Cs4qwU/yey8tP
+WeDBiW6Cx2XOnKqiNBaCY1BzvSH+hmHcos1DOLHgEZ3d2zaNn2mrhmBRy7/5Ww7O5PoF00OB9WHFAgM
+BAAECggEAHFC/pacCutdrh+lwUD1wFb5QclsoMnLeYJYvEhD0GDTTHfvh4ExhhO9iL7Jq1RK6HStgNn
+OkSPWASuj14kr+zRwDPRbsMhWw/+S0FwsxzJIoA/poO2SgplvUG3C8LwVpP9XS1y5ICIoRSl1qHxuPo
+ZExYqTcoJmzg31ES2pqWVXPx14DdpE6yvSL2XwFS4mb291OkydnvKSBcK0MwgEWLQHouzMjihJ1MCXx
+7NXsOxFX76OpmywMW7EtTLEngxL9b61hCYwWeNxmx9pN8qRzmvayKl40VLyqAlVcElZ7aEK0+O/Qpsu
+QhsFRjA4HcXUqlHbvh92OqX+QmBU2RIZ27wKBgQDnJ8E8cJOlJ9ZvFBfw8az49IX9E72oxb2yaXm0Eo
+OQ2Jz88+b2jzWqf3wdGvigNO25DbdYYodR7iJJo4OYPuyAnkJMWdPQ91ADo7ABwJiBqtUHC+Gvq5Rmm
+I2T3T4+Vqu5Sa8lVfHWfv7Pnb++I5/7bH+VuGspyf+0NcpPh9UfIwKBgQDGet1wh0+2378HnnQNb10w
+wxDiMC2hP+3RGPB6bKHLJ60LE+Ed2KFY+j8Q1+jQk9eMe6A75bwB/q6rMO1evpauCHTJoA863HxXtuL
+P9ozVpDk9k4TbiSOsD0s8TXL3XG1ANshk4VfuLboKj4MEwiuxfGt6QGpsgLfHcmlkFIM99wKBgQDeea
+C97wvrVOBJoGk6eSAlrBKZdTqBCXB+Go4MBhWifxj5TDXq8AKSyohF6wOIDekOxmjEJHBhJnTRsxKgo
+U82qxrcKUh4Qs878Xsg9KDTi/vkAEeCr/zwkbsRqUqS7Q/yET0FDibobuoIIKe+9MKxVcel7g0V91in
+tW22BeHVSQKBgQCKctwSiaCWTP8A/ouvb3ZO9FLLpJW/vEtUpxPgIfS+NH/lkUlfu2PZID5rrmAtVmN
+uEDJWdcsujQwkSC3cABA1d5qXpnnZMkHeIamXLUFSKYrwI/3x8XibpdNyTgga+jMPLuecTwA6GVWD1l
+WrNRKrbMG/9j0GUMdhbbKMaC6gQwKBgQCC9EUZBqCXS167OZNPQN4oKx6nJ9uTKUVyPigr12cMpPL6t
+JwZAVVwSnyg+cVznNrMhAnG547c0NnoOe+nd9zczLJOuQHHLSMZUH08c2ZWtwpwbHDWI55hfZL4te8e
+dEcxanXNYAfSMMtOoA+LmcCtfvqld/EucAN4mKTPGmWPQg==
+"""
+
+srv_certificate = """
+MIIDsTCCApmgAwIBAgIUIvMZU3zc3iYl6JzbDLSvr8NOK5swDQYJKoZIhvcNAQELBQAwVzELMAkGA1U
+EBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVn
+lPUzEQMA4GA1UEAwwHdnlvcy5pbzAeFw0yNDA2MDQwNjU1NDVaFw0yNTA2MDQwNjU1NDVaMFcxCzAJB
+gNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQHDAlTb21lLUNpdHkxDTALBgNVBAoM
+BFZ5T1MxEDAOBgNVBAMMB3Z5b3MuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtani
+zx0h1fEH0pMRBB7V7nUAnSOAiCRUNpeTz6RoUqH0y/UaxM+kqitUm+MSAWxEJAXW4ZlxNzU+tC6DOwP
+d+7/rZsT6fKeCbMIs8Es9VaXd2sZzb7DajEygeyIy1b3JGXIiNJ9KcOxzhmu5VHe+6qLCO3FDt4iFIr
+HXJxwQKm8qL6zgn7f9kboQYBHKOhY8x+ghkhLYAwMlvIHGwjF+I/p65J1LOBhAsmOLcX0/CygKXz5qe
+wyG16zNft6OWPIOBTs56NnNlW6EdqomxBM5SWr888qEjUy0ruUpAH4Ug8SloL+AeDW+TqUUcfoOiTi9
+3ZJ/t9YRj0+wQw4vakpUTAgMBAAGjdTBzMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1
+UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBTCubAbczcJE76YabOv+2oVV1zNSzAfBgNVHSMEGDAWg
+BTjOAyk4w7B5FlRt417AmeHnFktfDANBgkqhkiG9w0BAQsFAAOCAQEAjW9ovWDgEoUi8DWwNVtudKiT
+6ylJTSMqY7C+qJlRHpnZ64TNZFXI0BldYZr0QXGsZ257m9m9BiUcZr6UR0hywy4SiyxuteufniKIp9E
+vqv0aJhdTXO+l5msaGWu7YvWYqXW0m3rA9oiNYyBcNSFzlwiyvztYUmFFPrvhFHVSt+DuxZSltdf78G
+exS4YRMCTI+cuCfBt65Vkss4bNJH7kyWVc5aSQ/vKitMxB10gzsUa7psgS6LsBWxnehd3HKBPaHiWG9
+ssHKhHJWfjifgz0K1Y0/vi33USPJ1cBhWWx/dolXWmSmpfqXpD3Q84YjVWIRnFpQzwbT650v/H+fwB1
+zw==
+"""
+
+srv_private_key = """
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtanizx0h1fEH0pMRBB7V7nUAnSOA
+iCRUNpeTz6RoUqH0y/UaxM+kqitUm+MSAWxEJAXW4ZlxNzU+tC6DOwPd+7/rZsT6fKeCbMIs8Es9VaX
+d2sZzb7DajEygeyIy1b3JGXIiNJ9KcOxzhmu5VHe+6qLCO3FDt4iFIrHXJxwQKm8qL6zgn7f9kboQYB
+HKOhY8x+ghkhLYAwMlvIHGwjF+I/p65J1LOBhAsmOLcX0/CygKXz5qewyG16zNft6OWPIOBTs56NnNl
+W6EdqomxBM5SWr888qEjUy0ruUpAH4Ug8SloL+AeDW+TqUUcfoOiTi93ZJ/t9YRj0+wQw4vakpUTAgM
+BAAECggEAEa54SyBSb4QxYg/bYM636Y2G3oU229GK6il+4YMOy99tZeG0L6+IInR7DO5ddBbqSD2esq
+QL3PTw9EcUvi/9AYjXeL3H5vOeo+7Rq4OMIfx5wp+Ty6AB5s5hD1kfG7AWzzzHwYNiHS2Gdtb/XldfO
+5bP6xO5/rSenynSbWCTir8yakfoDenT12CXWzU+T10MKhoTXb/Uao+bMjziKEviK6OWq0vsLlDqyOAE
+Va685s7T0vHTfSs+yK9pqVypHXbkH1nJCoi9P4pcJ4Sslc3meStv3bqg8T62Ufv8QkQLTfJyKZlR1aV
+9ZjWT84YoH1XRnnkAZ+BMC267sHeBJbu6EQKBgQDbIUjQh/iPlkK77tFa//gSMD5ouJtuwtdS1MJ44p
+C81A140vjpkSCdU8zWRifi+akR1k6fXCp6VFUFvTCXkGlpbD4TNjCCRJjS4SoQ89jEnePQ2iS59jkn3
+V3OPNitOzk0jEm/x3R5wNdPlSX6+pLiUZAtMgcmCMv205VOkeqx8QKBgQDKmB3FtEfkKRrGkOJgaEkY
+iXp9b0Uy8peBoTcdqMMnXSlm9+CfIdhSwbQDiAhEcUeCE/S6TDqaMS+ekKFfs6kDlaJMStGsy81lwr5
+W/oZOldajDCu1CDInc+czkep10lsHdQwr71zXntiK3Fwq8Mr3ROBSpaH+DWIjILiQIOMzQwKBgQC7Mt
+UUqIQUjkZWbG/XcMLJLwOxzLukRLlUXsQAJ3WEixczN/BDAKM/JB7ikq5yfdwMi+tAwqjbNn4n1/bSF
+CGpWToyiWGpd9aimI6qStbNKSE9A47KeulbAAaqMFreqrB1Dr/WIRuFA9QsfXsjzLp8szcbFRj8ShmM
+tDZiF8/K0QKBgQCYbb0wzESu8RJZRhddC/m7QWzsxXReMdI2UTLj2N8EVf7ZnzTc5h0Znu4vHgGCZWy
+0/QjLxqDs9Ibsmcsg807+CG51UnHRvgFLSCvnzlcE943nXTfhXEpIDtdsoKO0hFHDGZjP0aeb/8LTL5
+sVH9jGFIdnB4ILYMxuu6bBokzvewKBgBWbjPppjrM46bZ0rwEYCcG0F/k6TKkw4pjyrDR4B0XsrqTjK
+0yz0ga7FHe10saeS2cXMqygdkjhWLZ6Zhrp0LAEzhEvdiBYeRH37J9Bvwo2YIHakox4hJCSXNnELs/A
+GhUb5YIISNnZnZZeUD/Z0IJXJryjk9eUbhDCgEZRVzeT
+"""
+
+
+def get_config_value(key):
+ tmp = read_file(STUNNEL_CONF)
+ tmp = re.findall(f'\n?{key}\s+(.*)', tmp)
+ return tmp
+
+
+def read_config():
+ config = {'global': {},
+ 'services': {}
+ }
+ service_pattern = re.compile(r'\[(.+?)\]')
+ key_value_pattern = re.compile(r'(\S+)\s*=\s*(.+)')
+ service = None
+
+ for line in read_file(STUNNEL_CONF).split('\n'):
+ line.strip()
+ if not line or line.startswith(';'):
+ continue
+ if service_pattern.match(line):
+ service = line.strip('[]')
+ config['services'][service] = {}
+ key_value_match = key_value_pattern.match(line)
+ if key_value_match:
+ key, value = key_value_match.group(1), key_value_match.group(2)
+ if service:
+ apply_value(config['services'][service], key, value)
+ else:
+ apply_value(config['global'], key, value)
+
+ return config
+
+
+def apply_value(service_config, key, value):
+ if service_config.get(key) is None:
+ service_config[key] = value
+ else:
+ if not isinstance(service_config[key], list):
+ service_config[key] = [
+ service_config[key]]
+ else:
+ service_config[key].append(value)
+
+
+class TestServiceStunnel(VyOSUnitTestSHIM.TestCase):
+ maxDiff = None
+ @classmethod
+ def setUpClass(cls):
+ super(TestServiceStunnel, cls).setUpClass()
+
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration :)
+ cls.cli_delete(cls, base_path)
+ cls.is_valid_conf = True
+
+ def tearDown(self):
+ # Check for running process
+ if self.is_valid_conf:
+ self.assertTrue(process_named_running(PROCESS_NAME))
+ self.is_valid_conf = True
+ # delete testing Stunnel config
+ self.cli_delete(base_path)
+ self.cli_delete(['pki'])
+ self.cli_commit()
+
+ # Check for stopped process
+ self.assertFalse(process_named_running(PROCESS_NAME))
+
+ def set_pki(self):
+ self.cli_set(['pki', 'ca', 'ca-1', 'certificate', ca_certificate.replace('\n','')])
+ self.cli_set(['pki', 'ca', 'ca-1', 'private', 'key', ca_private_key.replace('\n','')])
+ self.cli_set(['pki', 'certificate', 'srv-1', 'certificate', srv_certificate.replace('\n','')])
+ self.cli_set(['pki', 'certificate', 'srv-1', 'private', 'key', srv_private_key.replace('\n','')])
+ self.cli_commit()
+
+ def test_01_stunnel_simple_client(self):
+ service = 'app1'
+ self.cli_set(base_path + ['client', service, 'connect', 'port', '9001'])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + ['client', service, 'listen', 'port', '8001'])
+
+ self.cli_commit()
+ config = read_config()
+
+ self.assertEqual('/run/stunnel/stunnel.pid', config['global']['pid'])
+ self.assertEqual('notice', config['global']['debug'])
+ self.assertListEqual([service], list(config['services']))
+ self.assertEqual('8001', config['services'][service]['accept'])
+ self.assertEqual('9001', config['services'][service]['connect'])
+ self.assertEqual('yes', config['services'][service]['client'])
+
+ def test_02_stunnel_simple_server(self):
+ service = 'ser1'
+ self.set_pki()
+ self.cli_set(base_path + ['server', service, 'connect', 'port', '8080'])
+ self.cli_set(base_path + ['server', service, 'ssl', 'certificate', 'srv-1'])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + ['server', service, 'listen', 'port', '9001'])
+
+ self.cli_commit()
+ config = read_config()
+
+ self.assertEqual('/run/stunnel/stunnel.pid', config['global']['pid'])
+ self.assertEqual('notice', config['global']['debug'])
+ self.assertListEqual([service], list(config['services']))
+ self.assertEqual('9001', config['services'][service]['accept'])
+ self.assertEqual('8080', config['services'][service]['connect'])
+ self.assertIsNone(config['services'][service].get('client'))
+ self.assertEqual('/run/stunnel/server-ser1-srv-1.pem', config['services'][service]['cert'])
+ self.assertEqual('/run/stunnel/server-ser1-srv-1.pem.key', config['services'][service]['key'])
+
+ def test_03_multy_services(self):
+ self.set_pki()
+ clients = ['app1', 'app2', 'app3']
+ servers = ['serv1', 'serv2', 'serv3']
+ port = 80
+ for service in clients:
+ port += 1
+ self.cli_set(base_path + ['client', service, 'listen', 'port', f'{port}'])
+ port += 1
+ self.cli_set(base_path + ['client', service, 'connect', 'port', f'{port}'])
+ if service == 'app2':
+ self.cli_set(base_path + ['client', service, 'connect', 'address', f'192.168.0.10'])
+ self.cli_set(base_path + ['client', service, 'listen', 'address', '127.0.0.1'])
+ self.cli_set(base_path + ['client', service, 'protocol', 'connect'])
+ self.cli_set(base_path + ['client', service, 'options', 'authentication', 'basic'])
+ self.cli_set(base_path + ['client', service, 'options', 'domain', 'basic.com'])
+ self.cli_set(base_path + ['client', service, 'options', 'host', 'address', '127.0.0.1'])
+ self.cli_set(base_path + ['client', service, 'options', 'host', 'port', '5000'])
+ self.cli_set(base_path + ['client', service, 'options', 'password', 'test_pass'])
+ self.cli_set(base_path + ['client', service, 'options', 'username', 'test'])
+ if service == 'app3':
+ self.cli_set(base_path + ['client', service, 'ssl', 'ca-certificate', 'ca-1'])
+ self.cli_set(base_path + ['client', service, 'ssl', 'certificate', 'srv-1'])
+
+ for service in servers:
+ port += 1
+ self.cli_set(base_path + ['server', service, 'listen', 'port', f'{port}'])
+ port += 1
+ self.cli_set(base_path + ['server', service, 'connect', 'port', f'{port}'])
+ self.cli_set(base_path + ['server', service, 'ssl', 'certificate', 'srv-1'])
+ if service == 'serv2':
+ self.cli_set(base_path + ['server', service, 'ssl', 'ca-certificate', 'ca-1'])
+ self.cli_set(base_path + ['server', service, 'connect', 'address', f'google.com'])
+ self.cli_set(base_path + ['server', service, 'listen', 'address', f'127.0.0.1'])
+ if service == 'serv3':
+ self.cli_set(base_path + ['server', service, 'connect', 'address', f'10.18.105.10'])
+ self.cli_set(base_path + ['server', service, 'protocol', 'imap'])
+
+ self.cli_commit()
+ config = read_config()
+
+ self.assertEqual('/run/stunnel/stunnel.pid', config['global']['pid'])
+ self.assertListEqual(clients + servers, list(config['services']))
+ self.assertDictEqual(config['services'], {
+ 'app1': {
+ 'client': 'yes',
+ 'accept': '81',
+ 'connect': '82'
+ },
+ 'app2': {
+ 'client': 'yes',
+ 'accept': '127.0.0.1:83',
+ 'connect': '192.168.0.10:84',
+ 'protocol': 'connect',
+ 'protocolAuthentication': 'basic',
+ 'protocolDomain': 'basic.com',
+ 'protocolHost': '127.0.0.1:5000',
+ 'protocolPassword': 'test_pass',
+ 'protocolUsername': 'test'
+ },
+ 'app3': {
+ 'client': 'yes',
+ 'accept': '85',
+ 'connect': '86',
+ 'CApath': '/run/stunnel/ca',
+ 'CAfile': 'client-app3-ca.pem',
+ 'cert': '/run/stunnel/client-app3-srv-1.pem',
+ 'key': '/run/stunnel/client-app3-srv-1.pem.key'
+ },
+ 'serv1': {
+ 'accept': '87',
+ 'connect': '88',
+ 'cert': '/run/stunnel/server-serv1-srv-1.pem',
+ 'key': '/run/stunnel/server-serv1-srv-1.pem.key'
+ },
+ 'serv2': {
+ 'accept': '127.0.0.1:89',
+ 'connect': 'google.com:90',
+ 'CApath': '/run/stunnel/ca',
+ 'CAfile': 'server-serv2-ca.pem',
+ 'cert': '/run/stunnel/server-serv2-srv-1.pem',
+ 'key': '/run/stunnel/server-serv2-srv-1.pem.key'
+ },
+ 'serv3': {
+ 'accept': '91',
+ 'connect': '10.18.105.10:92',
+ 'protocol': 'imap',
+ 'cert': '/run/stunnel/server-serv3-srv-1.pem',
+ 'key': '/run/stunnel/server-serv3-srv-1.pem.key'
+ }
+ })
+
+ def test_04_cert_problems(self):
+ service = 'app1'
+ self.cli_set(base_path + ['client', service, 'connect', 'port', '9001'])
+ self.cli_set(base_path + ['client', service, 'listen', 'port', '8001'])
+ self.cli_set(base_path + ['client', service, 'ssl', 'ca-certificate', 'ca-2'])
+
+ # ca not exist in pki
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(base_path + ['client', service, 'ssl', 'ca-certificate', 'ca-2'])
+ self.cli_set(base_path + ['client', service, 'ssl', 'certificate', 'srv-2'])
+
+ # cert not exist in pki
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path)
+
+ self.cli_set(base_path + ['server', service, 'connect', 'port', '8080'])
+ self.cli_set(base_path + ['server', service, 'listen', 'port', '9001'])
+
+ # Create server without any cert
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + ['server', service, 'ssl', 'ca-certificate', 'ca-2'])
+ # ca not exist in pki
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(base_path + ['server', service, 'ssl', 'ca-certificate', 'ca-2'])
+ self.cli_set(base_path + ['server', service, 'ssl', 'certificate', 'srv-2'])
+ # cert not exist in pki
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.is_valid_conf = False
+
+ def test_05_psk_auth(self):
+ modes = ['client', 'server']
+ psk_id_1 = 'psk_id_1'
+ psk_secret_1 = '1234567890ABCDEF1234567890ABCDEF'
+ psk_id_2 = 'psk_id_2'
+ psk_secret_2 = '1234567890ABCDEF1234567890ABCDEA'
+ expected_config = {
+ 'global': {'pid': '/run/stunnel/stunnel.pid',
+ 'debug': 'notice'},
+ 'services': {}}
+ port = 8000
+ for mode in modes:
+ service = f'{mode}-one'
+ psk_secrets = f'/run/stunnel/psk/{mode}_{service}.txt'
+ expected_config['services'][service] = {
+ 'PSKsecrets': psk_secrets,
+ }
+ port += 1
+ expected_config['services'][service]['accept'] = f'{port}'
+ self.cli_set(base_path + [mode, service, 'listen', 'port', f'{port}'])
+ port += 1
+ expected_config['services'][service]['connect'] = f'{port}'
+ self.cli_set(base_path + [mode, service, 'connect', 'port', f'{port}'])
+ self.cli_set(base_path + [mode, service, 'psk', 'smoketest1', 'id', psk_id_1])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_set(base_path + [mode, service, 'psk', 'smoketest1', 'secret', '123'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_set(base_path + [mode, service, 'psk', 'smoketest1', 'secret', '1234567890ABCDEF1234567890ABCDEZ'])
+ self.cli_set(base_path + [mode, service, 'psk', 'smoketest1', 'secret', psk_secret_1])
+ self.cli_set(base_path + [mode, service, 'psk', 'smoketest2', 'id', psk_id_2])
+ self.cli_set(base_path + [mode, service, 'psk', 'smoketest2', 'secret', psk_secret_2])
+ if mode != 'server':
+ expected_config['services'][service]['client'] = 'yes'
+
+ self.cli_commit()
+ config = read_config()
+
+ self.assertDictEqual(expected_config, config)
+
+ self.assertListEqual([f'{psk_id_1}:{psk_secret_1}',
+ f'{psk_id_2}:{psk_secret_2}'],
+ [line for line in read_file(psk_secrets).split('\n')])
+
+ def test_06_socks_proxy(self):
+ server_port = '9001'
+ client_port = '9000'
+ srv_name = 'srv-one'
+ cli_name = 'cli-one'
+ expected_config = {
+ 'global': {'pid': '/run/stunnel/stunnel.pid',
+ 'debug': 'notice'},
+ 'services': {
+ 'cli-one': {
+ 'PSKsecrets': f'/run/stunnel/psk/client_{cli_name}.txt',
+ 'client': 'yes',
+ 'accept': client_port,
+ 'connect': server_port
+ },
+ 'srv-one': {
+ 'PSKsecrets': f'/run/stunnel/psk/server_{srv_name}.txt',
+ 'accept': server_port,
+ 'protocol': 'socks'
+ }
+ }}
+
+ self.cli_set(base_path + ['server', srv_name, 'listen', 'port', server_port])
+ self.cli_set(base_path + ['server', srv_name, 'connect', 'port', '9005'])
+ self.cli_set(base_path + ['server', srv_name, 'protocol', 'socks'])
+ self.cli_set(base_path + ['server', srv_name, 'psk', 'sock_proxy', 'id', cli_name])
+ self.cli_set(base_path + ['server', srv_name, 'psk', 'sock_proxy', 'secret', '1234567890ABCDEF1234567890ABCDEF'])
+
+ self.cli_set(base_path + ['client', cli_name, 'listen', 'port', client_port])
+ self.cli_set(base_path + ['client', cli_name, 'connect', 'port', server_port])
+ self.cli_set(base_path + ['client', cli_name, 'psk', 'sock_proxy', 'id', cli_name])
+ self.cli_set(base_path + ['client', cli_name, 'psk', 'sock_proxy', 'secret', '1234567890ABCDEF1234567890ABCDEF'])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(base_path + ['server', srv_name, 'connect'])
+ self.cli_commit()
+ config = read_config()
+
+ self.assertDictEqual(expected_config, config)
+
+ def test_07_available_port(self):
+ expected_config = {
+ 'global': {'pid': '/run/stunnel/stunnel.pid',
+ 'debug': 'notice'},
+ 'services': {
+ 'app1': {
+ 'client': 'yes',
+ 'accept': '8001',
+ 'connect': '9001'
+ },
+ 'srv1': {
+ 'PSKsecrets': f'/run/stunnel/psk/server_srv1.txt',
+ 'accept': '127.0.0.1:8002',
+ 'connect': '9001'
+ }
+ }}
+ self.cli_set(base_path + ['client', 'app1', 'connect', 'port', '9001'])
+ self.cli_set(base_path + ['client', 'app1', 'listen', 'port', '8001'])
+
+ self.cli_set(base_path + ['server', 'srv1', 'connect', 'port', '9001'])
+ self.cli_set(base_path + ['server', 'srv1', 'listen', 'address',
+ '127.0.0.1'])
+ self.cli_set(base_path + ['server', 'srv1', 'listen', 'port', '8001'])
+ self.cli_set(base_path + ['server', 'srv1', 'psk', 'smoketest1',
+ 'id', 'foo'])
+ self.cli_set(base_path + ['server', 'srv1', 'psk', 'smoketest1',
+ 'secret', '1234567890ABCDEF1234567890ABCDEF'])
+
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + ['server', 'srv1', 'listen', 'port', '8002'])
+ self.cli_commit()
+
+ config = read_config()
+ self.assertDictEqual(expected_config, config)
+
+ def test_08_two_endpoints(self):
+ expected_config = {
+ 'global': {'pid': '/run/stunnel/stunnel.pid',
+ 'debug': 'notice'},
+ 'services': {
+ 'app1': {
+ 'client': 'yes',
+ 'accept': '8001',
+ 'connect': '9001'
+ }
+ }}
+
+ self.cli_set(base_path + ['client', 'app1', 'listen', 'port', '8001'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_set(base_path + ['client', 'app1', 'connect', 'port', '9001'])
+ self.cli_commit()
+
+ config = read_config()
+ self.assertDictEqual(expected_config, config)
+
+ def test_09_pki_still_used(self):
+ service = 'ser1'
+ self.set_pki()
+ self.cli_set(base_path + ['server', service, 'connect', 'port', '8080'])
+ self.cli_set(base_path + ['server', service, 'listen', 'port', '9001'])
+ self.cli_set(base_path + ['server', service, 'ssl', 'certificate', 'srv-1'])
+ self.cli_commit()
+
+ self.cli_delete(['pki'])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ self.is_valid_conf = False
+
+ def test_99_protocols(self):
+ self.set_pki()
+ service = 'one'
+ proto_address = 'google.com'
+ proto_port = '80'
+ modes = ['client', 'server']
+ protocols = ['cifs', 'connect', 'imap', 'nntp', 'pgsql', 'pop3',
+ 'proxy', 'smtp', 'socks']
+ options = ['authentication', 'domain', 'host', 'password', 'username']
+
+ for protocol in protocols:
+ for mode in modes:
+ expected_config = {
+ 'global': {'pid': '/run/stunnel/stunnel.pid',
+ 'debug': 'notice'},
+ 'services': {'one': {
+ 'accept': '8001',
+ 'protocol': protocol,
+ }}}
+ if not(mode == 'server' and protocol == 'socks'):
+ self.cli_set(base_path + [mode, service, 'connect', 'port', '9001'])
+ expected_config['services']['one']['connect'] = '9001'
+ self.cli_set(base_path + [mode, service, 'listen', 'port', '8001'])
+
+ if mode == 'server':
+ expected_config['services'][service]['cert'] = '/run/stunnel/server-one-srv-1.pem'
+ expected_config['services'][service]['key'] = '/run/stunnel/server-one-srv-1.pem.key'
+ self.cli_set(base_path + [mode, service, 'ssl',
+ 'certificate', 'srv-1'])
+ else:
+ expected_config['services'][service]['client'] = 'yes'
+
+ # protocols connect and nntp is only supported in client mode.
+ if mode == 'server' and protocol in ['connect', 'nntp']:
+ with self.assertRaises(ConfigSessionError):
+ self.cli_set(base_path + [mode, service, 'protocol', protocol])
+ # self.cli_commit()
+ else:
+ self.cli_set(base_path + [mode, service, 'protocol', protocol])
+ self.cli_commit()
+ config = read_config()
+
+ self.assertDictEqual(expected_config, config)
+
+ expected_config['services'][service]['protocolDomain'] = 'valdomain'
+ expected_config['services'][service]['protocolPassword'] = 'valpassword'
+ expected_config['services'][service]['protocolUsername'] = 'valusername'
+
+ for option in options:
+ if option == 'authentication':
+ expected_config['services'][service]['protocolAuthentication'] = \
+ 'basic' if protocol == 'connect' else 'plain'
+ continue
+
+ if option == 'host' and mode != 'server':
+ expected_config['services'][service]['protocolHost'] = \
+ f'{proto_address}:{proto_port}'
+ self.cli_set(base_path + [mode, service, 'options',
+ option, 'address', f'{proto_address}'])
+ self.cli_set(base_path + [mode, service, 'options',
+ option, 'port', f'{proto_port}'])
+ continue
+ if mode == 'server':
+ with self.assertRaises(ConfigSessionError):
+ self.cli_set(
+ base_path + [mode, service, 'options', option, f'val{option}'])
+ else:
+ self.cli_set(
+ base_path + [mode, service, 'options', option, f'val{option}'])
+ # Additional option is only supported in the 'connect' and 'smtp' protocols.
+ if mode != 'server':
+ if protocol not in ['connect', 'smtp']:
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ else:
+ if protocol == 'smtp':
+ # Protocol smtp does not support options domain and host
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_delete(
+ base_path + [mode, service, 'options', 'domain'])
+ self.cli_delete(
+ base_path + [mode, service, 'options', 'host'])
+ del expected_config['services'][service]['protocolDomain']
+ del expected_config['services'][service]['protocolHost']
+
+ self.cli_commit()
+ config = read_config()
+
+ self.assertDictEqual(expected_config, config)
+
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ self.is_valid_conf = False
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py
index 3f249660d..28abba012 100755
--- a/smoketest/scripts/cli/test_system_login.py
+++ b/smoketest/scripts/cli/test_system_login.py
@@ -24,6 +24,7 @@ from subprocess import Popen, PIPE
from pwd import getpwall
from vyos.configsession import ConfigSessionError
+from vyos.utils.auth import get_current_user
from vyos.utils.process import cmd
from vyos.utils.file import read_file
from vyos.template import inc_ip
@@ -334,5 +335,14 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase):
self.assertIn(f'secret={tacacs_secret}', nss_tacacs_conf)
self.assertIn(f'server={server}', nss_tacacs_conf)
+ def test_delete_current_user(self):
+ current_user = get_current_user()
+
+ # We are not allowed to delete the current user
+ self.cli_delete(base_path + ['user', current_user])
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_discard()
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vpn_openconnect.py b/smoketest/scripts/cli/test_vpn_openconnect.py
index a2e426dc7..dcce229e2 100755
--- a/smoketest/scripts/cli/test_vpn_openconnect.py
+++ b/smoketest/scripts/cli/test_vpn_openconnect.py
@@ -106,32 +106,32 @@ n+vZdJAWTq76zAPT3n9FClo=
"""
ca_key_data = """
- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCg7Mjl6+rs8Bd
- kjqgl2QDuHfrH2mTDCeB7WuNTnIz0BPDtlmwIdqhU7LdCB/zUSABAa6LBe/Z/bK
- WCRKyq8fU2/4uWECe975IMXOfFdYT6KA78DROvOi32JZmln0LAXV+538eb+g19x
- NtoBhPO8igiNevfkV+nJehRK/41ATj+assTOv87vaSX7WqyaP/ZqkIdQD9Kc3cq
- B4JsYjkWcniHL9yk4oY3cjKK8PJ1pi4FqgFHt2hA+Ic+NvbAhc47K9otP8FM4jk
- Sii3MZfHA6Czb43BtbR+YEiWPzBhzE2bCuIgeRUumMF1Z+CAT6U7Cpx3XPh+Ac2
- RnDa8wKeQ1eqE1AgMBAAECggEAEDDaoqVqmMWsONoQiWRMr2h1RZvPxP7OpuKVW
- iF3XgrMOb9HZc+Ybpj1dC+NDMekvNaHhMuF2Lqz6UgjDjzzVMH/x4yfDwFWUqeb
- SxbglvGmVk4zg48JNkmArLT6GJQccD1XXjZZmqSOhagM4KalCpIdxfvgoZbTCa2
- xMSCLHS+1HCDcmpCoeXM6ZBPTn0NbjRDAqIzCwcq2veG7RSz040obk8h7nrdv7j
- hxRGmtPmPFzKgGLNn6GnL7AwYVMiidjj/ntvM4B1OMs9MwUYbtpg98TWcWyu+ZR
- akUrnVf9z2aIHCKyuJvke/PNqMgw+L8KV4/478XxWhXfl7K1F3nMQKBgQDRBUDY
- NFH0wC4MMWsA+RGwyz7RlzACChDJCMtA/agbW06gUoE9UYf8KtLQQQYljlLJHxH
- GD72QnuM+sowGGXnbD4BabA9TQiQUG5c6boznTy1uU1gt8T0Zl0mmC7vIMoMBVd
- 5bb0qrZvuR123kDGYn6crug9uvMIYSSlhGmBGTJQKBgQDFGC3vfkCyXzLoYy+RI
- s/rXgyBF1PUYQtyDgL0N811L0H7a8JhFnt4FvodUbxv2ob+1kIc9e3yXT6FsGyO
- 7IDOnqgeQKy74bYqVPZZuf1FOFb9fuxf00pn1FmhAF4OuSWkhVhrKkyrZwdD8Ar
- jLK253J94dogjdKAYfN1csaOA0QKBgD0zUZI8d4a3QoRVb+RACTr/t6v8nZTrR5
- DlX0XvP2qLKJFutuKyXaOrEkDh2R/j9T9oNncMos+WhikUdEVQ7koC1u0i2LXjF
- tdAYN4+Akmz+DRmeNoy2VYF4w2YP+pVR+B7OPkCtBVNuPkx3743Fy42mTGPMCKy
- jX8Lf59j5Tl1AoGBAI3sk2dZqozHMIlWovIH92CtIKP0gFD2cJ94p3fklvZDSWg
- aeKYg4lffc8uZB/AjlAH9ly3ziZx0uIjcOc/RTg96/+SI/dls9xgUhjCmVVJ692
- ki9GMsau/JYaEl+pTvjcOiocDJfNwQHJM3Tx+3FII59DtyXyXo3T/E6kHNSMeBA
- oGAR9M48DTspv9OH1S7X6yR6MtMY5ltsBmB3gPhQFxiDKBvARkIkAPqObQ9TG/V
- uOz2Purq0Oz7SHsY2jiFDd2KEGo6JfG61NDdIhiQC99ztSgt7NtvSCnX22SfVDW
- oFxSK+tek7tvDVXAXCNy4ZESMEUGJ6NDHImb80aF+xZ3wYKw=
+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
+EUGJ6NDHImb80aF+xZ3wYKw=
"""
PROCESS_NAME = 'ocserv-main'