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
1diff --git a/debian/tests/control b/debian/tests/control
2index 1985292..e22c775 100644
3--- a/debian/tests/control
4+++ b/debian/tests/control
5@@ -3,7 +3,7 @@ Depends: python3, hostapd, dnsmasq-base, wpasupplicant, isc-dhcp-client, iw
6 Restrictions: needs-root allow-stderr isolation-machine skippable
7
8 Tests: nm.py
9-Depends: python3, dnsmasq-base, isc-dhcp-client, gir1.2-nm-1.0, network-manager, hostapd, iw, python3-dbusmock, python3-netaddr, wpasupplicant
10+Depends: python3, dnsmasq-base, isc-dhcp-client, gir1.2-nm-1.0, network-manager, hostapd, iw, python3-dbusmock, python3-netaddr, wpasupplicant, easy-rsa
11 Restrictions: needs-root isolation-machine skippable
12
13 Tests: killswitches-no-urfkill
14diff --git a/debian/tests/nm.py b/debian/tests/nm.py
15index f7a03b7..2e59104 100755
16--- a/debian/tests/nm.py
17+++ b/debian/tests/nm.py
18@@ -16,6 +16,7 @@ import socket
19 import netaddr
20 import unittest
21 import ctypes
22+import shutil
23
24 try:
25 from dbusmock import DBusTestCase
26@@ -44,6 +45,102 @@ os.environ["GSETTINGS_BACKEND"] = "memory"
27 os.dup2(sys.stdout.fileno(), sys.stderr.fileno())
28
29
30+class WifiAuthentication():
31+ def __init__(self):
32+ self.wpa_settings = None
33+ self.wpa_eap_settings = None
34+ self.setting_name = None
35+ self.needed_secrets = None
36+
37+ self.tmpdir = '/tmp/hostapd'
38+ shutil.rmtree(self.tmpdir, ignore_errors=True)
39+
40+ @property
41+ def auth_settings(self):
42+ return self.wpa_settings
43+
44+ @property
45+ def auth_eap_settings(self):
46+ return self.wpa_eap_settings
47+
48+
49+class WifiAuthenticationWPAPSK(WifiAuthentication):
50+ def __init__(self, psk):
51+ super().__init__()
52+ self.wpa_settings = NM.SettingWirelessSecurity.new()
53+ self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk")
54+ self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_PSK, psk)
55+
56+ self.setting_name = NM.SETTING_WIRELESS_SECURITY_SETTING_NAME
57+ self.needed_secrets = [NM.SETTING_WIRELESS_SECURITY_PSK]
58+
59+
60+class WifiAuthenticationWPAEAP(WifiAuthentication):
61+ def __init__(self, modes, phase2, identity, password, client_cert=False):
62+ super().__init__()
63+
64+ self.make_certs()
65+
66+ self.wpa_settings = NM.SettingWirelessSecurity.new()
67+ self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap")
68+
69+ self.wpa_eap_settings = NM.Setting8021x.new()
70+ self.wpa_eap_settings.set_property(NM.SETTING_802_1X_EAP, modes)
71+
72+ self.wpa_eap_settings.set_property(NM.SETTING_802_1X_IDENTITY, identity)
73+
74+ if password:
75+ self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PASSWORD, password)
76+
77+ if phase2 == 'tls':
78+ self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PHASE2_AUTHEAP, phase2)
79+ else:
80+ self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PHASE2_AUTH, phase2)
81+
82+ if client_cert:
83+ # Certificate paths must start with file:// and be null terminated
84+ # See src/libnmc-setting/settings-docs.h
85+ self.wpa_eap_settings.set_property(
86+ NM.SETTING_802_1X_CA_CERT,
87+ GLib.Bytes(f'file://{self.tmpdir}/pki/ca.crt\0'.encode()))
88+ self.wpa_eap_settings.set_property(
89+ NM.SETTING_802_1X_CLIENT_CERT,
90+ GLib.Bytes(f'file://{self.tmpdir}/pki/issued/client.crt\0'.encode()))
91+ self.wpa_eap_settings.set_property(
92+ NM.SETTING_802_1X_PRIVATE_KEY,
93+ GLib.Bytes(f'file://{self.tmpdir}/pki/private/client.key\0'.encode()))
94+ self.wpa_eap_settings.set_property(
95+ NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD, 'passw0rd')
96+
97+ self.setting_name = NM.SETTING_802_1X_SETTING_NAME
98+ self.needed_secrets = [NM.SETTING_802_1X_PASSWORD, NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD]
99+
100+ def make_certs(self):
101+ os.mkdir(self.tmpdir)
102+
103+ with open(f'{self.tmpdir}/hostapd.eap_user', 'w') as f:
104+ f.write('''* PEAP,TLS
105+
106+"account1" MSCHAPV2 "password1" [2]
107+"account2" MSCHAPV2 "password2" [2]
108+''')
109+
110+ # Create a CA, server and client certificates protected by passw0rd and the DH parameters
111+ create_ca_script = """/usr/share/easy-rsa/easyrsa init-pki
112+EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-ca nopass
113+EASYRSA_PASSOUT=pass:passw0rd EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-server-full server
114+EASYRSA_PASSOUT=pass:passw0rd EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client
115+/usr/share/easy-rsa/easyrsa gen-dh
116+"""
117+
118+ with open(f'{self.tmpdir}/make_certs.sh', 'w') as f:
119+ f.write(create_ca_script)
120+
121+ cmd = ['bash', 'make_certs.sh']
122+ subprocess.call(cmd, stdout=subprocess.DEVNULL,
123+ stderr=subprocess.DEVNULL, cwd=self.tmpdir)
124+
125+
126 class NetworkManagerTest(network_test_base.NetworkTestBase):
127 """Provide common functionality for NM tests"""
128
129@@ -260,11 +357,11 @@ class NetworkManagerTest(network_test_base.NetworkTestBase):
130
131 return self.nmdev_w.get_access_points()[0]
132
133- def connect_to_ap(self, ap, secret, ipv6_mode, ip6_privacy):
134+ def connect_to_ap(self, ap, auth_settings, ipv6_mode, ip6_privacy):
135 """Connect to an NMAccessPoint.
136
137- secret should be None for open networks, and a string with the password
138- for WEP/WPA.
139+ auth_settings should be None for open networks and an instance of
140+ WifiAuthentication for WEP/WPA-PSK/WPA-EAP.
141
142 ip6_privacy is a NM.SettingIP6ConfigPrivacy flag.
143
144@@ -284,13 +381,10 @@ class NetworkManagerTest(network_test_base.NetworkTestBase):
145 # map of a map of gpointers to gpointers which is too much for PyGI
146 partial_conn = NM.SimpleConnection.new()
147 partial_conn.add_setting(NM.SettingIP4Config(method=ip4_method))
148- if secret:
149- partial_conn.add_setting(NM.SettingWirelessSecurity.new())
150- # FIXME: needs update for other auth types
151- partial_conn.update_secrets(
152- NM.SETTING_WIRELESS_SECURITY_SETTING_NAME,
153- GLib.Variant("a{sv}", {"psk": GLib.Variant("s", secret)}),
154- )
155+ if auth_settings:
156+ partial_conn.add_setting(auth_settings.auth_settings)
157+ if isinstance(auth_settings, WifiAuthenticationWPAEAP):
158+ partial_conn.add_setting(auth_settings.auth_eap_settings)
159 if ip6_privacy is not None:
160 partial_conn.add_setting(
161 NM.SettingIP6Config(ip6_privacy=ip6_privacy, method=ip6_method)
162@@ -344,16 +438,15 @@ class NetworkManagerTest(network_test_base.NetworkTestBase):
163
164 # verify need_secrets()
165 needed_secrets = conn.need_secrets()
166- if secret is None:
167+ if auth_settings is None:
168 self.assertEqual(needed_secrets, (None, []))
169 else:
170 self.assertEqual(
171- needed_secrets[0], NM.SETTING_WIRELESS_SECURITY_SETTING_NAME
172+ needed_secrets[0], auth_settings.setting_name
173 )
174 self.assertEqual(type(needed_secrets[1]), list)
175 self.assertGreaterEqual(len(needed_secrets[1]), 1)
176- # FIXME: needs update for other auth types
177- self.assertIn(needed_secrets[1][0], [NM.SETTING_WIRELESS_SECURITY_PSK])
178+ self.assertIn(needed_secrets[1][0], auth_settings.needed_secrets)
179
180 # we are usually ACTIVATING at this point; wait for completion
181 # TODO: 5s is not enough, argh slow DHCP client
182@@ -540,7 +633,7 @@ wpa_passphrase=12345678
183 % SSID,
184 None,
185 54000,
186- "12345678",
187+ WifiAuthenticationWPAPSK('12345678'),
188 )
189
190 def test_wpa2_ip4(self):
191@@ -558,7 +651,7 @@ wpa_passphrase=12345678
192 % SSID,
193 None,
194 54000,
195- "12345678",
196+ WifiAuthenticationWPAPSK('12345678'),
197 )
198
199 def test_wpa2_ip6(self):
200@@ -576,10 +669,70 @@ wpa_passphrase=12345678
201 % SSID,
202 "ra-only",
203 54000,
204- "12345678",
205+ WifiAuthenticationWPAPSK('12345678'),
206 ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,
207 )
208
209+ def test_wpa_enterprise_authentication_ip4(self):
210+ """WPA2 + 802.1x, 802.11g, IPv4"""
211+
212+ self.do_test(
213+ """hw_mode=g
214+channel=1
215+ssid=%s
216+auth_algs=1
217+eap_server=1
218+ieee8021x=1
219+eapol_version=2
220+wpa=2
221+wpa_key_mgmt=WPA-EAP
222+wpa_pairwise=TKIP
223+rsn_pairwise=CCMP
224+eap_user_file=/tmp/hostapd/hostapd.eap_user
225+ca_cert=/tmp/hostapd/pki/ca.crt
226+server_cert=/tmp/hostapd/pki/issued/server.crt
227+private_key=/tmp/hostapd/pki/private/server.key
228+private_key_passwd=passw0rd
229+dh_file=/tmp/hostapd/pki/dh.pem
230+ctrl_interface=/var/run/hostapd
231+ctrl_interface_group=0
232+"""
233+ % SSID,
234+ None,
235+ 54000,
236+ WifiAuthenticationWPAEAP(['peap'], 'mschapv2', 'account1', 'password1')
237+ )
238+
239+ def test_wpa_enterprise_authentication_with_client_certificate_ip4(self):
240+ """WPA2 + 802.1x with client certificate, 802.11g, IPv4"""
241+
242+ self.do_test(
243+ """hw_mode=g
244+channel=1
245+ssid=%s
246+auth_algs=1
247+eap_server=1
248+ieee8021x=1
249+eapol_version=2
250+wpa=2
251+wpa_key_mgmt=WPA-EAP
252+wpa_pairwise=TKIP CCMP
253+rsn_pairwise=TKIP CCMP
254+eap_user_file=/tmp/hostapd/hostapd.eap_user
255+ca_cert=/tmp/hostapd/pki/ca.crt
256+server_cert=/tmp/hostapd/pki/issued/server.crt
257+private_key=/tmp/hostapd/pki/private/server.key
258+private_key_passwd=passw0rd
259+dh_file=/tmp/hostapd/pki/dh.pem
260+ctrl_interface=/var/run/hostapd
261+ctrl_interface_group=0
262+"""
263+ % SSID,
264+ None,
265+ 54000,
266+ WifiAuthenticationWPAEAP(['tls'], 'tls', 'client', None, client_cert=True)
267+ )
268+
269 @network_test_base.run_in_subprocess
270 def test_rfkill(self):
271 """shut down connection on killswitch, restore it on unblock"""
272@@ -626,7 +779,7 @@ wpa_passphrase=12345678
273 hostapd_conf,
274 ipv6_mode,
275 expected_max_bitrate,
276- secret=None,
277+ auth_settings=None,
278 ip6_privacy=None,
279 ):
280 """Actual test code, parameterized for the particular test case"""
281@@ -645,7 +798,7 @@ wpa_passphrase=12345678
282 self.assertEqual(self.filtered_active_connections(), [])
283
284 # connect to that AP
285- (conn, active_conn) = self.connect_to_ap(ap, secret, ipv6_mode, ip6_privacy)
286+ (conn, active_conn) = self.connect_to_ap(ap, auth_settings, ipv6_mode, ip6_privacy)
287
288 # check NMActiveConnection object
289 self.assertIn(
290@@ -660,7 +813,7 @@ wpa_passphrase=12345678
291 wireless_setting = conn.get_setting_wireless()
292 self.assertEqual(wireless_setting.get_ssid().get_data(), SSID.encode())
293 self.assertEqual(wireless_setting.get_hidden(), False)
294- if secret:
295+ if auth_settings:
296 self.assertEqual(
297 conn.get_setting_wireless_security().get_name(),
298 NM.SETTING_WIRELESS_SECURITY_SETTING_NAME,
299diff --git a/debian/tests/nm_netplan.py b/debian/tests/nm_netplan.py
300index cc86bcf..b396627 100644
301--- a/debian/tests/nm_netplan.py
302+++ b/debian/tests/nm_netplan.py
303@@ -103,13 +103,29 @@ class TestNetplan(unittest.TestCase):
304 subprocess.call(cmd, stdout=subprocess.DEVNULL)
305
306 def _add_connection(self, connection):
307- main_loop = GLib.MainLoop()
308+ self.main_loop = GLib.MainLoop()
309+ self.cancel = Gio.Cancellable()
310+ self.timeout_tag = 0
311+
312 def add_cb(client, result, data):
313 self.nmclient.add_connection_finish(result)
314- main_loop.quit()
315+ self.main_loop.quit()
316+
317+ def timeout_cb():
318+ self.timeout_tag = -1
319+ self.cancel.cancel()
320+ self.main_loop.quit()
321+ return GLib.SOURCE_REMOVE
322+
323+ self.timeout_tag = GLib.timeout_add_seconds(120, timeout_cb)
324+
325+ self.nmclient.add_connection_async(connection, True, self.cancel, add_cb, None)
326+ self.main_loop.run()
327+
328+ if self.timeout_tag < 0:
329+ self.timeout_tag = 0
330+ self.fail('nm_netplan.py: main loop timed out during connection creation')
331
332- self.nmclient.add_connection_async(connection, True, None, add_cb, None)
333- main_loop.run()
334
335 def _delete_connection(self, connection):
336 uuid = connection.get_uuid()
337@@ -124,7 +140,7 @@ class TestNetplan(unittest.TestCase):
338
339 def _nmcli(self, parameters):
340 cmd = ['nmcli'] + parameters
341- subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
342+ return subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
343
344 def _bridge_show(self, bridge):
345 cmd = ['bridge', '-j', 'link', 'show', bridge]
346@@ -351,7 +367,6 @@ class TestNetplan(unittest.TestCase):
347 # There should be zero netplan NM yaml after deleting the bridge
348 self.assertEqual(self._get_number_of_yaml_files(), 0)
349
350- @unittest.skip('XXX: the netplan yaml file will be deleted when we try to change the connetion')
351 def test_create_an_interface_and_change_it(self):
352 """Add a tap interface and change it after create adding IP addresses to it."""
353
354@@ -536,7 +551,7 @@ class TestNetplan(unittest.TestCase):
355 with open('/etc/netplan/10-test.yaml', 'w') as f:
356 f.write(netplan_yaml)
357
358- self._netplan_generate();
359+ self._netplan_generate()
360 self._nmcli_con_reload()
361 self.nmclient = NM.Client.new()
362
363@@ -565,7 +580,7 @@ class TestNetplan(unittest.TestCase):
364 with open('/etc/netplan/10-test.yaml', 'w') as f:
365 f.write(netplan_yaml)
366
367- self._netplan_generate();
368+ self._netplan_generate()
369 self._nmcli_con_reload()
370 self.nmclient = NM.Client.new()
371
372@@ -607,7 +622,7 @@ class TestNetplan(unittest.TestCase):
373 with open('/etc/netplan/10-test.yaml', 'w') as f:
374 f.write(netplan_yaml)
375
376- self._netplan_generate();
377+ self._netplan_generate()
378 self._nmcli_con_reload()
379 self._nmcli(['con', 'mod', 'netplan-eth123', 'ipv4.method', 'auto'])
380
381@@ -672,7 +687,7 @@ EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client nopass
382 f.write(client_config)
383
384 cmd = ['bash', 'openvpn_spinup.sh']
385- subprocess.call(cmd, stdout=subprocess.DEVNULL)
386+ subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
387
388 openvpn_server_cmd = ['openvpn', '--config', 'server.conf']
389 p_server = subprocess.Popen(openvpn_server_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
390@@ -711,6 +726,124 @@ EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client nopass
391 self.assertEqual(self._get_number_of_yaml_files(), 2,
392 msg='More than expected YAML files were found after stopping the OpenVPN server')
393
394+ def test_migrate_existing_tunnel_with_nmcli(self):
395+ """
396+ Change an existing tunnel defined in Netplan with nmcli so it will be "imported"
397+ to NM. See LP: #2016473.
398+ """
399+
400+ netplan_yaml = '''network:
401+ renderer: NetworkManager
402+ tunnels:
403+ wg0:
404+ mode: wireguard
405+ port: 51821
406+ key: YCNQCAes1OTbD2ynY+aBlaA5x4ZFJhsc4co+XHpZ4FU=
407+ addresses:
408+ - 172.17.0.1/24
409+ peers:
410+ - allowed-ips: [172.17.0.0/24]
411+ endpoint: 4.4.4.4:51821
412+ keys:
413+ public: cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI='''
414+
415+ with open('/etc/netplan/10-test.yaml', 'w') as f:
416+ f.write(netplan_yaml)
417+
418+ self._netplan_generate()
419+ self._nmcli_con_reload()
420+ self._nmcli(['con', 'mod', 'netplan-wg0', 'con-name', 'netplan-wireguard-wg0'])
421+
422+ # After being processed by NM (and libnetplan) the new file shouldn't
423+ # redefine the interface type. If it does, "netplan get" will fail
424+ # when it tries to load the YAML hierarchy.
425+ out = subprocess.run(['netplan', 'get'],
426+ capture_output=True, text=True)
427+
428+ self.assertEqual(out.returncode, 0, f'"netplan get" failed due to issues in the resulting YAML files.')
429+
430+ def test_create_wireguard_tunnel_in_multiple_steps_nmcli(self):
431+ """
432+ Network Manager should be able to create partial Wireguard connections
433+
434+ See: LP: #2016473
435+ """
436+
437+ ret = self._nmcli(['con', 'add', 'type', 'wireguard', 'con-name', 'client-wg0', 'ifname', 'wg0', 'autoconnect', 'no'])
438+ self.assertEqual(ret, 0, 'nmcli con add failed.')
439+ ret = self._nmcli(['con', 'modify', 'client-wg0', 'ipv4.method', 'manual', 'ipv4.addresses', '10.1.2.3/24'])
440+ self.assertEqual(ret, 0, 'nmcli ipv4 modify failed.')
441+ ret = self._nmcli(['con', 'modify', 'client-wg0', 'wireguard.private-key', 'aPUcp5vHz8yMLrzk8SsDyYnV33IhE/k20e52iKJFV0A='])
442+ self.assertEqual(ret, 0, 'nmcli add private key failed.')
443+
444+ # Use examples/python/gi/nm-wg-set to add one peer,
445+ # nmcli doesn't support adding peers yet.
446+ wg_peer_cmd = ['python3', 'examples/python/gi/nm-wg-set', 'client-wg0',
447+ 'peer', 'cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI=',
448+ 'endpoint', '1.2.3.4:12345', 'allowed-ips', '192.168.0.0/24']
449+ out = subprocess.run(wg_peer_cmd, capture_output=True, text=True)
450+ self.assertEqual(out.returncode, 0, 'nm-wg-set failed to add the peer')
451+
452+ def test_import_wireguard_profile_from_file(self):
453+ """
454+ Network Manager should be able to import a Wireguard connection
455+ from a configuration file.
456+
457+ See: LP: #2016473
458+ """
459+ wg_profile = '''[Interface]
460+PrivateKey = wFemfDk+MQbdHQnpADll/4fN/TaI7OPEMgbALP4BtF0=
461+Address = 10.8.1.2/24
462+DNS = 10.8.1.1
463+[Peer]
464+PublicKey = e3Yvr6qmGHGfOcF1wgsIWILT57FzpIgKjjP+AfcMwGI=
465+AllowedIPs = 192.168.0.0/24
466+Endpoint = 1.2.3.4:12345
467+PersistentKeepalive = 15'''
468+
469+ wg_profile_path = '/etc/netplan/wg-client.conf'
470+
471+ with open(wg_profile_path, 'w') as f:
472+ f.write(wg_profile)
473+
474+ ret = self._nmcli(['con', 'import', 'type', 'wireguard', 'file', wg_profile_path])
475+ self.assertEqual(ret, 0, f'nmcli failed to import the Wireguard profile from {wg_profile_path}')
476+
477+ def test_create_wifi_connection_with_8021x(self):
478+ """
479+ See LP: #2016625.
480+ """
481+
482+ openssl_cmd = [
483+ 'openssl', 'req', '-new', '-newkey', 'rsa:2048',
484+ '-nodes', '-x509', '-subj',
485+ '/C=US/ST=A/L=B/O=C/CN=www.a.com', '-keyout',
486+ '/etc/netplan/a.key', '-out', '/etc/netplan/a.crt']
487+
488+ subprocess.check_output(openssl_cmd, universal_newlines=True,
489+ stderr=subprocess.DEVNULL)
490+
491+ ret = self._nmcli(['con', 'add', 'con-name', 'eduroam',
492+ 'type', 'wifi', 'ssid', 'eduroam',
493+ 'wifi-sec.key-mgmt', 'wpa-eap', '802-1x.eap',
494+ 'peap', '802-1x.identity', 'user@example.org',
495+ '802-1x.password', 'testing123',
496+ '802-1x.phase2-auth', 'mschapv2',
497+ '802-1x.ca-cert', '/etc/netplan/a.crt'])
498+
499+ self.assertEqual(ret, 0, 'nmcli failed to add connection')
500+
501+ def test_create_gre_connection(self):
502+ """
503+ Test case for LP: #1952967.
504+ """
505+
506+ ret = self._nmcli(['con', 'add', 'con-name', '"IP tunnel connection 1"',
507+ 'type', 'ip-tunnel', 'ip-tunnel.mode', 'gre',
508+ 'ifname', 'gre10', 'remote',
509+ '10.20.20.2', 'local', '10.20.20.1'])
510+
511+ self.assertEqual(ret, 0, 'nmcli failed to add connection')
512
513 if __name__ == '__main__':
514 runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)

Subscribers

People subscribed via source and target branches