Merge ~danilogondolfo/network-manager/+git/network-manager:new_autopkgtests into network-manager:ubuntu/master

Proposed by Danilo Egea Gondolfo
Status: Merged
Merge reported by: Lukas Märdian
Merged at revision: c358f28a92bcb4aec37d7d82c403331fcb29ddda
Proposed branch: ~danilogondolfo/network-manager/+git/network-manager:new_autopkgtests
Merge into: network-manager:ubuntu/master
Diff against target: 514 lines (+317/-31)
3 files modified
debian/tests/control (+1/-1)
debian/tests/nm.py (+173/-20)
debian/tests/nm_netplan.py (+143/-10)
Reviewer Review Type Date Requested Status
Lukas Märdian Approve
Sebastien Bacher Pending
Review via email: mp+443011@code.launchpad.net

This proposal supersedes a proposal from 2023-05-11.

Description of the change

New autopkgtests targeting the network manager + netplan integration.

I did some refactoring in nm.py so it's a bit easier to implement new tests that rely on wifi authentication.

The new tests are related to https://bugs.launchpad.net/netplan/+bug/2016473 and https://bugs.launchpad.net/netplan/+bug/2016625. The first one is not fixed yet but we are working on it.

To post a comment you must log in.
Revision history for this message
Lukas Märdian (slyon) wrote : Posted in a previous version of this proposal

Thank you! LGTM. I left one little (non-blocking) inline comment, which you could consider fixing.

This MP depends on some fixes in libnetplan, so we should hold it back until those fixed landed in Mantic. Once that's done (and the new autopkgtests PASS), we should rebase this MP against https://code.launchpad.net/~network-manager/network-manager/+git/ubuntu/+ref/ubuntu/master and get it landed via the offical NetworkManager package.

review: Approve
Revision history for this message
Lukas Märdian (slyon) wrote :

Thank you very much, Danilo! LGTM.

praise: I really like how you enhanced the generic NetworkManager tests in nm.py along the way and resolved an old FIXME!

I left two little (non-blocking) comments inline.

I moved the MP state to "Work in progress" as it's still pending the corresponding update to libnetplan. IMO this can be merged as soon as the new Netplan version hits mantic-proposed! This is the point where the new tests should start passing.

review: Approve
Revision history for this message
Danilo Egea Gondolfo (danilogondolfo) wrote :

Thanks, Lukas. I addressed your comments and implemented two new test cases related to Wireguard.

Revision history for this message
Lukas Märdian (slyon) wrote :

I'd like us to make sure that this test-case (from bug #1952967) is also supported (doesn't need to be using "nmtui", though):

> To test one can launch nmtui with the following command:
> network-manager.nmtui and then:
> - Proceed to add new connection
> - Select "IP tunnel"
> - enter a profile name e.g. "IP tunnel connection 1"
> - enter a device e.g. "gre10"
> - select mode "GRE"
> - enter local IP e.g. "10.20.20.1"
> - enter remote IP e.g. "10.20.20.2"
> - Press "OK" to save the connection

Revision history for this message
Danilo Egea Gondolfo (danilogondolfo) wrote :

Now that netplan.io 0.106.1 is in mantic-release, all these new tests will pass, see https://autopkgtest.ubuntu.com/results/autopkgtest-mantic-danilogondolfo-network-manager/mantic/amd64/n/network-manager/20230529_165124_321d1@/log.gz

May I ask someone from Desktop to take a look at it?

Revision history for this message
Lukas Märdian (slyon) wrote :

I talked to @seb128 and he agreed we can go ahead with uploading these new tests.

Rebased, merged and sponsored!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/tests/control b/debian/tests/control
index 1985292..e22c775 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -3,7 +3,7 @@ Depends: python3, hostapd, dnsmasq-base, wpasupplicant, isc-dhcp-client, iw
3Restrictions: needs-root allow-stderr isolation-machine skippable3Restrictions: needs-root allow-stderr isolation-machine skippable
44
5Tests: nm.py5Tests: nm.py
6Depends: python3, dnsmasq-base, isc-dhcp-client, gir1.2-nm-1.0, network-manager, hostapd, iw, python3-dbusmock, python3-netaddr, wpasupplicant6Depends: python3, dnsmasq-base, isc-dhcp-client, gir1.2-nm-1.0, network-manager, hostapd, iw, python3-dbusmock, python3-netaddr, wpasupplicant, easy-rsa
7Restrictions: needs-root isolation-machine skippable7Restrictions: needs-root isolation-machine skippable
88
9Tests: killswitches-no-urfkill9Tests: killswitches-no-urfkill
diff --git a/debian/tests/nm.py b/debian/tests/nm.py
index f7a03b7..2e59104 100755
--- a/debian/tests/nm.py
+++ b/debian/tests/nm.py
@@ -16,6 +16,7 @@ import socket
16import netaddr16import netaddr
17import unittest17import unittest
18import ctypes18import ctypes
19import shutil
1920
20try:21try:
21 from dbusmock import DBusTestCase22 from dbusmock import DBusTestCase
@@ -44,6 +45,102 @@ os.environ["GSETTINGS_BACKEND"] = "memory"
44os.dup2(sys.stdout.fileno(), sys.stderr.fileno())45os.dup2(sys.stdout.fileno(), sys.stderr.fileno())
4546
4647
48class WifiAuthentication():
49 def __init__(self):
50 self.wpa_settings = None
51 self.wpa_eap_settings = None
52 self.setting_name = None
53 self.needed_secrets = None
54
55 self.tmpdir = '/tmp/hostapd'
56 shutil.rmtree(self.tmpdir, ignore_errors=True)
57
58 @property
59 def auth_settings(self):
60 return self.wpa_settings
61
62 @property
63 def auth_eap_settings(self):
64 return self.wpa_eap_settings
65
66
67class WifiAuthenticationWPAPSK(WifiAuthentication):
68 def __init__(self, psk):
69 super().__init__()
70 self.wpa_settings = NM.SettingWirelessSecurity.new()
71 self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk")
72 self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_PSK, psk)
73
74 self.setting_name = NM.SETTING_WIRELESS_SECURITY_SETTING_NAME
75 self.needed_secrets = [NM.SETTING_WIRELESS_SECURITY_PSK]
76
77
78class WifiAuthenticationWPAEAP(WifiAuthentication):
79 def __init__(self, modes, phase2, identity, password, client_cert=False):
80 super().__init__()
81
82 self.make_certs()
83
84 self.wpa_settings = NM.SettingWirelessSecurity.new()
85 self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap")
86
87 self.wpa_eap_settings = NM.Setting8021x.new()
88 self.wpa_eap_settings.set_property(NM.SETTING_802_1X_EAP, modes)
89
90 self.wpa_eap_settings.set_property(NM.SETTING_802_1X_IDENTITY, identity)
91
92 if password:
93 self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PASSWORD, password)
94
95 if phase2 == 'tls':
96 self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PHASE2_AUTHEAP, phase2)
97 else:
98 self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PHASE2_AUTH, phase2)
99
100 if client_cert:
101 # Certificate paths must start with file:// and be null terminated
102 # See src/libnmc-setting/settings-docs.h
103 self.wpa_eap_settings.set_property(
104 NM.SETTING_802_1X_CA_CERT,
105 GLib.Bytes(f'file://{self.tmpdir}/pki/ca.crt\0'.encode()))
106 self.wpa_eap_settings.set_property(
107 NM.SETTING_802_1X_CLIENT_CERT,
108 GLib.Bytes(f'file://{self.tmpdir}/pki/issued/client.crt\0'.encode()))
109 self.wpa_eap_settings.set_property(
110 NM.SETTING_802_1X_PRIVATE_KEY,
111 GLib.Bytes(f'file://{self.tmpdir}/pki/private/client.key\0'.encode()))
112 self.wpa_eap_settings.set_property(
113 NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD, 'passw0rd')
114
115 self.setting_name = NM.SETTING_802_1X_SETTING_NAME
116 self.needed_secrets = [NM.SETTING_802_1X_PASSWORD, NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD]
117
118 def make_certs(self):
119 os.mkdir(self.tmpdir)
120
121 with open(f'{self.tmpdir}/hostapd.eap_user', 'w') as f:
122 f.write('''* PEAP,TLS
123
124"account1" MSCHAPV2 "password1" [2]
125"account2" MSCHAPV2 "password2" [2]
126''')
127
128 # Create a CA, server and client certificates protected by passw0rd and the DH parameters
129 create_ca_script = """/usr/share/easy-rsa/easyrsa init-pki
130EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-ca nopass
131EASYRSA_PASSOUT=pass:passw0rd EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-server-full server
132EASYRSA_PASSOUT=pass:passw0rd EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client
133/usr/share/easy-rsa/easyrsa gen-dh
134"""
135
136 with open(f'{self.tmpdir}/make_certs.sh', 'w') as f:
137 f.write(create_ca_script)
138
139 cmd = ['bash', 'make_certs.sh']
140 subprocess.call(cmd, stdout=subprocess.DEVNULL,
141 stderr=subprocess.DEVNULL, cwd=self.tmpdir)
142
143
47class NetworkManagerTest(network_test_base.NetworkTestBase):144class NetworkManagerTest(network_test_base.NetworkTestBase):
48 """Provide common functionality for NM tests"""145 """Provide common functionality for NM tests"""
49146
@@ -260,11 +357,11 @@ class NetworkManagerTest(network_test_base.NetworkTestBase):
260357
261 return self.nmdev_w.get_access_points()[0]358 return self.nmdev_w.get_access_points()[0]
262359
263 def connect_to_ap(self, ap, secret, ipv6_mode, ip6_privacy):360 def connect_to_ap(self, ap, auth_settings, ipv6_mode, ip6_privacy):
264 """Connect to an NMAccessPoint.361 """Connect to an NMAccessPoint.
265362
266 secret should be None for open networks, and a string with the password363 auth_settings should be None for open networks and an instance of
267 for WEP/WPA.364 WifiAuthentication for WEP/WPA-PSK/WPA-EAP.
268365
269 ip6_privacy is a NM.SettingIP6ConfigPrivacy flag.366 ip6_privacy is a NM.SettingIP6ConfigPrivacy flag.
270367
@@ -284,13 +381,10 @@ class NetworkManagerTest(network_test_base.NetworkTestBase):
284 # map of a map of gpointers to gpointers which is too much for PyGI381 # map of a map of gpointers to gpointers which is too much for PyGI
285 partial_conn = NM.SimpleConnection.new()382 partial_conn = NM.SimpleConnection.new()
286 partial_conn.add_setting(NM.SettingIP4Config(method=ip4_method))383 partial_conn.add_setting(NM.SettingIP4Config(method=ip4_method))
287 if secret:384 if auth_settings:
288 partial_conn.add_setting(NM.SettingWirelessSecurity.new())385 partial_conn.add_setting(auth_settings.auth_settings)
289 # FIXME: needs update for other auth types386 if isinstance(auth_settings, WifiAuthenticationWPAEAP):
290 partial_conn.update_secrets(387 partial_conn.add_setting(auth_settings.auth_eap_settings)
291 NM.SETTING_WIRELESS_SECURITY_SETTING_NAME,
292 GLib.Variant("a{sv}", {"psk": GLib.Variant("s", secret)}),
293 )
294 if ip6_privacy is not None:388 if ip6_privacy is not None:
295 partial_conn.add_setting(389 partial_conn.add_setting(
296 NM.SettingIP6Config(ip6_privacy=ip6_privacy, method=ip6_method)390 NM.SettingIP6Config(ip6_privacy=ip6_privacy, method=ip6_method)
@@ -344,16 +438,15 @@ class NetworkManagerTest(network_test_base.NetworkTestBase):
344438
345 # verify need_secrets()439 # verify need_secrets()
346 needed_secrets = conn.need_secrets()440 needed_secrets = conn.need_secrets()
347 if secret is None:441 if auth_settings is None:
348 self.assertEqual(needed_secrets, (None, []))442 self.assertEqual(needed_secrets, (None, []))
349 else:443 else:
350 self.assertEqual(444 self.assertEqual(
351 needed_secrets[0], NM.SETTING_WIRELESS_SECURITY_SETTING_NAME445 needed_secrets[0], auth_settings.setting_name
352 )446 )
353 self.assertEqual(type(needed_secrets[1]), list)447 self.assertEqual(type(needed_secrets[1]), list)
354 self.assertGreaterEqual(len(needed_secrets[1]), 1)448 self.assertGreaterEqual(len(needed_secrets[1]), 1)
355 # FIXME: needs update for other auth types449 self.assertIn(needed_secrets[1][0], auth_settings.needed_secrets)
356 self.assertIn(needed_secrets[1][0], [NM.SETTING_WIRELESS_SECURITY_PSK])
357450
358 # we are usually ACTIVATING at this point; wait for completion451 # we are usually ACTIVATING at this point; wait for completion
359 # TODO: 5s is not enough, argh slow DHCP client452 # TODO: 5s is not enough, argh slow DHCP client
@@ -540,7 +633,7 @@ wpa_passphrase=12345678
540 % SSID,633 % SSID,
541 None,634 None,
542 54000,635 54000,
543 "12345678",636 WifiAuthenticationWPAPSK('12345678'),
544 )637 )
545638
546 def test_wpa2_ip4(self):639 def test_wpa2_ip4(self):
@@ -558,7 +651,7 @@ wpa_passphrase=12345678
558 % SSID,651 % SSID,
559 None,652 None,
560 54000,653 54000,
561 "12345678",654 WifiAuthenticationWPAPSK('12345678'),
562 )655 )
563656
564 def test_wpa2_ip6(self):657 def test_wpa2_ip6(self):
@@ -576,10 +669,70 @@ wpa_passphrase=12345678
576 % SSID,669 % SSID,
577 "ra-only",670 "ra-only",
578 54000,671 54000,
579 "12345678",672 WifiAuthenticationWPAPSK('12345678'),
580 ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,673 ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,
581 )674 )
582675
676 def test_wpa_enterprise_authentication_ip4(self):
677 """WPA2 + 802.1x, 802.11g, IPv4"""
678
679 self.do_test(
680 """hw_mode=g
681channel=1
682ssid=%s
683auth_algs=1
684eap_server=1
685ieee8021x=1
686eapol_version=2
687wpa=2
688wpa_key_mgmt=WPA-EAP
689wpa_pairwise=TKIP
690rsn_pairwise=CCMP
691eap_user_file=/tmp/hostapd/hostapd.eap_user
692ca_cert=/tmp/hostapd/pki/ca.crt
693server_cert=/tmp/hostapd/pki/issued/server.crt
694private_key=/tmp/hostapd/pki/private/server.key
695private_key_passwd=passw0rd
696dh_file=/tmp/hostapd/pki/dh.pem
697ctrl_interface=/var/run/hostapd
698ctrl_interface_group=0
699"""
700 % SSID,
701 None,
702 54000,
703 WifiAuthenticationWPAEAP(['peap'], 'mschapv2', 'account1', 'password1')
704 )
705
706 def test_wpa_enterprise_authentication_with_client_certificate_ip4(self):
707 """WPA2 + 802.1x with client certificate, 802.11g, IPv4"""
708
709 self.do_test(
710 """hw_mode=g
711channel=1
712ssid=%s
713auth_algs=1
714eap_server=1
715ieee8021x=1
716eapol_version=2
717wpa=2
718wpa_key_mgmt=WPA-EAP
719wpa_pairwise=TKIP CCMP
720rsn_pairwise=TKIP CCMP
721eap_user_file=/tmp/hostapd/hostapd.eap_user
722ca_cert=/tmp/hostapd/pki/ca.crt
723server_cert=/tmp/hostapd/pki/issued/server.crt
724private_key=/tmp/hostapd/pki/private/server.key
725private_key_passwd=passw0rd
726dh_file=/tmp/hostapd/pki/dh.pem
727ctrl_interface=/var/run/hostapd
728ctrl_interface_group=0
729"""
730 % SSID,
731 None,
732 54000,
733 WifiAuthenticationWPAEAP(['tls'], 'tls', 'client', None, client_cert=True)
734 )
735
583 @network_test_base.run_in_subprocess736 @network_test_base.run_in_subprocess
584 def test_rfkill(self):737 def test_rfkill(self):
585 """shut down connection on killswitch, restore it on unblock"""738 """shut down connection on killswitch, restore it on unblock"""
@@ -626,7 +779,7 @@ wpa_passphrase=12345678
626 hostapd_conf,779 hostapd_conf,
627 ipv6_mode,780 ipv6_mode,
628 expected_max_bitrate,781 expected_max_bitrate,
629 secret=None,782 auth_settings=None,
630 ip6_privacy=None,783 ip6_privacy=None,
631 ):784 ):
632 """Actual test code, parameterized for the particular test case"""785 """Actual test code, parameterized for the particular test case"""
@@ -645,7 +798,7 @@ wpa_passphrase=12345678
645 self.assertEqual(self.filtered_active_connections(), [])798 self.assertEqual(self.filtered_active_connections(), [])
646799
647 # connect to that AP800 # connect to that AP
648 (conn, active_conn) = self.connect_to_ap(ap, secret, ipv6_mode, ip6_privacy)801 (conn, active_conn) = self.connect_to_ap(ap, auth_settings, ipv6_mode, ip6_privacy)
649802
650 # check NMActiveConnection object803 # check NMActiveConnection object
651 self.assertIn(804 self.assertIn(
@@ -660,7 +813,7 @@ wpa_passphrase=12345678
660 wireless_setting = conn.get_setting_wireless()813 wireless_setting = conn.get_setting_wireless()
661 self.assertEqual(wireless_setting.get_ssid().get_data(), SSID.encode())814 self.assertEqual(wireless_setting.get_ssid().get_data(), SSID.encode())
662 self.assertEqual(wireless_setting.get_hidden(), False)815 self.assertEqual(wireless_setting.get_hidden(), False)
663 if secret:816 if auth_settings:
664 self.assertEqual(817 self.assertEqual(
665 conn.get_setting_wireless_security().get_name(),818 conn.get_setting_wireless_security().get_name(),
666 NM.SETTING_WIRELESS_SECURITY_SETTING_NAME,819 NM.SETTING_WIRELESS_SECURITY_SETTING_NAME,
diff --git a/debian/tests/nm_netplan.py b/debian/tests/nm_netplan.py
index cc86bcf..b396627 100644
--- a/debian/tests/nm_netplan.py
+++ b/debian/tests/nm_netplan.py
@@ -103,13 +103,29 @@ class TestNetplan(unittest.TestCase):
103 subprocess.call(cmd, stdout=subprocess.DEVNULL)103 subprocess.call(cmd, stdout=subprocess.DEVNULL)
104104
105 def _add_connection(self, connection):105 def _add_connection(self, connection):
106 main_loop = GLib.MainLoop()106 self.main_loop = GLib.MainLoop()
107 self.cancel = Gio.Cancellable()
108 self.timeout_tag = 0
109
107 def add_cb(client, result, data):110 def add_cb(client, result, data):
108 self.nmclient.add_connection_finish(result)111 self.nmclient.add_connection_finish(result)
109 main_loop.quit()112 self.main_loop.quit()
113
114 def timeout_cb():
115 self.timeout_tag = -1
116 self.cancel.cancel()
117 self.main_loop.quit()
118 return GLib.SOURCE_REMOVE
119
120 self.timeout_tag = GLib.timeout_add_seconds(120, timeout_cb)
121
122 self.nmclient.add_connection_async(connection, True, self.cancel, add_cb, None)
123 self.main_loop.run()
124
125 if self.timeout_tag < 0:
126 self.timeout_tag = 0
127 self.fail('nm_netplan.py: main loop timed out during connection creation')
110128
111 self.nmclient.add_connection_async(connection, True, None, add_cb, None)
112 main_loop.run()
113129
114 def _delete_connection(self, connection):130 def _delete_connection(self, connection):
115 uuid = connection.get_uuid()131 uuid = connection.get_uuid()
@@ -124,7 +140,7 @@ class TestNetplan(unittest.TestCase):
124140
125 def _nmcli(self, parameters):141 def _nmcli(self, parameters):
126 cmd = ['nmcli'] + parameters142 cmd = ['nmcli'] + parameters
127 subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)143 return subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
128144
129 def _bridge_show(self, bridge):145 def _bridge_show(self, bridge):
130 cmd = ['bridge', '-j', 'link', 'show', bridge]146 cmd = ['bridge', '-j', 'link', 'show', bridge]
@@ -351,7 +367,6 @@ class TestNetplan(unittest.TestCase):
351 # There should be zero netplan NM yaml after deleting the bridge367 # There should be zero netplan NM yaml after deleting the bridge
352 self.assertEqual(self._get_number_of_yaml_files(), 0)368 self.assertEqual(self._get_number_of_yaml_files(), 0)
353369
354 @unittest.skip('XXX: the netplan yaml file will be deleted when we try to change the connetion')
355 def test_create_an_interface_and_change_it(self):370 def test_create_an_interface_and_change_it(self):
356 """Add a tap interface and change it after create adding IP addresses to it."""371 """Add a tap interface and change it after create adding IP addresses to it."""
357372
@@ -536,7 +551,7 @@ class TestNetplan(unittest.TestCase):
536 with open('/etc/netplan/10-test.yaml', 'w') as f:551 with open('/etc/netplan/10-test.yaml', 'w') as f:
537 f.write(netplan_yaml)552 f.write(netplan_yaml)
538553
539 self._netplan_generate();554 self._netplan_generate()
540 self._nmcli_con_reload()555 self._nmcli_con_reload()
541 self.nmclient = NM.Client.new()556 self.nmclient = NM.Client.new()
542557
@@ -565,7 +580,7 @@ class TestNetplan(unittest.TestCase):
565 with open('/etc/netplan/10-test.yaml', 'w') as f:580 with open('/etc/netplan/10-test.yaml', 'w') as f:
566 f.write(netplan_yaml)581 f.write(netplan_yaml)
567582
568 self._netplan_generate();583 self._netplan_generate()
569 self._nmcli_con_reload()584 self._nmcli_con_reload()
570 self.nmclient = NM.Client.new()585 self.nmclient = NM.Client.new()
571586
@@ -607,7 +622,7 @@ class TestNetplan(unittest.TestCase):
607 with open('/etc/netplan/10-test.yaml', 'w') as f:622 with open('/etc/netplan/10-test.yaml', 'w') as f:
608 f.write(netplan_yaml)623 f.write(netplan_yaml)
609624
610 self._netplan_generate();625 self._netplan_generate()
611 self._nmcli_con_reload()626 self._nmcli_con_reload()
612 self._nmcli(['con', 'mod', 'netplan-eth123', 'ipv4.method', 'auto'])627 self._nmcli(['con', 'mod', 'netplan-eth123', 'ipv4.method', 'auto'])
613628
@@ -672,7 +687,7 @@ EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client nopass
672 f.write(client_config)687 f.write(client_config)
673688
674 cmd = ['bash', 'openvpn_spinup.sh']689 cmd = ['bash', 'openvpn_spinup.sh']
675 subprocess.call(cmd, stdout=subprocess.DEVNULL)690 subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
676691
677 openvpn_server_cmd = ['openvpn', '--config', 'server.conf']692 openvpn_server_cmd = ['openvpn', '--config', 'server.conf']
678 p_server = subprocess.Popen(openvpn_server_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)693 p_server = subprocess.Popen(openvpn_server_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
@@ -711,6 +726,124 @@ EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client nopass
711 self.assertEqual(self._get_number_of_yaml_files(), 2,726 self.assertEqual(self._get_number_of_yaml_files(), 2,
712 msg='More than expected YAML files were found after stopping the OpenVPN server')727 msg='More than expected YAML files were found after stopping the OpenVPN server')
713728
729 def test_migrate_existing_tunnel_with_nmcli(self):
730 """
731 Change an existing tunnel defined in Netplan with nmcli so it will be "imported"
732 to NM. See LP: #2016473.
733 """
734
735 netplan_yaml = '''network:
736 renderer: NetworkManager
737 tunnels:
738 wg0:
739 mode: wireguard
740 port: 51821
741 key: YCNQCAes1OTbD2ynY+aBlaA5x4ZFJhsc4co+XHpZ4FU=
742 addresses:
743 - 172.17.0.1/24
744 peers:
745 - allowed-ips: [172.17.0.0/24]
746 endpoint: 4.4.4.4:51821
747 keys:
748 public: cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI='''
749
750 with open('/etc/netplan/10-test.yaml', 'w') as f:
751 f.write(netplan_yaml)
752
753 self._netplan_generate()
754 self._nmcli_con_reload()
755 self._nmcli(['con', 'mod', 'netplan-wg0', 'con-name', 'netplan-wireguard-wg0'])
756
757 # After being processed by NM (and libnetplan) the new file shouldn't
758 # redefine the interface type. If it does, "netplan get" will fail
759 # when it tries to load the YAML hierarchy.
760 out = subprocess.run(['netplan', 'get'],
761 capture_output=True, text=True)
762
763 self.assertEqual(out.returncode, 0, f'"netplan get" failed due to issues in the resulting YAML files.')
764
765 def test_create_wireguard_tunnel_in_multiple_steps_nmcli(self):
766 """
767 Network Manager should be able to create partial Wireguard connections
768
769 See: LP: #2016473
770 """
771
772 ret = self._nmcli(['con', 'add', 'type', 'wireguard', 'con-name', 'client-wg0', 'ifname', 'wg0', 'autoconnect', 'no'])
773 self.assertEqual(ret, 0, 'nmcli con add failed.')
774 ret = self._nmcli(['con', 'modify', 'client-wg0', 'ipv4.method', 'manual', 'ipv4.addresses', '10.1.2.3/24'])
775 self.assertEqual(ret, 0, 'nmcli ipv4 modify failed.')
776 ret = self._nmcli(['con', 'modify', 'client-wg0', 'wireguard.private-key', 'aPUcp5vHz8yMLrzk8SsDyYnV33IhE/k20e52iKJFV0A='])
777 self.assertEqual(ret, 0, 'nmcli add private key failed.')
778
779 # Use examples/python/gi/nm-wg-set to add one peer,
780 # nmcli doesn't support adding peers yet.
781 wg_peer_cmd = ['python3', 'examples/python/gi/nm-wg-set', 'client-wg0',
782 'peer', 'cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI=',
783 'endpoint', '1.2.3.4:12345', 'allowed-ips', '192.168.0.0/24']
784 out = subprocess.run(wg_peer_cmd, capture_output=True, text=True)
785 self.assertEqual(out.returncode, 0, 'nm-wg-set failed to add the peer')
786
787 def test_import_wireguard_profile_from_file(self):
788 """
789 Network Manager should be able to import a Wireguard connection
790 from a configuration file.
791
792 See: LP: #2016473
793 """
794 wg_profile = '''[Interface]
795PrivateKey = wFemfDk+MQbdHQnpADll/4fN/TaI7OPEMgbALP4BtF0=
796Address = 10.8.1.2/24
797DNS = 10.8.1.1
798[Peer]
799PublicKey = e3Yvr6qmGHGfOcF1wgsIWILT57FzpIgKjjP+AfcMwGI=
800AllowedIPs = 192.168.0.0/24
801Endpoint = 1.2.3.4:12345
802PersistentKeepalive = 15'''
803
804 wg_profile_path = '/etc/netplan/wg-client.conf'
805
806 with open(wg_profile_path, 'w') as f:
807 f.write(wg_profile)
808
809 ret = self._nmcli(['con', 'import', 'type', 'wireguard', 'file', wg_profile_path])
810 self.assertEqual(ret, 0, f'nmcli failed to import the Wireguard profile from {wg_profile_path}')
811
812 def test_create_wifi_connection_with_8021x(self):
813 """
814 See LP: #2016625.
815 """
816
817 openssl_cmd = [
818 'openssl', 'req', '-new', '-newkey', 'rsa:2048',
819 '-nodes', '-x509', '-subj',
820 '/C=US/ST=A/L=B/O=C/CN=www.a.com', '-keyout',
821 '/etc/netplan/a.key', '-out', '/etc/netplan/a.crt']
822
823 subprocess.check_output(openssl_cmd, universal_newlines=True,
824 stderr=subprocess.DEVNULL)
825
826 ret = self._nmcli(['con', 'add', 'con-name', 'eduroam',
827 'type', 'wifi', 'ssid', 'eduroam',
828 'wifi-sec.key-mgmt', 'wpa-eap', '802-1x.eap',
829 'peap', '802-1x.identity', 'user@example.org',
830 '802-1x.password', 'testing123',
831 '802-1x.phase2-auth', 'mschapv2',
832 '802-1x.ca-cert', '/etc/netplan/a.crt'])
833
834 self.assertEqual(ret, 0, 'nmcli failed to add connection')
835
836 def test_create_gre_connection(self):
837 """
838 Test case for LP: #1952967.
839 """
840
841 ret = self._nmcli(['con', 'add', 'con-name', '"IP tunnel connection 1"',
842 'type', 'ip-tunnel', 'ip-tunnel.mode', 'gre',
843 'ifname', 'gre10', 'remote',
844 '10.20.20.2', 'local', '10.20.20.1'])
845
846 self.assertEqual(ret, 0, 'nmcli failed to add connection')
714847
715if __name__ == '__main__':848if __name__ == '__main__':
716 runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)849 runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)

Subscribers

People subscribed via source and target branches