diff options
author | Kim <kim.sidney@gmail.com> | 2021-10-07 16:52:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-07 16:52:56 +0200 |
commit | 2274dbf9047493a00a6f30346b38dacd8cfcf965 (patch) | |
tree | f431f5f6f1b2770c98ed9047e1cec9209e536366 /smoketest/scripts | |
parent | 2acfffab8b98238e7d869673a858a4ae21651f0b (diff) | |
parent | adc7ef387d40e92bd7163ee6b401e99e554394a3 (diff) | |
download | vyos-1x-2274dbf9047493a00a6f30346b38dacd8cfcf965.tar.gz vyos-1x-2274dbf9047493a00a6f30346b38dacd8cfcf965.zip |
Merge branch 'current' into 2fa
Diffstat (limited to 'smoketest/scripts')
-rw-r--r-- | smoketest/scripts/cli/base_interfaces_test.py | 83 | ||||
-rw-r--r-- | smoketest/scripts/cli/base_vyostest_shim.py | 25 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_ha_vrrp.py | 171 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_ethernet.py | 42 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_pppoe.py | 120 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_nat66.py | 9 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_policy.py | 86 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_bgp.py | 70 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_isis.py | 53 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_ospf.py | 58 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_dhcp-server.py | 122 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_ssh.py | 7 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_webproxy.py | 6 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_system_conntrack.py | 23 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_system_login.py | 41 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_vpn_ipsec.py | 41 |
16 files changed, 718 insertions, 239 deletions
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index 7f69b8444..90c534796 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -214,7 +214,7 @@ class BasicInterfaceTest: self.cli_commit() for interface in self._interfaces: - self.assertTrue(AF_INET6 not in ifaddresses(interface)) + self.assertNotIn(AF_INET6, ifaddresses(interface)) def test_interface_mtu(self): if not self._test_mtu: @@ -246,11 +246,19 @@ class BasicInterfaceTest: for intf in self._interfaces: base = self._base_path + [intf] self.cli_set(base + ['mtu', self._mtu]) - self.cli_set(base + ['ipv6', 'address', 'no-default-link-local']) for option in self._options.get(intf, []): self.cli_set(base + option.split()) + # check validate() - can not set low MTU if 'no-default-link-local' + # is not set on CLI + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + for intf in self._interfaces: + base = self._base_path + [intf] + self.cli_set(base + ['ipv6', 'address', 'no-default-link-local']) + # commit interface changes self.cli_commit() @@ -278,30 +286,12 @@ class BasicInterfaceTest: base = self._base_path + [interface, 'vif', vlan] for address in self._test_addr: self.cli_set(base + ['address', address]) - self.cli_set(base + ['ingress-qos', '0:1']) - self.cli_set(base + ['egress-qos', '1:6']) self.cli_commit() for intf in self._interfaces: for vlan in self._vlan_range: vif = f'{intf}.{vlan}' - tmp = get_interface_config(f'{vif}') - - tmp2 = dict_search('linkinfo.info_data.ingress_qos', tmp) - for item in tmp2 if tmp2 else []: - from_key = item['from'] - to_key = item['to'] - self.assertEqual(from_key, 0) - self.assertEqual(to_key, 1) - - tmp2 = dict_search('linkinfo.info_data.egress_qos', tmp) - for item in tmp2 if tmp2 else []: - from_key = item['from'] - to_key = item['to'] - self.assertEqual(from_key, 1) - self.assertEqual(to_key, 6) - for address in self._test_addr: self.assertTrue(is_intf_addr_assigned(vif, address)) @@ -369,8 +359,6 @@ class BasicInterfaceTest: for vlan in self._vlan_range: base = self._base_path + [interface, 'vif', vlan] - for address in self._test_addr: - self.cli_set(base + ['address', address]) self.cli_set(base + ['ingress-qos', '0:1']) self.cli_set(base + ['egress-qos', '1:6']) @@ -395,9 +383,6 @@ class BasicInterfaceTest: self.assertEqual(from_key, 1) self.assertEqual(to_key, 6) - for address in self._test_addr: - self.assertTrue(is_intf_addr_assigned(vif, address)) - self.assertEqual(Interface(vif).get_admin_state(), 'up') new_ingress_qos_from = 1 @@ -408,8 +393,6 @@ class BasicInterfaceTest: base = self._base_path + [interface] for vlan in self._vlan_range: base = self._base_path + [interface, 'vif', vlan] - self.cli_delete(base + ['ingress-qos', '0:1']) - self.cli_delete(base + ['egress-qos', '1:6']) self.cli_set(base + ['ingress-qos', f'{new_ingress_qos_from}:{new_ingress_qos_to}']) self.cli_set(base + ['egress-qos', f'{new_egress_qos_from}:{new_egress_qos_to}']) @@ -556,13 +539,16 @@ class BasicInterfaceTest: if not self._test_ip: self.skipTest('not supported') + arp_tmo = '300' + mss = '1420' + for interface in self._interfaces: - arp_tmo = '300' path = self._base_path + [interface] for option in self._options.get(interface, []): self.cli_set(path + option.split()) # Options + self.cli_set(path + ['ip', 'adjust-mss', mss]) self.cli_set(path + ['ip', 'arp-cache-timeout', arp_tmo]) self.cli_set(path + ['ip', 'disable-arp-filter']) self.cli_set(path + ['ip', 'disable-forwarding']) @@ -576,54 +562,73 @@ class BasicInterfaceTest: self.cli_commit() for interface in self._interfaces: + base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN' + out = cmd('sudo iptables-save -t mangle') + for line in out.splitlines(): + if line.startswith(base_options): + self.assertIn(f'--set-mss {mss}', line) + tmp = read_file(f'/proc/sys/net/ipv4/neigh/{interface}/base_reachable_time_ms') self.assertEqual(tmp, str((int(arp_tmo) * 1000))) # tmo value is in milli seconds - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_filter') + proc_base = f'/proc/sys/net/ipv4/conf/{interface}' + + tmp = read_file(f'{proc_base}/arp_filter') self.assertEqual('0', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_accept') + tmp = read_file(f'{proc_base}/arp_accept') self.assertEqual('1', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_announce') + tmp = read_file(f'{proc_base}/arp_announce') self.assertEqual('1', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_ignore') + tmp = read_file(f'{proc_base}/arp_ignore') self.assertEqual('1', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/forwarding') + tmp = read_file(f'{proc_base}/forwarding') self.assertEqual('0', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp') + tmp = read_file(f'{proc_base}/proxy_arp') self.assertEqual('1', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp_pvlan') + tmp = read_file(f'{proc_base}/proxy_arp_pvlan') self.assertEqual('1', tmp) - tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/rp_filter') + tmp = read_file(f'{proc_base}/rp_filter') self.assertEqual('2', tmp) def test_interface_ipv6_options(self): if not self._test_ipv6: self.skipTest('not supported') + mss = '1400' + dad_transmits = '10' + for interface in self._interfaces: - dad_transmits = '10' path = self._base_path + [interface] for option in self._options.get(interface, []): self.cli_set(path + option.split()) # Options + self.cli_set(path + ['ipv6', 'adjust-mss', mss]) self.cli_set(path + ['ipv6', 'disable-forwarding']) self.cli_set(path + ['ipv6', 'dup-addr-detect-transmits', dad_transmits]) self.cli_commit() for interface in self._interfaces: - tmp = read_file(f'/proc/sys/net/ipv6/conf/{interface}/forwarding') + base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN' + out = cmd('sudo ip6tables-save -t mangle') + for line in out.splitlines(): + if line.startswith(base_options): + self.assertIn(f'--set-mss {mss}', line) + + proc_base = f'/proc/sys/net/ipv6/conf/{interface}' + + tmp = read_file(f'{proc_base}/forwarding') self.assertEqual('0', tmp) - tmp = read_file(f'/proc/sys/net/ipv6/conf/{interface}/dad_transmits') + tmp = read_file(f'{proc_base}/dad_transmits') self.assertEqual(dad_transmits, tmp) def test_dhcpv6_client_options(self): diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py index 18e49f47f..50f80e7d1 100644 --- a/smoketest/scripts/cli/base_vyostest_shim.py +++ b/smoketest/scripts/cli/base_vyostest_shim.py @@ -20,7 +20,9 @@ from time import sleep from vyos.configsession import ConfigSession from vyos.configsession import ConfigSessionError from vyos import ConfigError +from vyos.defaults import commit_lock from vyos.util import cmd +from vyos.util import run save_config = '/tmp/vyos-smoketest-save' @@ -70,21 +72,16 @@ class VyOSUnitTestSHIM: def cli_commit(self): self._session.commit() + # during a commit there is a process opening commit_lock, and run() returns 0 + while run(f'sudo lsof | grep -q {commit_lock}') == 0: + sleep(0.250) - def getFRRconfig(self, string, end='$', endsection='^!'): + def getFRRconfig(self, string, end='$', endsection='^!', daemon=''): """ Retrieve current "running configuration" from FRR """ - command = f'vtysh -c "show run" | sed -n "/^{string}{end}/,/{endsection}/p"' - - count = 0 - tmp = '' - while count < 10 and tmp == '': - # Let FRR settle after a config change first before harassing it again - sleep(1) - tmp = cmd(command) - count += 1 - - if self.debug or tmp == '': + command = f'vtysh -c "show run {daemon} no-header" | sed -n "/^{string}{end}/,/{endsection}/p"' + out = cmd(command) + if self.debug: import pprint print(f'\n\ncommand "{command}" returned:\n') - pprint.pprint(tmp) - return tmp + pprint.pprint(out) + return out diff --git a/smoketest/scripts/cli/test_ha_vrrp.py b/smoketest/scripts/cli/test_ha_vrrp.py new file mode 100755 index 000000000..8c5bb86d8 --- /dev/null +++ b/smoketest/scripts/cli/test_ha_vrrp.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 unittest + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSession +from vyos.configsession import ConfigSessionError +from vyos.ifconfig.vrrp import VRRP +from vyos.util import cmd +from vyos.util import process_named_running +from vyos.util import read_file +from vyos.template import inc_ip + +PROCESS_NAME = 'keepalived' +KEEPALIVED_CONF = VRRP.location['config'] +base_path = ['high-availability', 'vrrp'] + +vrrp_interface = 'eth1' +groups = ['VLAN77', 'VLAN78', 'VLAN201'] + +def getConfig(string, end='}'): + command = f'cat {KEEPALIVED_CONF} | sed -n "/^{string}/,/^{end}/p"' + out = cmd(command) + return out + +class TestVRRP(VyOSUnitTestSHIM.TestCase): + def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + + for group in groups: + vlan_id = group.lstrip('VLAN') + self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id]) + + self.cli_delete(base_path) + self.cli_commit() + + # Process must be terminated after deleting the config + self.assertFalse(process_named_running(PROCESS_NAME)) + + def test_01_default_values(self): + for group in groups: + vlan_id = group.lstrip('VLAN') + vip = f'100.64.{vlan_id}.1/24' + group_base = base_path + ['group', group] + + self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', inc_ip(vip, 1) + '/' + vip.split('/')[-1]]) + + self.cli_set(group_base + ['description', group]) + self.cli_set(group_base + ['interface', f'{vrrp_interface}.{vlan_id}']) + self.cli_set(group_base + ['address', vip]) + self.cli_set(group_base + ['vrid', vlan_id]) + + # commit changes + self.cli_commit() + + for group in groups: + vlan_id = group.lstrip('VLAN') + vip = f'100.64.{vlan_id}.1/24' + + config = getConfig(f'vrrp_instance {group}') + + self.assertIn(f'# {group}', config) + self.assertIn(f'interface {vrrp_interface}.{vlan_id}', config) + self.assertIn(f'virtual_router_id {vlan_id}', config) + self.assertIn(f'priority 100', config) # default value + self.assertIn(f'advert_int 1', config) # default value + self.assertIn(f'preempt_delay 0', config) # default value + self.assertNotIn(f'use_vmac', config) + self.assertIn(f' {vip}', config) + + def test_02_simple_options(self): + advertise_interval = '77' + priority = '123' + preempt_delay = '400' + + for group in groups: + vlan_id = group.lstrip('VLAN') + vip = f'100.64.{vlan_id}.1/24' + group_base = base_path + ['group', group] + + self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', inc_ip(vip, 1) + '/' + vip.split('/')[-1]]) + + self.cli_set(group_base + ['description', group]) + self.cli_set(group_base + ['interface', f'{vrrp_interface}.{vlan_id}']) + self.cli_set(group_base + ['address', vip]) + self.cli_set(group_base + ['vrid', vlan_id]) + + self.cli_set(group_base + ['advertise-interval', advertise_interval]) + self.cli_set(group_base + ['priority', priority]) + self.cli_set(group_base + ['preempt-delay', preempt_delay]) + + self.cli_set(group_base + ['rfc3768-compatibility']) + + # Authentication + self.cli_set(group_base + ['authentication', 'type', 'plaintext-password']) + self.cli_set(group_base + ['authentication', 'password', f'vyos-{group}']) + + # commit changes + self.cli_commit() + + for group in groups: + vlan_id = group.lstrip('VLAN') + vip = f'100.64.{vlan_id}.1/24' + + config = getConfig(f'vrrp_instance {group}') + self.assertIn(f'# {group}', config) + self.assertIn(f'state BACKUP', config) + self.assertIn(f'interface {vrrp_interface}.{vlan_id}', config) + self.assertIn(f'virtual_router_id {vlan_id}', config) + self.assertIn(f'priority {priority}', config) + self.assertIn(f'advert_int {advertise_interval}', config) + self.assertIn(f'preempt_delay {preempt_delay}', config) + self.assertIn(f'use_vmac {vrrp_interface}.{vlan_id}v{vlan_id}', config) + self.assertIn(f' {vip}', config) + + # Authentication + self.assertIn(f'auth_pass "vyos-{group}"', config) + self.assertIn(f'auth_type PASS', config) + + def test_03_sync_group(self): + sync_group = 'VyOS' + + for group in groups: + vlan_id = group.lstrip('VLAN') + vip = f'100.64.{vlan_id}.1/24' + group_base = base_path + ['group', group] + + self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', inc_ip(vip, 1) + '/' + vip.split('/')[-1]]) + + self.cli_set(group_base + ['interface', f'{vrrp_interface}.{vlan_id}']) + self.cli_set(group_base + ['address', vip]) + self.cli_set(group_base + ['vrid', vlan_id]) + + self.cli_set(base_path + ['sync-group', sync_group, 'member', group]) + + # commit changes + self.cli_commit() + + for group in groups: + vlan_id = group.lstrip('VLAN') + vip = f'100.64.{vlan_id}.1/24' + config = getConfig(f'vrrp_instance {group}') + + self.assertIn(f'interface {vrrp_interface}.{vlan_id}', config) + self.assertIn(f'virtual_router_id {vlan_id}', config) + self.assertNotIn(f'use_vmac', config) + self.assertIn(f' {vip}', config) + + config = getConfig(f'vrrp_sync_group {sync_group}') + self.assertIn(r'group {', config) + for group in groups: + self.assertIn(f'{group}', config) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index a9cdab16a..6d80e4c96 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -25,9 +25,26 @@ from vyos.util import cmd from vyos.util import process_named_running from vyos.util import read_file -pki_path = ['pki'] -cert_data = 'MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIxMDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3LftzngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93+dm/LDnp7C0=' -key_data = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww' +cert_data = """ +MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv +bWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIx +MDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNV +BAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlP +UzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3 +QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu ++JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3Lftz +ngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93 ++dm/LDnp7C0= +""" + +key_data = """ +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx +2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7 +u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww +""" def get_wpa_supplicant_value(interface, key): tmp = read_file(f'/run/wpa_supplicant/{interface}.conf') @@ -64,10 +81,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): # call base-classes classmethod super(cls, cls).setUpClass() - def tearDown(self): - self.cli_delete(pki_path) - for interface in self._interfaces: # when using a dedicated interface to test via TEST_ETH environment # variable only this one will be cleared in the end - usable to test @@ -151,14 +165,17 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): self.cli_commit() def test_eapol_support(self): - self.cli_set(pki_path + ['ca', 'eapol', 'certificate', cert_data]) - self.cli_set(pki_path + ['certificate', 'eapol', 'certificate', cert_data]) - self.cli_set(pki_path + ['certificate', 'eapol', 'private', 'key', key_data]) + ca_name = 'eapol' + cert_name = 'eapol' + + self.cli_set(['pki', 'ca', ca_name, 'certificate', cert_data.replace('\n','')]) + self.cli_set(['pki', 'certificate', cert_name, 'certificate', cert_data.replace('\n','')]) + self.cli_set(['pki', 'certificate', cert_name, 'private', 'key', key_data.replace('\n','')]) for interface in self._interfaces: # Enable EAPoL - self.cli_set(self._base_path + [interface, 'eapol', 'ca-certificate', 'eapol']) - self.cli_set(self._base_path + [interface, 'eapol', 'certificate', 'eapol']) + self.cli_set(self._base_path + [interface, 'eapol', 'ca-certificate', ca_name]) + self.cli_set(self._base_path + [interface, 'eapol', 'certificate', cert_name]) self.cli_commit() @@ -189,5 +206,8 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): tmp = get_wpa_supplicant_value(interface, 'identity') self.assertEqual(f'"{mac}"', tmp) + self.cli_delete(['pki', 'ca', ca_name]) + self.cli_delete(['pki', 'certificate', cert_name]) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_pppoe.py b/smoketest/scripts/cli/test_interfaces_pppoe.py index 3412ebae0..67edce2a0 100755 --- a/smoketest/scripts/cli/test_interfaces_pppoe.py +++ b/smoketest/scripts/cli/test_interfaces_pppoe.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2021 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 @@ -22,10 +22,8 @@ from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSession from vyos.configsession import ConfigSessionError -from vyos.util import read_file config_file = '/etc/ppp/peers/{}' -dhcp6c_config_file = '/run/dhcp6c/dhcp6c.{}.conf' base_path = ['interfaces', 'pppoe'] def get_config_value(interface, key): @@ -35,25 +33,26 @@ def get_config_value(interface, key): return list(line.split()) return [] -def get_dhcp6c_config_value(interface, key): - tmp = read_file(dhcp6c_config_file.format(interface)) - tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) - - out = [] - for item in tmp: - out.append(item.replace(';','')) - return out - +# add a classmethod to setup a temporaray PPPoE server for "proper" validation class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): def setUp(self): self._interfaces = ['pppoe10', 'pppoe20', 'pppoe30'] self._source_interface = 'eth0' def tearDown(self): + # Validate PPPoE client process + for interface in self._interfaces: + running = False + for proc in process_iter(): + if interface in proc.cmdline(): + running = True + break + self.assertTrue(running) + self.cli_delete(base_path) self.cli_commit() - def test_pppoe_client(self): + def test_01_pppoe_client(self): # Check if PPPoE dialer can be configured and runs for interface in self._interfaces: user = 'VyOS-user-' + interface @@ -71,8 +70,8 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): self.cli_commit() self.cli_set(base_path + [interface, 'source-interface', self._source_interface]) - # commit changes - self.cli_commit() + # commit changes + self.cli_commit() # verify configuration file(s) for interface in self._interfaces: @@ -88,17 +87,7 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): tmp = get_config_value(interface, 'ifname')[1] self.assertEqual(tmp, interface) - # Check if ppp process is running in the interface in question - running = False - for p in process_iter(): - if "pppd" in p.name(): - if interface in p.cmdline(): - running = True - - self.assertTrue(running) - - - def test_pppoe_clent_disabled_interface(self): + def test_02_pppoe_client_disabled_interface(self): # Check if PPPoE Client can be disabled for interface in self._interfaces: self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos']) @@ -106,23 +95,45 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + [interface, 'source-interface', self._source_interface]) self.cli_set(base_path + [interface, 'disable']) - self.cli_commit() + self.cli_commit() - # Validate PPPoE client process - running = False + # Validate PPPoE client process - must not run as interfaces are disabled for interface in self._interfaces: + running = False for proc in process_iter(): if interface in proc.cmdline(): running = True + break + self.assertFalse(running) + + # enable PPPoE interfaces + for interface in self._interfaces: + self.cli_delete(base_path + [interface, 'disable']) + + self.cli_commit() + - self.assertFalse(running) + def test_03_pppoe_authentication(self): + # When username or password is set - so must be the other + for interface in self._interfaces: + self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos']) + self.cli_set(base_path + [interface, 'source-interface', self._source_interface]) + self.cli_set(base_path + [interface, 'ipv6', 'address', 'autoconf']) + # check validate() - if user is set, so must be the password + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos']) + + self.cli_commit() - def test_pppoe_dhcpv6pd(self): + def test_04_pppoe_dhcpv6pd(self): # Check if PPPoE dialer can be configured with DHCPv6-PD address = '1' sla_id = '0' sla_len = '8' + for interface in self._interfaces: self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos']) self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos']) @@ -147,51 +158,8 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): self.assertEqual(tmp, 'vyos') tmp = get_config_value(interface, 'password')[1].replace('"', '') self.assertEqual(tmp, 'vyos') - - for param in ['+ipv6', 'ipv6cp-use-ipaddr']: - tmp = get_config_value(interface, param)[0] - self.assertEqual(tmp, param) - - # verify DHCPv6 prefix delegation - # will return: ['delegation', '::/56 infinity;'] - tmp = get_dhcp6c_config_value(interface, 'prefix')[1].split()[0] # mind the whitespace - self.assertEqual(tmp, '::/56') - tmp = get_dhcp6c_config_value(interface, 'prefix-interface')[0].split()[0] - self.assertEqual(tmp, self._source_interface) - tmp = get_dhcp6c_config_value(interface, 'ifid')[0] - self.assertEqual(tmp, address) - tmp = get_dhcp6c_config_value(interface, 'sla-id')[0] - self.assertEqual(tmp, sla_id) - tmp = get_dhcp6c_config_value(interface, 'sla-len')[0] - self.assertEqual(tmp, sla_len) - - # Check if ppp process is running in the interface in question - running = False - for p in process_iter(): - if "pppd" in p.name(): - running = True - self.assertTrue(running) - - # We can not check if wide-dhcpv6 process is running as it is started - # after the PPP interface gets a link to the ISP - but we can see if - # it would be started by the scripts - tmp = read_file(f'/etc/ppp/ipv6-up.d/1000-vyos-pppoe-{interface}') - tmp = re.findall(f'systemctl restart dhcp6c@{interface}.service', tmp) - self.assertTrue(tmp) - - def test_pppoe_authentication(self): - # When username or password is set - so must be the other - interface = 'pppoe0' - self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos']) - self.cli_set(base_path + [interface, 'source-interface', self._source_interface]) - self.cli_set(base_path + [interface, 'ipv6', 'address', 'autoconf']) - - # check validate() - if user is set, so must be the password - with self.assertRaises(ConfigSessionError): - self.cli_commit() - - self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos']) - self.cli_commit() + tmp = get_config_value(interface, '+ipv6 ipv6cp-use-ipaddr') + self.assertListEqual(tmp, ['+ipv6', 'ipv6cp-use-ipaddr']) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py index dca92c97d..7721105e0 100755 --- a/smoketest/scripts/cli/test_nat66.py +++ b/smoketest/scripts/cli/test_nat66.py @@ -31,10 +31,13 @@ src_path = base_path + ['source'] dst_path = base_path + ['destination'] class TestNAT66(VyOSUnitTestSHIM.TestCase): - def setUp(self): + @classmethod + def setUpClass(cls): + super(cls, cls).setUpClass() + # ensure we can also run this test on a live system - so lets clean # out the current configuration :) - self.cli_delete(base_path) + cls.cli_delete(cls, base_path) def tearDown(self): self.cli_delete(base_path) @@ -183,4 +186,4 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): self.cli_commit() if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2, failfast=True) diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 2d7b78048..c2288a86a 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -804,6 +804,19 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): }, }, }, + 'evpn-configuration' : { + 'rule' : { + '10' : { + 'action' : 'permit', + 'match' : { + 'evpn-default-route' : '', + 'evpn-rd' : '100:300', + 'evpn-route-type' : 'prefix', + 'evpn-vni' : '1234', + }, + }, + }, + }, } self.cli_set(['policy', 'access-list', access_list, 'rule', '10', 'action', 'permit']) @@ -847,6 +860,14 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): if 'community' in rule_config['match']: self.cli_set(path + ['rule', rule, 'match', 'community', 'community-list', rule_config['match']['community']]) self.cli_set(path + ['rule', rule, 'match', 'community', 'exact-match']) + if 'evpn-default-route' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'default-route']) + if 'evpn-rd' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'rd', rule_config['match']['evpn-rd']]) + if 'evpn-route-type' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'route-type', rule_config['match']['evpn-route-type']]) + if 'evpn-vni' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'evpn', 'vni', rule_config['match']['evpn-vni']]) if 'extcommunity' in rule_config['match']: self.cli_set(path + ['rule', rule, 'match', 'extcommunity', rule_config['match']['extcommunity']]) if 'interface' in rule_config['match']: @@ -967,6 +988,18 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): if 'community' in rule_config['match']: tmp = f'match community {rule_config["match"]["community"]} exact-match' self.assertIn(tmp, config) + if 'evpn-default-route' in rule_config['match']: + tmp = f'match evpn default-route' + self.assertIn(tmp, config) + if 'evpn-rd' in rule_config['match']: + tmp = f'match evpn rd {rule_config["match"]["evpn-rd"]}' + self.assertIn(tmp, config) + if 'evpn-route-type' in rule_config['match']: + tmp = f'match evpn route-type {rule_config["match"]["evpn-route-type"]}' + self.assertIn(tmp, config) + if 'evpn-vni' in rule_config['match']: + tmp = f'match evpn vni {rule_config["match"]["evpn-vni"]}' + self.assertIn(tmp, config) if 'extcommunity' in rule_config['match']: tmp = f'match extcommunity {rule_config["match"]["extcommunity"]}' self.assertIn(tmp, config) @@ -1116,5 +1149,58 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.assertEqual(tmp, original) + # Test set table for fwmark + def test_fwmark_table_id(self): + path = base_path + ['local-route'] + + fwmk = '24' + rule = '101' + table = '154' + + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + # Check generated configuration + + # Expected values + original = """ + 101: from all fwmark 0x18 lookup 154 + """ + tmp = cmd('ip rule show prio 101') + original = original.split() + tmp = tmp.split() + + self.assertEqual(tmp, original) + + # Test set table for sources with fwmark + def test_fwmark_sources_table_id(self): + path = base_path + ['local-route'] + + sources = ['203.0.113.11', '203.0.113.12'] + fwmk = '23' + rule = '100' + table = '150' + for src in sources: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + # Check generated configuration + + # Expected values + original = """ + 100: from 203.0.113.11 fwmark 0x17 lookup 150 + 100: from 203.0.113.12 fwmark 0x17 lookup 150 + """ + tmp = cmd('ip rule show prio 100') + original = original.split() + tmp = tmp.split() + + self.assertEqual(tmp, original) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index c3a2ffbf9..16284ed01 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -78,6 +78,7 @@ neighbor_config = { 'cap_over' : '', 'ttl_security' : '5', 'local_as' : '300', + 'solo' : '', 'route_map_in' : route_map_in, 'route_map_out': route_map_out, 'no_send_comm_std' : '', @@ -164,7 +165,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): if 'multi_hop' in peer_config: self.assertIn(f' neighbor {peer} ebgp-multihop {peer_config["multi_hop"]}', frrconfig) if 'local_as' in peer_config: - self.assertIn(f' neighbor {peer} local-as {peer_config["local_as"]}', frrconfig) + self.assertIn(f' neighbor {peer} local-as {peer_config["local_as"]} no-prepend replace-as', frrconfig) if 'cap_over' in peer_config: self.assertIn(f' neighbor {peer} override-capability', frrconfig) if 'passive' in peer_config: @@ -173,6 +174,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' neighbor {peer} password {peer_config["password"]}', frrconfig) if 'remote_as' in peer_config: self.assertIn(f' neighbor {peer} remote-as {peer_config["remote_as"]}', frrconfig) + if 'solo' in peer_config: + self.assertIn(f' neighbor {peer} solo', frrconfig) if 'shutdown' in peer_config: self.assertIn(f' neighbor {peer} shutdown', frrconfig) if 'ttl_security' in peer_config: @@ -218,8 +221,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): # Default local preference (higher = more preferred, default value is 100) self.cli_set(base_path + ['parameters', 'default', 'local-pref', local_pref]) - # Deactivate IPv4 unicast for a peer by default - self.cli_set(base_path + ['parameters', 'default', 'no-ipv4-unicast']) self.cli_set(base_path + ['parameters', 'graceful-restart', 'stalepath-time', stalepath_time]) self.cli_set(base_path + ['parameters', 'graceful-shutdown']) self.cli_set(base_path + ['parameters', 'ebgp-requires-policy']) @@ -243,7 +244,6 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' bgp router-id {router_id}', frrconfig) self.assertIn(f' bgp log-neighbor-changes', frrconfig) self.assertIn(f' bgp default local-preference {local_pref}', frrconfig) - self.assertIn(f' no bgp default ipv4-unicast', frrconfig) self.assertIn(f' bgp graceful-restart stalepath-time {stalepath_time}', frrconfig) self.assertIn(f' bgp graceful-shutdown', frrconfig) self.assertIn(f' bgp bestpath as-path multipath-relax', frrconfig) @@ -281,7 +281,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): if 'multi_hop' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'ebgp-multihop', peer_config["multi_hop"]]) if 'local_as' in peer_config: - self.cli_set(base_path + ['neighbor', peer, 'local-as', peer_config["local_as"]]) + self.cli_set(base_path + ['neighbor', peer, 'local-as', peer_config["local_as"], 'no-prepend', 'replace-as']) if 'cap_over' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'override-capability']) if 'passive' in peer_config: @@ -296,6 +296,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['neighbor', peer, 'strict-capability-match']) if 'shutdown' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'shutdown']) + if 'solo' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'solo']) if 'ttl_security' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'ttl-security', 'hops', peer_config["ttl_security"]]) if 'update_src' in peer_config: @@ -348,7 +350,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): if 'multi_hop' in config: self.cli_set(base_path + ['peer-group', peer_group, 'ebgp-multihop', config["multi_hop"]]) if 'local_as' in config: - self.cli_set(base_path + ['peer-group', peer_group, 'local-as', config["local_as"]]) + self.cli_set(base_path + ['peer-group', peer_group, 'local-as', config["local_as"], 'no-prepend', 'replace-as']) if 'cap_over' in config: self.cli_set(base_path + ['peer-group', peer_group, 'override-capability']) if 'passive' in config: @@ -628,6 +630,9 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): # templates and Jinja2 FRR template. table = '1000' + self.cli_set(base_path + ['local-as', ASN]) + # testing only one AFI is sufficient as it's generic code + for vrf in vrfs: vrf_base = ['vrf', 'name', vrf] self.cli_set(vrf_base + ['table', table]) @@ -636,15 +641,26 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(vrf_base + ['protocols', 'bgp', 'route-map', route_map_in]) table = str(int(table) + 1000) + # import VRF routes do main RIB + self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'import', 'vrf', vrf]) + self.cli_commit() + # Verify FRR bgpd configuration + frrconfig = self.getFRRconfig(f'router bgp {ASN}') + self.assertIn(f'router bgp {ASN}', frrconfig) + self.assertIn(f' address-family ipv6 unicast', frrconfig) + + for vrf in vrfs: + self.assertIn(f' import vrf {vrf}', frrconfig) + # Verify FRR bgpd configuration - frrconfig = self.getFRRconfig(f'router bgp {ASN} vrf {vrf}') - self.assertIn(f'router bgp {ASN} vrf {vrf}', frrconfig) - self.assertIn(f' bgp router-id {router_id}', frrconfig) + frr_vrf_config = self.getFRRconfig(f'router bgp {ASN} vrf {vrf}') + self.assertIn(f'router bgp {ASN} vrf {vrf}', frr_vrf_config) + self.assertIn(f' bgp router-id {router_id}', frr_vrf_config) - # CCC: Currently this is not working as FRR() class does not support + # XXX: Currently this is not working as FRR() class does not support # route-maps for multiple vrfs because the modify_section() only works # on lines and not text blocks. # @@ -694,13 +710,27 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' neighbor {interface} activate', frrconfig) self.assertIn(f' exit-address-family', frrconfig) - def test_bgp_13_solo(self): + + def test_bgp_13_vpn(self): remote_asn = str(int(ASN) + 150) neighbor = '192.0.2.55' + vrf_name = 'red' + label = 'auto' + rd = f'{neighbor}:{ASN}' + rt_export = f'{neighbor}:1002 1.2.3.4:567' + rt_import = f'{neighbor}:1003 500:100' self.cli_set(base_path + ['local-as', ASN]) - self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn]) - self.cli_set(base_path + ['neighbor', neighbor, 'solo']) + # testing only one AFI is sufficient as it's generic code + for afi in ['ipv4-unicast', 'ipv6-unicast']: + self.cli_set(base_path + ['address-family', afi, 'export', 'vpn']) + self.cli_set(base_path + ['address-family', afi, 'import', 'vpn']) + self.cli_set(base_path + ['address-family', afi, 'label', 'vpn', 'export', label]) + self.cli_set(base_path + ['address-family', afi, 'rd', 'vpn', 'export', rd]) + self.cli_set(base_path + ['address-family', afi, 'route-map', 'vpn', 'export', route_map_out]) + self.cli_set(base_path + ['address-family', afi, 'route-map', 'vpn', 'import', route_map_in]) + self.cli_set(base_path + ['address-family', afi, 'route-target', 'vpn', 'export', rt_export]) + self.cli_set(base_path + ['address-family', afi, 'route-target', 'vpn', 'import', rt_import]) # commit changes self.cli_commit() @@ -708,7 +738,19 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): # Verify FRR bgpd configuration frrconfig = self.getFRRconfig(f'router bgp {ASN}') self.assertIn(f'router bgp {ASN}', frrconfig) - self.assertIn(f' neighbor {neighbor} solo', frrconfig) + + for afi in ['ipv4', 'ipv6']: + afi_config = self.getFRRconfig(f' address-family {afi} unicast', endsection='exit-address-family', daemon='bgpd') + self.assertIn(f'address-family {afi} unicast', afi_config) + self.assertIn(f' export vpn', afi_config) + self.assertIn(f' import vpn', afi_config) + self.assertIn(f' label vpn export {label}', afi_config) + self.assertIn(f' rd vpn export {rd}', afi_config) + self.assertIn(f' route-map vpn export {route_map_out}', afi_config) + self.assertIn(f' route-map vpn import {route_map_in}', afi_config) + self.assertIn(f' rt vpn export {rt_export}', afi_config) + self.assertIn(f' rt vpn import {rt_import}', afi_config) + self.assertIn(f' exit-address-family', afi_config) if __name__ == '__main__': unittest.main(verbosity=2)
\ No newline at end of file diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 9b6d4a4ec..8170f2b56 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -199,5 +199,58 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.assertIn(f' area-password clear {password}', tmp) + def test_isis_06_spf_delay(self): + self.isis_base_config() + + network = 'point-to-point' + holddown = '10' + init_delay = '50' + long_delay = '200' + short_delay = '100' + time_to_learn = '75' + + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'network', network]) + + self.cli_set(base_path + ['spf-delay-ietf', 'holddown', holddown]) + # verify() - All types of spf-delay must be configured + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['spf-delay-ietf', 'init-delay', init_delay]) + # verify() - All types of spf-delay must be configured + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['spf-delay-ietf', 'long-delay', long_delay]) + # verify() - All types of spf-delay must be configured + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['spf-delay-ietf', 'long-delay', long_delay]) + # verify() - All types of spf-delay must be configured + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['spf-delay-ietf', 'short-delay', short_delay]) + # verify() - All types of spf-delay must be configured + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['spf-delay-ietf', 'time-to-learn', time_to_learn]) + + # Commit all changes + self.cli_commit() + + # Verify all changes + tmp = self.getFRRconfig(f'router isis {domain}') + self.assertIn(f' net {net}', tmp) + self.assertIn(f' spf-delay-ietf init-delay {init_delay} short-delay {short_delay} long-delay {long_delay} holddown {holddown} time-to-learn {time_to_learn}', tmp) + + for interface in self._interfaces: + tmp = self.getFRRconfig(f'interface {interface}') + self.assertIn(f' ip router isis {domain}', tmp) + self.assertIn(f' ipv6 router isis {domain}', tmp) + self.assertIn(f' isis network {network}', tmp) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 623d40497..0529eefbd 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -14,10 +14,13 @@ # 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 logging +import sys import unittest from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.configsession import ConfigSessionError from vyos.ifconfig import Section from vyos.util import process_named_running from vyos.util import cmd @@ -27,6 +30,8 @@ base_path = ['protocols', 'ospf'] route_map = 'foo-bar-baz10' +log = logging.getLogger('TestProtocolsOSPF') + class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): def setUp(self): self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) @@ -202,10 +207,11 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): for interface in interfaces: self.assertIn(f' no passive-interface {interface}', frrconfig) # default except: - tmp1 = cmd('sudo dmesg') - tmp2 = cmd('tail -n 250 /var/log/messages') - tmp3 = cmd('vtysh -c "show run"') - self.fail(f'Now we can hopefully see why OSPF fails:\n{tmp1}\n\n{tmp2}\n\n{tmp3}') + log.debug(frrconfig) + log.debug(cmd('sudo dmesg')) + log.debug(cmd('sudo cat /var/log/messages')) + log.debug(cmd('vtysh -c "show run"')) + self.fail('Now we can hopefully see why OSPF fails!') def test_ospf_08_redistribute(self): metric = '15' @@ -215,21 +221,22 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): for protocol in redistribute: self.cli_set(base_path + ['redistribute', protocol, 'metric', metric]) self.cli_set(base_path + ['redistribute', protocol, 'route-map', route_map]) - if protocol not in ['kernel', 'static']: - self.cli_set(base_path + ['redistribute', protocol, 'metric-type', metric_type]) + self.cli_set(base_path + ['redistribute', protocol, 'metric-type', metric_type]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') - self.assertIn(f'router ospf', frrconfig) - for protocol in redistribute: - if protocol in ['kernel', 'static']: - self.assertIn(f' redistribute {protocol} metric {metric} route-map {route_map}', frrconfig) - else: + try: + self.assertIn(f'router ospf', frrconfig) + for protocol in redistribute: self.assertIn(f' redistribute {protocol} metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) - + except: + log.debug(frrconfig) + log.debug(cmd('sudo cat /var/log/messages')) + log.debug(cmd('vtysh -c "show run"')) + self.fail('Now we can hopefully see why OSPF fails!') def test_ospf_09_virtual_link(self): networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] @@ -261,7 +268,7 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' network {network} area {area}', frrconfig) - def test_ospf_10_interface_configureation(self): + def test_ospf_10_interface_configuration(self): interfaces = Section.interfaces('ethernet') password = 'vyos1234' bandwidth = '10000' @@ -344,5 +351,30 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): frrconfig = self.getFRRconfig(zebra_route_map) self.assertNotIn(zebra_route_map, frrconfig) + def test_ospf_13_interface_area(self): + area = '0' + interfaces = Section.interfaces('ethernet') + + self.cli_set(base_path + ['area', area, 'network', '10.0.0.0/8']) + for interface in interfaces: + self.cli_set(base_path + ['interface', interface, 'area', area]) + + # we can not have bot area network and interface area set + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base_path + ['area', area, 'network']) + + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf') + self.assertIn(f'router ospf', frrconfig) + + for interface in interfaces: + config = self.getFRRconfig(f'interface {interface}') + self.assertIn(f'interface {interface}', config) + self.assertIn(f' ip ospf area {area}', config) + if __name__ == '__main__': + logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py index 815bd333a..301f8fa31 100755 --- a/smoketest/scripts/cli/test_service_dhcp-server.py +++ b/smoketest/scripts/cli/test_service_dhcp-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2021 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 @@ -37,12 +37,19 @@ dns_2 = inc_ip(subnet, 3) domain_name = 'vyos.net' class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): - def setUp(self): + @classmethod + def setUpClass(cls): + super(cls, cls).setUpClass() + cidr_mask = subnet.split('/')[-1] - self.cli_set(['interfaces', 'dummy', 'dum8765', 'address', f'{router}/{cidr_mask}']) + cls.cli_set(cls, ['interfaces', 'dummy', 'dum8765', 'address', f'{router}/{cidr_mask}']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'dummy', 'dum8765']) + super(cls, cls).tearDownClass() def tearDown(self): - self.cli_delete(['interfaces', 'dummy', 'dum8765']) self.cli_delete(base_path) self.cli_commit() @@ -59,9 +66,10 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] # we use the first subnet IP address as default gateway self.cli_set(pool + ['default-router', router]) - self.cli_set(pool + ['dns-server', dns_1]) - self.cli_set(pool + ['dns-server', dns_2]) + self.cli_set(pool + ['name-server', dns_1]) + self.cli_set(pool + ['name-server', dns_2]) self.cli_set(pool + ['domain-name', domain_name]) + self.cli_set(pool + ['ping-check']) # check validate() - No DHCP address range or active static-mapping set with self.assertRaises(ConfigSessionError): @@ -84,6 +92,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): self.assertIn(f'option domain-name "{domain_name}";', config) self.assertIn(f'default-lease-time 86400;', config) self.assertIn(f'max-lease-time 86400;', config) + self.assertIn(f'ping-check true;', config) self.assertIn(f'range {range_0_start} {range_0_stop};', config) self.assertIn(f'range {range_1_start} {range_1_stop};', config) self.assertIn(f'set shared-networkname = "{shared_net_name}";', config) @@ -108,8 +117,8 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] # we use the first subnet IP address as default gateway self.cli_set(pool + ['default-router', router]) - self.cli_set(pool + ['dns-server', dns_1]) - self.cli_set(pool + ['dns-server', dns_2]) + self.cli_set(pool + ['name-server', dns_1]) + self.cli_set(pool + ['name-server', dns_2]) self.cli_set(pool + ['domain-name', domain_name]) self.cli_set(pool + ['ip-forwarding']) self.cli_set(pool + ['smtp-server', smtp_server]) @@ -123,8 +132,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): self.cli_set(pool + ['wpad-url', wpad]) self.cli_set(pool + ['server-identifier', server_identifier]) - self.cli_set(pool + ['static-route', 'destination-subnet', '10.0.0.0/24']) - self.cli_set(pool + ['static-route', 'router', '192.0.2.1']) + self.cli_set(pool + ['static-route', '10.0.0.0/24', 'next-hop', '192.0.2.1']) # check validate() - No DHCP address range or active static-mapping set with self.assertRaises(ConfigSessionError): @@ -132,34 +140,11 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): self.cli_set(pool + ['range', '0', 'start', range_0_start]) self.cli_set(pool + ['range', '0', 'stop', range_0_stop]) - # failover - failover_local = router - failover_remote = inc_ip(router, 1) - - self.cli_set(pool + ['failover', 'local-address', failover_local]) - self.cli_set(pool + ['failover', 'name', shared_net_name]) - self.cli_set(pool + ['failover', 'peer-address', failover_remote]) - self.cli_set(pool + ['failover', 'status', 'primary']) - # commit changes self.cli_commit() config = read_file(DHCPD_CONF) - self.assertIn(f'failover peer "{shared_net_name}"' + r' {', config) - self.assertIn(f'primary;', config) - self.assertIn(f'mclt 1800;', config) - self.assertIn(f'mclt 1800;', config) - self.assertIn(f'split 128;', config) - self.assertIn(f'port 520;', config) - self.assertIn(f'peer port 520;', config) - self.assertIn(f'max-response-delay 30;', config) - self.assertIn(f'max-unacked-updates 10;', config) - self.assertIn(f'load balance max seconds 3;', config) - self.assertIn(f'peer port 520;', config) - self.assertIn(f'address {failover_local};', config) - self.assertIn(f'peer address {failover_remote};', config) - network = address_from_cidr(subnet) netmask = netmask_from_cidr(subnet) self.assertIn(f'ddns-update-style none;', config) @@ -185,8 +170,6 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): self.assertIn(f'max-lease-time 86400;', config) self.assertIn(f'range {range_0_start} {range_0_stop};', config) self.assertIn(f'set shared-networkname = "{shared_net_name}";', config) - self.assertIn(f'failover peer "{shared_net_name}";', config) - self.assertIn(f'deny dynamic bootp clients;', config) # weird syntax for those static routes self.assertIn(f'option rfc3442-static-route 24,10,0,0,192,0,2,1, 0,192,0,2,1;', config) @@ -202,8 +185,8 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] # we use the first subnet IP address as default gateway self.cli_set(pool + ['default-router', router]) - self.cli_set(pool + ['dns-server', dns_1]) - self.cli_set(pool + ['dns-server', dns_2]) + self.cli_set(pool + ['name-server', dns_1]) + self.cli_set(pool + ['name-server', dns_2]) self.cli_set(pool + ['domain-name', domain_name]) # check validate() - No DHCP address range or active static-mapping set @@ -262,7 +245,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] # we use the first subnet IP address as default gateway self.cli_set(pool + ['default-router', router]) - self.cli_set(pool + ['dns-server', dns_1]) + self.cli_set(pool + ['name-server', dns_1]) self.cli_set(pool + ['domain-name', domain_name]) self.cli_set(pool + ['lease', lease_time]) @@ -438,5 +421,68 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) + def test_dhcp_failover(self): + shared_net_name = 'FAILOVER' + failover_name = 'VyOS-Failover' + + range_0_start = inc_ip(subnet, 10) + range_0_stop = inc_ip(subnet, 20) + + pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet] + # we use the first subnet IP address as default gateway + self.cli_set(pool + ['default-router', router]) + + # check validate() - No DHCP address range or active static-mapping set + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(pool + ['range', '0', 'start', range_0_start]) + self.cli_set(pool + ['range', '0', 'stop', range_0_stop]) + + # failover + failover_local = router + failover_remote = inc_ip(router, 1) + + self.cli_set(base_path + ['failover', 'source-address', failover_local]) + self.cli_set(base_path + ['failover', 'name', failover_name]) + self.cli_set(base_path + ['failover', 'remote', failover_remote]) + self.cli_set(base_path + ['failover', 'status', 'primary']) + + # check validate() - failover needs to be enabled for at least one subnet + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(pool + ['enable-failover']) + + # commit changes + self.cli_commit() + + config = read_file(DHCPD_CONF) + + self.assertIn(f'failover peer "{failover_name}"' + r' {', config) + self.assertIn(f'primary;', config) + self.assertIn(f'mclt 1800;', config) + self.assertIn(f'mclt 1800;', config) + self.assertIn(f'split 128;', config) + self.assertIn(f'port 520;', config) + self.assertIn(f'peer port 520;', config) + self.assertIn(f'max-response-delay 30;', config) + self.assertIn(f'max-unacked-updates 10;', config) + self.assertIn(f'load balance max seconds 3;', config) + self.assertIn(f'peer port 520;', config) + self.assertIn(f'address {failover_local};', config) + self.assertIn(f'peer address {failover_remote};', config) + + network = address_from_cidr(subnet) + netmask = netmask_from_cidr(subnet) + self.assertIn(f'ddns-update-style none;', config) + self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config) + self.assertIn(f'option routers {router};', config) + self.assertIn(f'range {range_0_start} {range_0_stop};', config) + self.assertIn(f'set shared-networkname = "{shared_net_name}";', config) + self.assertIn(f'failover peer "{failover_name}";', config) + self.assertIn(f'deny dynamic bootp clients;', config) + + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py index c76f709b1..ded4d8301 100755 --- a/smoketest/scripts/cli/test_service_ssh.py +++ b/smoketest/scripts/cli/test_service_ssh.py @@ -41,10 +41,13 @@ def get_config_value(key): return tmp class TestServiceSSH(VyOSUnitTestSHIM.TestCase): - def setUp(self): + @classmethod + def setUpClass(cls): + super(cls, cls).setUpClass() + # ensure we can also run this test on a live system - so lets clean # out the current configuration :) - self.cli_delete(base_path) + cls.cli_delete(cls, base_path) def tearDown(self): # delete testing SSH config diff --git a/smoketest/scripts/cli/test_service_webproxy.py b/smoketest/scripts/cli/test_service_webproxy.py index d47bd452d..6780a93f9 100755 --- a/smoketest/scripts/cli/test_service_webproxy.py +++ b/smoketest/scripts/cli/test_service_webproxy.py @@ -52,8 +52,6 @@ class TestServiceWebProxy(VyOSUnitTestSHIM.TestCase): self.assertIn(f'access_log /var/log/squid/access.log squid', config) # ACL verification - self.assertIn(f'acl localhost src 127.0.0.1/32', config) - self.assertIn(f'acl to_localhost dst 127.0.0.0/8', config) self.assertIn(f'acl net src all', config) self.assertIn(f'acl SSL_ports port 443', config) @@ -234,8 +232,8 @@ class TestServiceWebProxy(VyOSUnitTestSHIM.TestCase): config = read_file(PROXY_CONF) self.assertIn(f'http_port {listen_ip}:3128 intercept', config) - self.assertIn(f'redirect_program /usr/bin/squidGuard -c /etc/squidguard/squidGuard.conf', config) - self.assertIn(f'redirect_children 8', config) + self.assertIn(f'url_rewrite_program /usr/bin/squidGuard -c /etc/squidguard/squidGuard.conf', config) + self.assertIn(f'url_rewrite_children 8', config) # Check SquidGuard config sg_config = read_file('/etc/squidguard/squidGuard.conf') diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py index 21d626d2f..a2380981b 100755 --- a/smoketest/scripts/cli/test_system_conntrack.py +++ b/smoketest/scripts/cli/test_system_conntrack.py @@ -147,8 +147,8 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): self.assertEqual(get_sysctl(f'{parameter}'), parameter_config['default_value']) - def test_conntrack_module_disable(self): - # Some features are disabled by onloading the kernel helper module(s) + def test_conntrack_module_enable(self): + # conntrack helper modules are disabled by default modules = { 'ftp' : { 'driver' : ['nf_nat_ftp', 'nf_conntrack_ftp'], @@ -176,38 +176,39 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): }, } + # load modules for module in modules: - self.cli_set(base_path + ['modules', module, 'disable']) + self.cli_set(base_path + ['modules', module]) # commit changes self.cli_commit() - # verify modules are no longer loaded on the system + # verify modules are loaded on the system for module, module_options in modules.items(): if 'driver' in module_options: for driver in module_options['driver']: - self.assertFalse(os.path.isdir(f'/sys/module/{driver}')) + self.assertTrue(os.path.isdir(f'/sys/module/{driver}')) if 'iptables' in module_options: rules = cmd('sudo iptables-save -t raw') for ruleset in module_options['iptables']: - self.assertNotIn(ruleset, rules) + self.assertIn(ruleset, rules) - # reload modules + # unload modules for module in modules: - self.cli_delete(base_path + ['modules', module, 'disable']) + self.cli_delete(base_path + ['modules', module]) # commit changes self.cli_commit() - # verify modules are again loaded on the system + # verify modules are not loaded on the system for module, module_options in modules.items(): if 'driver' in module_options: for driver in module_options['driver']: - self.assertTrue(os.path.isdir(f'/sys/module/{driver}')) + self.assertFalse(os.path.isdir(f'/sys/module/{driver}')) if 'iptables' in module_options: rules = cmd('sudo iptables-save -t raw') for ruleset in module_options['iptables']: - self.assertIn(ruleset, rules) + self.assertNotIn(ruleset, rules) def test_conntrack_hash_size(self): hash_size = '65536' diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index 8327235fb..0addd630e 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.py @@ -31,7 +31,19 @@ from vyos.util import read_file from vyos.template import inc_ip base_path = ['system', 'login'] -users = ['vyos1', 'vyos2'] +users = ['vyos1', 'vyos-roxx123', 'VyOS-123_super.Nice'] + +ssh_pubkey = """ +AAAAB3NzaC1yc2EAAAADAQABAAABgQD0NuhUOEtMIKnUVFIHoFatqX/c4mjerXyF +TlXYfVt6Ls2NZZsUSwHbnhK4BKDrPvVZMW/LycjQPzWW6TGtk6UbZP1WqdviQ9hP +jsEeKJSTKciMSvQpjBWyEQQPXSKYQC7ryQQilZDqnJgzqwzejKEe+nhhOdBvjuZc +uukxjT69E0UmWAwLxzvfiurwiQaC7tG+PwqvtfHOPL3i6yRO2C5ORpFarx8PeGDS +IfIXJCr3LoUbLHeuE7T2KaOKQcX0UsWJ4CoCapRLpTVYPDB32BYfgq7cW1Sal1re +EGH2PzuXBklinTBgCHA87lHjpwDIAqdmvMj7SXIW9LxazLtP+e37sexE7xEs0cpN +l68txdDbY2P2Kbz5mqGFfCvBYKv9V2clM5vyWNy/Xp5TsCis89nn83KJmgFS7sMx +pHJz8umqkxy3hfw0K7BRFtjWd63sbOP8Q/SDV7LPaIfIxenA9zv2rY7y+AIqTmSr +TTSb0X1zPGxPIRFy5GoGtO9Mm5h4OZk= +""" class TestSystemLogin(VyOSUnitTestSHIM.TestCase): def tearDown(self): @@ -42,6 +54,8 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): self.cli_commit() def test_add_linux_system_user(self): + # We are not allowed to re-use a username already taken by the Linux + # base system system_user = 'backup' self.cli_set(base_path + ['user', system_user, 'authentication', 'plaintext-password', system_user]) @@ -75,9 +89,30 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): (stdout, stderr) = proc.communicate() # stdout is something like this: - # b'Linux vyos 4.19.101-amd64-vyos #1 SMP Sun Feb 2 10:18:07 UTC 2020 x86_64 GNU/Linux\n' + # b'Linux LR1.wue3 5.10.61-amd64-vyos #1 SMP Fri Aug 27 08:55:46 UTC 2021 x86_64 GNU/Linux\n' self.assertTrue(len(stdout) > 40) + def test_system_user_ssh_key(self): + ssh_user = 'ssh-test_user' + public_keys = 'vyos_test@domain-foo.com' + type = 'ssh-rsa' + + self.cli_set(base_path + ['user', ssh_user, 'authentication', 'public-keys', public_keys, 'key', ssh_pubkey.replace('\n','')]) + + # check validate() - missing type for public-key + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['user', ssh_user, 'authentication', 'public-keys', public_keys, 'type', type]) + + self.cli_commit() + + # Check that SSH key was written properly + tmp = cmd(f'sudo cat /home/{ssh_user}/.ssh/authorized_keys') + key = f'{type} ' + ssh_pubkey.replace('\n','') + self.assertIn(key, tmp) + + self.cli_delete(base_path + ['user', ssh_user]) + def test_radius_kernel_features(self): # T2886: RADIUS requires some Kernel options to be present kernel = platform.release() @@ -201,4 +236,4 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): self.assertTrue(tmp) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2, failfast=True) diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py index a34387dc9..93569c4ec 100755 --- a/smoketest/scripts/cli/test_vpn_ipsec.py +++ b/smoketest/scripts/cli/test_vpn_ipsec.py @@ -126,9 +126,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.assertTrue(process_named_running('charon')) self.cli_delete(base_path) - self.cli_delete(nhrp_path) self.cli_delete(tunnel_path) - self.cli_delete(vti_path) self.cli_delete(ethernet_path) self.cli_commit() @@ -182,8 +180,10 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): swanctl_conf_lines = [ f'version = 2', f'auth = psk', + f'rekey_time = 28800s', # default value f'proposals = aes128-sha1-modp1024', f'esp_proposals = aes128-sha1-modp1024', + f'life_time = 3600s', # default value f'local_addrs = {local_address} # dhcp:no', f'remote_addrs = {peer_ip}', f'mode = tunnel', @@ -226,6 +226,11 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.cli_commit() swanctl_conf = read_file(swanctl_file) + if_id = vti.lstrip('vti') + # The key defaults to 0 and will match any policies which similarly do + # not have a lookup key configuration - thus we shift the key by one + # to also support a vti0 interface + if_id = str(int(if_id) +1) swanctl_conf_lines = [ f'version = 2', f'auth = psk', @@ -236,9 +241,9 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): f'mode = tunnel', f'local_ts = 172.16.10.0/24,172.16.11.0/24', f'remote_ts = 172.17.10.0/24,172.17.11.0/24', - f'if_id_in = {vti.lstrip("vti")}', # will be 10 for vti10 - f'if_id_out = {vti.lstrip("vti")}', - f'updown = "/etc/ipsec.d/vti-up-down {vti} no"' + f'if_id_in = {if_id}', # will be 11 for vti10 - shifted by one + f'if_id_out = {if_id}', + f'updown = "/etc/ipsec.d/vti-up-down {vti}"' ] for line in swanctl_conf_lines: self.assertIn(line, swanctl_conf) @@ -255,6 +260,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): def test_04_dmvpn(self): tunnel_if = 'tun100' nhrp_secret = 'secret' + ike_lifetime = '3600' + esp_lifetime = '1800' # Tunnel self.cli_set(tunnel_path + [tunnel_if, 'address', '172.16.253.134/29']) @@ -272,7 +279,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): # IKE/ESP Groups self.cli_set(base_path + ['esp-group', esp_group, 'compression', 'disable']) - self.cli_set(base_path + ['esp-group', esp_group, 'lifetime', '1800']) + self.cli_set(base_path + ['esp-group', esp_group, 'lifetime', esp_lifetime]) self.cli_set(base_path + ['esp-group', esp_group, 'mode', 'transport']) self.cli_set(base_path + ['esp-group', esp_group, 'pfs', 'dh-group2']) self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '2', 'encryption', 'aes256']) @@ -282,7 +289,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['ike-group', ike_group, 'ikev2-reauth', 'no']) self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev1']) - self.cli_set(base_path + ['ike-group', ike_group, 'lifetime', '3600']) + self.cli_set(base_path + ['ike-group', ike_group, 'lifetime', ike_lifetime]) self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'dh-group', '2']) self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'encryption', 'aes256']) self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'hash', 'sha1']) @@ -300,7 +307,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): swanctl_lines = [ f'proposals = aes128-sha1-modp1024,aes256-sha1-modp1024', f'version = 1', - f'rekey_time = 3600s', + f'life_time = {ike_lifetime}s', + f'rekey_time = {esp_lifetime}s', f'esp_proposals = aes128-sha1-modp1024,aes256-sha1-modp1024,3des-md5-modp1024', f'local_ts = dynamic[gre]', f'remote_ts = dynamic[gre]', @@ -310,6 +318,9 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): for line in swanctl_lines: self.assertIn(line, swanctl_conf) + # There is only one NHRP test so no need to delete this globally in tearDown() + self.cli_delete(nhrp_path) + def test_05_x509_site2site(self): # Enable PKI peer_name = 'peer1' @@ -341,6 +352,11 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): swanctl_conf = read_file(swanctl_file) tmp = peer_ip.replace('.', '-') + if_id = vti.lstrip('vti') + # The key defaults to 0 and will match any policies which similarly do + # not have a lookup key configuration - thus we shift the key by one + # to also support a vti0 interface + if_id = str(int(if_id) +1) swanctl_lines = [ f'peer_{tmp}', f'version = 0', # key-exchange not set - defaulting to 0 for ikev1 and ikev2 @@ -356,9 +372,9 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): f'remote_addrs = {peer_ip}', f'local_ts = 0.0.0.0/0,::/0', f'remote_ts = 0.0.0.0/0,::/0', - f'updown = "/etc/ipsec.d/vti-up-down {vti} no"', - f'if_id_in = {vti.lstrip("vti")}', # will be 10 for vti10 - f'if_id_out = {vti.lstrip("vti")}', + f'updown = "/etc/ipsec.d/vti-up-down {vti}"', + f'if_id_in = {if_id}', # will be 11 for vti10 + f'if_id_out = {if_id}', f'ipcomp = no', f'mode = tunnel', f'start_action = start', @@ -373,5 +389,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): for line in swanctl_secrets_lines: self.assertIn(line, swanctl_conf) + # There is only one VTI test so no need to delete this globally in tearDown() + self.cli_delete(vti_path) + if __name__ == '__main__': unittest.main(verbosity=2) |