def setUp(self): self.session = ConfigSession(os.getpid()) # ensure we can also run this test on a live system - so lets clean # out the current configuration :) self.session.delete(base_path)
class TestServiceBroadcastRelay(unittest.TestCase): _address1 = '192.0.2.1/24' _address2 = '192.0.2.1/24' def setUp(self): self.session = ConfigSession(os.getpid()) self.session.set( ['interfaces', 'dummy', 'dum1001', 'address', self._address1]) self.session.set( ['interfaces', 'dummy', 'dum1002', 'address', self._address2]) self.session.commit() def tearDown(self): self.session.delete(['interfaces', 'dummy', 'dum1001']) self.session.delete(['interfaces', 'dummy', 'dum1002']) self.session.delete(base_path) self.session.commit() del self.session def test_service(self): """ Check if broadcast relay service can be configured and runs """ ids = range(1, 5) for id in ids: base = base_path + ['id', str(id)] self.session.set(base + ['description', 'vyos']) self.session.set(base + ['port', str(10000 + id)]) # check validate() - two interfaces must be present with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base + ['interface', 'dum1001']) self.session.set(base + ['interface', 'dum1002']) self.session.set(base + ['address', self._address1.split('/')[0]]) self.session.commit() for id in ids: # check if process is running running = False for p in process_iter(): if "udp-broadcast-relay" in p.name(): if p.cmdline()[3] == str(id): running = True break self.assertTrue(running)
class TestSNMPService(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) # ensure we can also run this test on a live system - so lets clean # out the current configuration :) self.session.delete(base_path) def tearDown(self): del self.session def test_snmp(self): """ Check if SNMP can be configured and service runs """ clients = ['192.0.2.1', '2001:db8::1'] networks = ['192.0.2.128/25', '2001:db8:babe::/48'] listen = ['127.0.0.1', '::1'] for auth in ['ro', 'rw']: community = 'VyOS' + auth self.session.set(base_path + ['community', community, 'authorization', auth]) for client in clients: self.session.set(base_path + ['community', community, 'client', client]) for network in networks: self.session.set(base_path + ['community', community, 'network', network]) for addr in listen: self.session.set(base_path + ['listen-address', addr]) self.session.set(base_path + ['contact', '*****@*****.**']) self.session.set(base_path + ['location', 'qemu']) self.session.commit() # verify listen address, it will be returned as # ['unix:/run/snmpd.socket,udp:127.0.0.1:161,udp6:[::1]:161'] # thus we need to transfor this into a proper list config = get_config_value('agentaddress') expected = 'unix:/run/snmpd.socket' for addr in listen: if is_ipv4(addr): expected += ',udp:{}:161'.format(addr) else: expected += ',udp6:[{}]:161'.format(addr) self.assertTrue(expected in config) # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) def test_snmpv3_sha(self): """ Check if SNMPv3 can be configured with SHA authentication and service runs""" self.session.set(base_path + ['v3', 'engineid', '000000000000000000000002']) self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) # check validate() - a view must be created before this can be comitted with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base_path + ['v3', 'view', 'default', 'oid', '1']) self.session.set(base_path + ['v3', 'group', 'default', 'view', 'default']) # create user self.session.set(base_path + [ 'v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678' ]) self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'sha']) self.session.set(base_path + [ 'v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678' ]) self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'aes']) self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) self.session.commit() # commit will alter the CLI values - check if they have been updated: hashed_password = '******' tmp = self.session.show_config( base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) tmp = self.session.show_config( base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) # TODO: read in config file and check values # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) def test_snmpv3_md5(self): """ Check if SNMPv3 can be configured with MD5 authentication and service runs""" self.session.set(base_path + ['v3', 'engineid', '000000000000000000000002']) self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) # check validate() - a view must be created before this can be comitted with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base_path + ['v3', 'view', 'default', 'oid', '1']) self.session.set(base_path + ['v3', 'group', 'default', 'view', 'default']) # create user self.session.set(base_path + [ 'v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678' ]) self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'md5']) self.session.set(base_path + [ 'v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678' ]) self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'des']) self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) self.session.commit() # commit will alter the CLI values - check if they have been updated: hashed_password = '******' tmp = self.session.show_config( base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) tmp = self.session.show_config( base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) # TODO: read in config file and check values # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter()))
class TestServiceRADVD(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) self.session.set(address_base + ['2001:db8::1/64']) def tearDown(self): self.session.delete(address_base) self.session.delete(base_path) self.session.commit() del self.session def test_single(self): self.session.set(base_path + ['prefix', '::/64', 'no-on-link-flag']) self.session.set(base_path + ['prefix', '::/64', 'no-autonomous-flag']) self.session.set(base_path + ['prefix', '::/64', 'valid-lifetime', 'infinity']) self.session.set(base_path + ['dnssl', '2001:db8::1234']) self.session.set(base_path + ['other-config-flag']) # commit changes self.session.commit() # verify values tmp = get_config_value('interface') self.assertEqual(tmp, interface) tmp = get_config_value('prefix') self.assertEqual(tmp, '::/64') tmp = get_config_value('AdvOtherConfigFlag') self.assertEqual(tmp, 'on') # this is a default value tmp = get_config_value('AdvRetransTimer') self.assertEqual(tmp, '0') # this is a default value tmp = get_config_value('AdvCurHopLimit') self.assertEqual(tmp, '64') # this is a default value tmp = get_config_value('AdvDefaultPreference') self.assertEqual(tmp, 'medium') tmp = get_config_value('AdvAutonomous') self.assertEqual(tmp, 'off') # this is a default value tmp = get_config_value('AdvValidLifetime') self.assertEqual(tmp, 'infinity') # this is a default value tmp = get_config_value('AdvPreferredLifetime') self.assertEqual(tmp, '14400') tmp = get_config_value('AdvOnLink') self.assertEqual(tmp, 'off') # Check for running process self.assertTrue('radvd' in (p.name() for p in process_iter()))
def setUp(self): self.session = ConfigSession(os.getpid()) self.session.set(address_base + ['2001:db8::1/64'])
if len(sys.argv) < 2: print("Must specify boot config file.") sys.exit(1) else: file_name = sys.argv[1] # Set user and group options, so that others will be able to commit # Currently, the only caller does 'sg CFG_GROUP', but that may change cfg_group = grp.getgrnam(CFG_GROUP) os.setgid(cfg_group.gr_gid) # Need to set file permissions to 775 so that every vyattacfg group # member has write access to the running config os.umask(0o002) session = ConfigSession(os.getpid(), 'vyos-boot-config-loader') env = session.get_session_env() default_file_name = env['vyatta_sysconfdir'] + '/config.boot.default' try: with open(file_name, 'r') as f: config_file = f.read() except Exception: write_config_status(1) if trace_config: failsafe(default_file_name) trace_to_file(TRACE_FILE) sys.exit(1) try:
class TestVpnAnyconnect(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) def tearDown(self): # Delete vpn anyconnect configuration self.session.delete(base_path) self.session.commit() del self.session def test_vpn(self): user = '******' password = '******' self.session.delete(base_path) self.session.set(base_path + [ "authentication", "local-users", "username", user, "password", password ]) self.session.set(base_path + ["authentication", "mode", "local"]) self.session.set(base_path + [ "network-settings", "client-ip-settings", "subnet", "192.0.2.0/24" ]) self.session.set(base_path + ["ssl", "ca-cert-file", cert]) self.session.set(base_path + ["ssl", "cert-file", cert]) self.session.set(base_path + ["ssl", "key-file", cert_key]) self.session.commit() # Check for running process self.assertTrue("ocserv-main" in (p.name() for p in process_iter()))
def setUp(self): self.session = ConfigSession(os.getpid()) self._vrfs = ['red', 'green', 'blue']
class WWANInterfaceTest(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) self._interfaces = ['wlm0', 'wlm1'] def tearDown(self): self.session.delete(base_path) self.session.commit() del self.session def test_wlm_1(self): for interface in self._interfaces: self.session.set(base_path + [interface, 'no-peer-dns']) self.session.set(base_path + [interface, 'ondemand']) # check validate() - APN must be configure with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base_path + [interface, 'apn', 'vyos.net']) # check validate() - device must be configure with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base_path + [interface, 'device', 'ttyS0']) # commit changes self.session.commit() # verify configuration file(s) for interface in self._interfaces: tmp = get_config_value(interface, 'ifname')[1] self.assertTrue(interface in tmp) tmp = get_config_value(interface, 'demand')[0] self.assertTrue('demand' in tmp) tmp = os.path.isfile(f'/etc/ppp/peers/chat.{interface}') self.assertTrue(tmp) # 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)
class TestServiceDDNS(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) def tearDown(self): # Delete DDNS configuration self.session.delete(base_path) self.session.commit() del self.session def test_service(self): """ Check individual DDNS service providers """ ddns = ['interface', 'eth0', 'service'] services = ['cloudflare', 'afraid', 'dyndns', 'zoneedit'] for service in services: user = '******' password = '******' zone = 'vyos.io' self.session.delete(base_path) self.session.set(base_path + ddns + [service, 'host-name', 'test.ddns.vyos.io']) self.session.set(base_path + ddns + [service, 'login', user]) self.session.set(base_path + ddns + [service, 'password', password]) self.session.set(base_path + ddns + [service, 'zone', zone]) # commit changes if service == 'cloudflare': self.session.commit() else: # zone option only works on cloudflare, an exception is raised # for all others with self.assertRaises(ConfigSessionError): self.session.commit() self.session.delete(base_path + ddns + [service, 'zone', 'vyos.io']) # commit changes again - now it should work self.session.commit() # we can only read the configuration file when we operate as 'root' if getuser() == 'root': protocol = get_config_value('protocol') login = get_config_value('login') pwd = get_config_value('password') # some services need special treatment protoname = service if service == 'cloudflare': tmp = get_config_value('zone') self.assertTrue(tmp == zone) elif service == 'afraid': protoname = 'freedns' elif service == 'dyndns': protoname = 'dyndns2' elif service == 'zoneedit': protoname = 'zoneedit1' self.assertTrue(protocol == protoname) self.assertTrue(login == user) self.assertTrue(pwd == "'" + password + "'") # Check for running process self.assertTrue(check_process()) def test_rfc2136(self): """ Check if DDNS service can be configured and runs """ ddns = ['interface', 'eth0', 'rfc2136', 'vyos'] ddns_key_file = '/config/auth/my.key' self.session.set(base_path + ddns + ['key', ddns_key_file]) self.session.set(base_path + ddns + ['record', 'test.ddns.vyos.io']) self.session.set(base_path + ddns + ['server', 'ns1.vyos.io']) self.session.set(base_path + ddns + ['ttl', '300']) self.session.set(base_path + ddns + ['zone', 'vyos.io']) # ensure an exception will be raised as no key is present if os.path.exists(ddns_key_file): os.unlink(ddns_key_file) # check validate() - the key file does not exist yet with self.assertRaises(ConfigSessionError): self.session.commit() with open(ddns_key_file, 'w') as f: f.write('S3cretKey') # commit changes self.session.commit() # TODO: inspect generated configuration file # Check for running process self.assertTrue(check_process())
class VRFTest(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) self._vrfs = ['red', 'green', 'blue'] def tearDown(self): # delete all VRFs self.session.delete(['vrf']) self.session.commit() del self.session def test_table_id(self): table = 1000 for vrf in self._vrfs: base = ['vrf', 'name', vrf] description = "VyOS-VRF-" + vrf self.session.set(base + ['description', description]) # check validate() - a table ID is mandatory with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base + ['table', str(table)]) table += 1 # commit changes self.session.commit()
def setUp(self): self.session = ConfigSession(os.getpid()) self._interfaces = ['pppoe0', 'pppoe50'] self._source_interface = 'eth0'
class PPPoEInterfaceTest(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) self._interfaces = ['pppoe0', 'pppoe50'] self._source_interface = 'eth0' def tearDown(self): self.session.delete(base_path) self.session.commit() del self.session def test_pppoe(self): """ Check if PPPoE dialer can be configured and runs """ for interface in self._interfaces: user = '******' + interface passwd = 'VyOS-passwd-' + interface mtu = '1400' self.session.set(base_path + [interface, 'authentication', 'user', user]) self.session.set(base_path + [interface, 'authentication', 'password', passwd]) self.session.set(base_path + [interface, 'default-route', 'auto']) self.session.set(base_path + [interface, 'mtu', mtu]) self.session.set(base_path + [interface, 'no-peer-dns']) # check validate() - a source-interface is required with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set( base_path + [interface, 'source-interface', self._source_interface]) # commit changes self.session.commit() # verify configuration file(s) for interface in self._interfaces: user = '******' + interface password = '******' + interface tmp = get_config_value(interface, 'mtu')[1] self.assertEqual(tmp, mtu) tmp = get_config_value(interface, 'user')[1].replace('"', '') self.assertEqual(tmp, user) tmp = get_config_value(interface, 'password')[1].replace('"', '') self.assertEqual(tmp, password) 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_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.session.set(base_path + [interface, 'authentication', 'user', 'vyos']) self.session.set(base_path + [interface, 'authentication', 'password', 'vyos']) self.session.set(base_path + [interface, 'default-route', 'none']) self.session.set(base_path + [interface, 'no-peer-dns']) self.session.set( base_path + [interface, 'source-interface', self._source_interface]) self.session.set(base_path + [interface, 'ipv6', 'enable']) # prefix delegation stuff dhcpv6_pd_base = base_path + [ interface, 'dhcpv6-options', 'pd', '0' ] self.session.set(dhcpv6_pd_base + ['length', '56']) self.session.set( dhcpv6_pd_base + ['interface', self._source_interface, 'address', address]) self.session.set( dhcpv6_pd_base + ['interface', self._source_interface, 'sla-id', sla_id]) # commit changes self.session.commit() # verify "normal" PPPoE value - 1492 is default MTU tmp = get_config_value(interface, 'mtu')[1] self.assertEqual(tmp, '1492') tmp = get_config_value(interface, 'user')[1].replace('"', '') 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 start dhcp6c@{interface}.service', tmp) self.assertTrue(tmp)
class BaseTest(unittest.TestCase): _test_mtu = False _base_path = [] _options = {} _interfaces = [] def setUp(self): self.session = ConfigSession(os.getpid()) self._test_addr = [ '192.0.2.1/26', '192.0.2.255/31', '192.0.2.64/32', '2001:db8:1::ffff/64', '2001:db8:101::1/112' ] self._test_mtu = False self._options = {} def tearDown(self): # we should not remove ethernet from the overall CLI if 'ethernet' in self._base_path: self.session.delete(self._base_path) for intf in self._interfaces: self.session.set(self._base_path + [intf]) else: self.session.delete(self._base_path) self.session.commit() del self.session def test_add_description(self): """ Check if description can be added to interface """ for intf in self._interfaces: test_string = 'Description-Test-{}'.format(intf) self.session.set(self._base_path + [intf, 'description', test_string]) for option in self._options.get(intf, []): self.session.set(self._base_path + [intf] + option.split()) self.session.commit() # Validate interface description for intf in self._interfaces: test_string = 'Description-Test-{}'.format(intf) with open('/sys/class/net/{}/ifalias'.format(intf), 'r') as f: tmp = f.read().rstrip() self.assertTrue(tmp, test_string) def test_add_address_single(self): """ Check if a single address can be added to interface. """ addr = '192.0.2.0/31' for intf in self._interfaces: self.session.set(self._base_path + [intf, 'address', addr]) for option in self._options.get(intf, []): self.session.set(self._base_path + [intf] + option.split()) self.session.commit() for intf in self._interfaces: self.assertTrue(is_intf_addr_assigned(intf, addr)) def test_add_address_multi(self): """ Check if IPv4/IPv6 addresses can be added to interface. """ # Add address for intf in self._interfaces: for addr in self._test_addr: self.session.set(self._base_path + [intf, 'address', addr]) for option in self._options.get(intf, []): self.session.set(self._base_path + [intf] + option.split()) self.session.commit() # Validate address for intf in self._interfaces: for af in AF_INET, AF_INET6: for addr in ifaddresses(intf)[af]: # checking link local addresses makes no sense if is_ipv6_link_local(addr['addr']): continue self.assertTrue( is_intf_addr_assigned(intf, addr['addr'])) def test_change_mtu(self): """ Check if MTU can be changed on interface. Test MTU size will be 1400 bytes. """ if self._test_mtu is False: return None # choose a MTU which works on every interface mtu = '1400' for intf in self._interfaces: self.session.set(self._base_path + [intf, 'mtu', mtu]) for option in self._options.get(intf, []): self.session.set(self._base_path + [intf] + option.split()) self.session.commit() # Validate interface description for intf in self._interfaces: with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: tmp = f.read().rstrip() self.assertTrue(tmp == mtu)
class TestSystemLogin(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) def tearDown(self): # Delete individual users from configuration for user in users: self.session.delete(base_path + ['user', user]) self.session.commit() del self.session def test_user(self): """ Check if user can be created and we can SSH to localhost """ self.session.set(['service', 'ssh', 'port', '22']) for user in users: name = "VyOS Roxx " + user home_dir = "/tmp/" + user self.session.set( base_path + ['user', user, 'authentication', 'plaintext-password', user]) self.session.set(base_path + ['user', user, 'full-name', 'VyOS Roxx']) self.session.set(base_path + ['user', user, 'home-directory', home_dir]) self.session.commit() for user in users: cmd = ['su', '-', user] proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) tmp = "{}\nuname -a".format(user) proc.stdin.write(tmp.encode()) proc.stdin.flush() (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' self.assertTrue(len(stdout) > 40)
def setUp(self): self.session = ConfigSession(os.getpid()) self._interfaces = ['wlm0', 'wlm1']
def setUp(self): self.session = ConfigSession(os.getpid())
class TestServiceMDNSrepeater(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) def tearDown(self): self.session.delete(base_path) self.session.delete(intf_base + ['dum10']) self.session.delete(intf_base + ['dum20']) self.session.commit() del self.session def test_service(self): # Service required a configured IP address on the interface self.session.set(intf_base + ['dum10', 'address', '192.0.2.1/30']) self.session.set(intf_base + ['dum20', 'address', '192.0.2.5/30']) self.session.set(base_path + ['interface', 'dum10']) self.session.set(base_path + ['interface', 'dum20']) self.session.commit() # Check for running process self.assertTrue("mdns-repeater" in (p.name() for p in process_iter()))