diff options
Diffstat (limited to 'smoketest')
-rwxr-xr-x | smoketest/scripts/cli/test_config_dependency.py | 85 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_openvpn.py | 186 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_router-advert.py | 29 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_system_option.py | 15 |
4 files changed, 313 insertions, 2 deletions
diff --git a/smoketest/scripts/cli/test_config_dependency.py b/smoketest/scripts/cli/test_config_dependency.py index 14e88321a..99e807ac5 100755 --- a/smoketest/scripts/cli/test_config_dependency.py +++ b/smoketest/scripts/cli/test_config_dependency.py @@ -16,13 +16,39 @@ import unittest +from time import sleep -from base_vyostest_shim import VyOSUnitTestSHIM - +from vyos.utils.process import is_systemd_service_running +from vyos.utils.process import cmd from vyos.configsession import ConfigSessionError +from base_vyostest_shim import VyOSUnitTestSHIM + class TestConfigDep(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + # smoketests are run without configd in 1.4; with configd in 1.5 + # the tests below check behavior under configd: + # test_configdep_error checks for regression under configd (T6559) + # test_configdep_prio_queue checks resolution under configd (T6671) + cls.running_state = is_systemd_service_running('vyos-configd.service') + + if not cls.running_state: + cmd('sudo systemctl start vyos-configd.service') + # allow time for init + sleep(1) + + super(TestConfigDep, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestConfigDep, cls).tearDownClass() + + # return to running_state + if not cls.running_state: + cmd('sudo systemctl stop vyos-configd.service') + def test_configdep_error(self): address_group = 'AG' address = '192.168.137.5' @@ -45,5 +71,60 @@ class TestConfigDep(VyOSUnitTestSHIM.TestCase): self.cli_delete(['nat']) self.cli_commit() + def test_configdep_prio_queue(self): + # confirm that that a dependency (in this case, conntrack -> + # conntrack-sync) is not immediately called if the target is + # scheduled in the priority queue, indicating that it may require an + # intermediate activitation (bond0) + bonding_base = ['interfaces', 'bonding'] + bond_interface = 'bond0' + bond_address = '192.0.2.1/24' + vrrp_group_base = ['high-availability', 'vrrp', 'group'] + vrrp_sync_group_base = ['high-availability', 'vrrp', 'sync-group'] + vrrp_group = 'ETH2' + vrrp_sync_group = 'GROUP' + conntrack_sync_base = ['service', 'conntrack-sync'] + conntrack_peer = '192.0.2.77' + + # simple set to trigger in-session conntrack -> conntrack-sync + # dependency; note that this is triggered on boot in 1.4 due to + # default 'system conntrack modules' + self.cli_set(['system', 'conntrack', 'table-size', '524288']) + + self.cli_set(['interfaces', 'ethernet', 'eth2', 'address', + '198.51.100.2/24']) + + self.cli_set(bonding_base + [bond_interface, 'address', + bond_address]) + self.cli_set(bonding_base + [bond_interface, 'member', 'interface', + 'eth3']) + + self.cli_set(vrrp_group_base + [vrrp_group, 'address', + '198.51.100.200/24']) + self.cli_set(vrrp_group_base + [vrrp_group, 'hello-source-address', + '198.51.100.2']) + self.cli_set(vrrp_group_base + [vrrp_group, 'interface', 'eth2']) + self.cli_set(vrrp_group_base + [vrrp_group, 'priority', '200']) + self.cli_set(vrrp_group_base + [vrrp_group, 'vrid', '22']) + self.cli_set(vrrp_sync_group_base + [vrrp_sync_group, 'member', + vrrp_group]) + + self.cli_set(conntrack_sync_base + ['failover-mechanism', 'vrrp', + 'sync-group', vrrp_sync_group]) + + self.cli_set(conntrack_sync_base + ['interface', bond_interface, + 'peer', conntrack_peer]) + + self.cli_commit() + + # clean up + self.cli_delete(bonding_base) + self.cli_delete(vrrp_group_base) + self.cli_delete(vrrp_sync_group_base) + self.cli_delete(conntrack_sync_base) + self.cli_delete(['interfaces', 'ethernet', 'eth2', 'address']) + self.cli_delete(['system', 'conntrack', 'table-size']) + self.cli_commit() + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py index d8a091aaa..e087b8735 100755 --- a/smoketest/scripts/cli/test_interfaces_openvpn.py +++ b/smoketest/scripts/cli/test_interfaces_openvpn.py @@ -250,6 +250,67 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): interface = f'vtun{ii}' self.assertNotIn(interface, interfaces()) + def test_openvpn_client_ip_version(self): + # Test the client mode behavior combined with different IP protocol versions + + interface = 'vtun10' + remote_host = '192.0.2.10' + remote_host_v6 = 'fd00::2:10' + path = base_path + [interface] + auth_hash = 'sha1' + + # Default behavior: client uses uspecified protocol version (udp) + self.cli_set(path + ['device-type', 'tun']) + self.cli_set(path + ['encryption', 'data-ciphers', 'aes256']) + self.cli_set(path + ['hash', auth_hash]) + self.cli_set(path + ['mode', 'client']) + self.cli_set(path + ['persistent-tunnel']) + self.cli_set(path + ['protocol', 'udp']) + self.cli_set(path + ['remote-host', remote_host]) + self.cli_set(path + ['remote-port', remote_port]) + self.cli_set(path + ['tls', 'ca-certificate', 'ovpn_test']) + self.cli_set(path + ['tls', 'certificate', 'ovpn_test']) + self.cli_set(path + ['vrf', vrf_name]) + self.cli_set(path + ['authentication', 'username', interface+'user']) + self.cli_set(path + ['authentication', 'password', interface+'secretpw']) + + self.cli_commit() + + config_file = f'/run/openvpn/{interface}.conf' + config = read_file(config_file) + + self.assertIn(f'dev vtun10', config) + self.assertIn(f'dev-type tun', config) + self.assertIn(f'persist-key', config) + self.assertIn(f'proto udp', config) + self.assertIn(f'rport {remote_port}', config) + self.assertIn(f'remote {remote_host}', config) + self.assertIn(f'persist-tun', config) + + # IPv4 only: client usees udp4 protocol + self.cli_set(path + ['ip-version', 'ipv4']) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp4', config) + + # IPv6 only: client uses udp6 protocol + self.cli_set(path + ['ip-version', 'ipv6']) + self.cli_delete(path + ['remote-host', remote_host]) + self.cli_set(path + ['remote-host', remote_host_v6]) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp6', config) + + # IPv6 dual-stack: not allowed in client mode + self.cli_set(path + ['ip-version', 'dual-stack']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_delete(base_path) + self.cli_commit() + def test_openvpn_server_verify(self): # Create one OpenVPN server interface and check required verify() stages interface = 'vtun5000' @@ -453,6 +514,74 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): interface = f'vtun{ii}' self.assertNotIn(interface, interfaces()) + def test_openvpn_server_ip_version(self): + # Test the server mode behavior combined with each IP protocol version + + auth_hash = 'sha256' + port = '2000' + + interface = 'vtun20' + subnet = '192.0.20.0/24' + path = base_path + [interface] + + # Default behavior: client uses uspecified protocol version (udp) + self.cli_set(path + ['device-type', 'tun']) + self.cli_set(path + ['encryption', 'data-ciphers', 'aes192']) + self.cli_set(path + ['hash', auth_hash]) + self.cli_set(path + ['mode', 'server']) + self.cli_set(path + ['local-port', port]) + self.cli_set(path + ['server', 'subnet', subnet]) + self.cli_set(path + ['server', 'topology', 'subnet']) + + self.cli_set(path + ['replace-default-route']) + self.cli_set(path + ['tls', 'ca-certificate', 'ovpn_test']) + self.cli_set(path + ['tls', 'certificate', 'ovpn_test']) + self.cli_set(path + ['tls', 'dh-params', 'ovpn_test']) + + self.cli_commit() + + start_addr = inc_ip(subnet, '2') + stop_addr = last_host_address(subnet) + + config_file = f'/run/openvpn/{interface}.conf' + config = read_file(config_file) + + self.assertIn(f'dev {interface}', config) + self.assertIn(f'dev-type tun', config) + self.assertIn(f'persist-key', config) + self.assertIn(f'proto udp', config) # default protocol + self.assertIn(f'auth {auth_hash}', config) + self.assertIn(f'data-ciphers AES-192-CBC', config) + self.assertIn(f'topology subnet', config) + self.assertIn(f'lport {port}', config) + self.assertIn(f'push "redirect-gateway def1"', config) + + # IPv4 only: server usees udp4 protocol + self.cli_set(path + ['ip-version', 'ipv4']) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp4', config) + + # IPv6 only: server uses udp6 protocol + bind ipv6only + self.cli_set(path + ['ip-version', 'ipv6']) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp6', config) + self.assertIn(f'bind ipv6only', config) + + # IPv6 dual-stack: server uses udp6 protocol without bind ipv6only + self.cli_set(path + ['ip-version', 'dual-stack']) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp6', config) + self.assertNotIn(f'bind ipv6only', config) + + self.cli_delete(base_path) + self.cli_commit() + def test_openvpn_site2site_verify(self): # Create one OpenVPN site2site interface and check required # verify() stages @@ -627,6 +756,63 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): self.assertNotIn(interface, interfaces()) + def test_openvpn_site2site_ip_version(self): + # Test the site-to-site mode behavior combined with each IP protocol version + + encryption_cipher = 'aes256' + + interface = 'vtun30' + local_address = '192.0.30.1' + local_address_subnet = '255.255.255.252' + remote_address = '172.16.30.1' + path = base_path + [interface] + port = '3030' + + self.cli_set(path + ['local-address', local_address]) + self.cli_set(path + ['device-type', 'tun']) + self.cli_set(path + ['mode', 'site-to-site']) + self.cli_set(path + ['local-port', port]) + self.cli_set(path + ['remote-port', port]) + self.cli_set(path + ['shared-secret-key', 'ovpn_test']) + self.cli_set(path + ['remote-address', remote_address]) + self.cli_set(path + ['encryption', 'cipher', encryption_cipher]) + + self.cli_commit() + + config_file = f'/run/openvpn/{interface}.conf' + config = read_file(config_file) + + self.assertIn(f'dev-type tun', config) + self.assertIn(f'ifconfig {local_address} {remote_address}', config) + self.assertIn(f'proto udp', config) + self.assertIn(f'dev {interface}', config) + self.assertIn(f'secret /run/openvpn/{interface}_shared.key', config) + self.assertIn(f'lport {port}', config) + self.assertIn(f'rport {port}', config) + + # IPv4 only: server usees udp4 protocol + self.cli_set(path + ['ip-version', 'ipv4']) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp4', config) + + # IPv6 only: server uses udp6 protocol + bind ipv6only + self.cli_set(path + ['ip-version', 'ipv6']) + self.cli_commit() + + config = read_file(config_file) + self.assertIn(f'proto udp6', config) + self.assertIn(f'bind ipv6only', config) + + # IPv6 dual-stack: not allowed in site-to-site mode + self.cli_set(path + ['ip-version', 'dual-stack']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_delete(base_path) + self.cli_commit() + def test_openvpn_server_server_bridge(self): # Create OpenVPN server interface using bridge. # Validate configuration afterwards. diff --git a/smoketest/scripts/cli/test_service_router-advert.py b/smoketest/scripts/cli/test_service_router-advert.py index d1ff25a58..6dbb6add4 100755 --- a/smoketest/scripts/cli/test_service_router-advert.py +++ b/smoketest/scripts/cli/test_service_router-advert.py @@ -224,5 +224,34 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase): self.assertIn(tmp, config) self.assertIn('AdvValidLifetime 65528;', config) # default + def test_advsendadvert_advintervalopt(self): + ra_src = ['fe80::1', 'fe80::2'] + + self.cli_set(base_path + ['prefix', prefix]) + self.cli_set(base_path + ['no-send-advert']) + # commit changes + self.cli_commit() + + # Verify generated configuration + config = read_file(RADVD_CONF) + tmp = get_config_value('AdvSendAdvert') + self.assertEqual(tmp, 'off') + + tmp = get_config_value('AdvIntervalOpt') + self.assertEqual(tmp, 'on') + + self.cli_set(base_path + ['no-send-interval']) + # commit changes + self.cli_commit() + + # Verify generated configuration + config = read_file(RADVD_CONF) + tmp = get_config_value('AdvSendAdvert') + self.assertEqual(tmp, 'off') + + tmp = get_config_value('AdvIntervalOpt') + self.assertEqual(tmp, 'off') + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_option.py b/smoketest/scripts/cli/test_system_option.py index c6f48bfc6..ffb1d76ae 100755 --- a/smoketest/scripts/cli/test_system_option.py +++ b/smoketest/scripts/cli/test_system_option.py @@ -80,5 +80,20 @@ class TestSystemOption(VyOSUnitTestSHIM.TestCase): self.assertEqual(sysctl_read('net.ipv4.neigh.default.gc_thresh2'), gc_thresh2) self.assertEqual(sysctl_read('net.ipv4.neigh.default.gc_thresh3'), gc_thresh3) + def test_ssh_client_options(self): + loopback = 'lo' + ssh_client_opt_file = '/etc/ssh/ssh_config.d/91-vyos-ssh-client-options.conf' + + self.cli_set(['system', 'option', 'ssh-client', 'source-interface', loopback]) + self.cli_commit() + + tmp = read_file(ssh_client_opt_file) + self.assertEqual(tmp, f'BindInterface {loopback}') + + self.cli_delete(['system', 'option']) + self.cli_commit() + self.assertFalse(os.path.exists(ssh_client_opt_file)) + + if __name__ == '__main__': unittest.main(verbosity=2, failfast=True) |