Skip to content

Commit

Permalink
networking: Add wireguard keepalive and preshared-key option in the gui
Browse files Browse the repository at this point in the history
Update the tests accordingly.

fixes #19491
  • Loading branch information
subhoghoshX committed Oct 26, 2023
1 parent b2d2a4c commit 30ae48d
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 13 deletions.
25 changes: 23 additions & 2 deletions pkg/networkmanager/interfaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,8 @@ export function NetworkManagerModel() {
peers: get("wireguard", "peers", []).map(peer => ({
publicKey: peer['public-key'].v,
endpoint: peer.endpoint?.v, // enpoint of a peer is optional
allowedIps: peer['allowed-ips']?.v
allowedIps: peer['allowed-ips']?.v,
persistentKeepalive: peer['persistent-keepalive']?.v,
})),
};
}
Expand Down Expand Up @@ -730,7 +731,27 @@ export function NetworkManagerModel() {
"allowed-ips": {
t: "as",
v: peer.allowedIps
}
},
...peer.persistentKeepalive
? {
"persistent-keepalive": {
t: "u",
v: peer.persistentKeepalive
}
}
: {},
...peer.presharedKey
? {
"preshared-key": {
t: "s",
v: peer.presharedKey
},
'preshared-key-flags': {
t: "u",
v: 0
}
}
: {}
};
}));
} else {
Expand Down
50 changes: 45 additions & 5 deletions pkg/networkmanager/wireguard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { FormGroup, FormFieldGroup, FormFieldGroupHeader, FormHelperText } from
import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js";
import { Grid } from '@patternfly/react-core/dist/esm/layouts/Grid/index.js';
import { HelperText, HelperTextItem } from '@patternfly/react-core/dist/esm/components/HelperText/index';
import { InputGroup } from '@patternfly/react-core/dist/esm/components/InputGroup/index.js';
import { InputGroup, InputGroupItem, InputGroupText } from '@patternfly/react-core/dist/esm/components/InputGroup/index.js';
import { Popover } from '@patternfly/react-core/dist/esm/components/Popover/index.js';
import { Radio } from '@patternfly/react-core/dist/esm/components/Radio/index.js';
import { Text } from "@patternfly/react-core/dist/esm/components/Text/index.js";
Expand Down Expand Up @@ -73,7 +73,12 @@ export function WireGuardDialog({ settings, connection, dev }) {
const [listenPort, setListenPort] = useState(settings.wireguard.listen_port);
const [addresses, setAddresses] = useState(addressesToString(settings.ipv4.addresses));
const [dialogError, setDialogError] = useState("");
const [peers, setPeers] = useState(settings.wireguard.peers.map(peer => ({ ...peer, allowedIps: peer.allowedIps?.join(",") ?? '' })));
const [peers, setPeers] = useState(settings.wireguard.peers.map(peer => ({
...peer,
allowedIps: peer.allowedIps?.join(",") ?? '',
persistentKeepalive: peer.persistentKeepalive?.toString() ?? '',
presharedKey: peer.presharedKey ?? ''
})));

// Additional check for `wg` after install_dialog for non-packagekit and el8 environments
useEffect(() => {
Expand All @@ -98,6 +103,7 @@ export function WireGuardDialog({ settings, connection, dev }) {
const objpath = connection[" priv"].path;
const [result] = await model.client.call(objpath, "org.freedesktop.NetworkManager.Settings.Connection", "GetSecrets", ["wireguard"]);
setGeneratedPrivateKey(result.wireguard["private-key"].v);
setPeers(oldPeers => oldPeers.map((oldPeer, index) => ({ ...oldPeer, presharedKey: result.wireguard.peers?.v[index]["preshared-key"]?.v ?? '' })));
}

if (connection?.[" priv"].path) {
Expand Down Expand Up @@ -160,7 +166,11 @@ export function WireGuardDialog({ settings, connection, dev }) {
throw cockpit.format(_("Peer #$0 has invalid endpoint port. Port must be a number."), index + 1);
}
}
return ({ ...peer, allowedIps: peer.allowedIps.trim().split(',') });
if (peer.persistentKeepalive.trim()) {
if (isNaN(Number(peer.persistentKeepalive)))
throw cockpit.format(_("Peer #$0 has invalid persistent keepalive. It must be a number."), index + 1);
}
return ({ ...peer, allowedIps: peer.allowedIps.trim().split(','), persistentKeepalive: Number(peer.persistentKeepalive) });
});
} catch (e) {
setDialogError(typeof e === 'string' ? e : e.message);
Expand Down Expand Up @@ -285,7 +295,7 @@ export function WireGuardDialog({ settings, connection, dev }) {
actions={
<Button
variant='secondary'
onClick={() => setPeers(peers => [...peers, { publicKey: '', endpoint: '', allowedIps: '' }])}
onClick={() => setPeers(peers => [...peers, { publicKey: '', endpoint: '', allowedIps: '', persistentKeepalive: '', presharedKey: '' }])}
>
{_("Add peer")}
</Button>
Expand Down Expand Up @@ -315,7 +325,21 @@ export function WireGuardDialog({ settings, connection, dev }) {
id={idPrefix + '-endpoint-peer-' + i}
/>
</FormGroup>
<FormGroup className='pf-m-3-col-on-md' label={_("Allowed IPs")} fieldId={idPrefix + '-allowedips-peer-' + i}>
<FormGroup className='pf-m-3-col-on-md' label={_("Keepalive")} fieldId={idPrefix + '-keepalive-peer-' + i}>
<InputGroup>
<InputGroupItem isFill>
<TextInput
value={peer.persistentKeepalive}
onChange={(_, val) => {
setPeers(peers => peers.map((peer, index) => i === index ? { ...peer, persistentKeepalive: val } : peer));
}}
id={idPrefix + '-keepalive-peer-' + i}
/>
</InputGroupItem>
<InputGroupText className='pf-v5-u-text-nowrap'>{_("seconds")}</InputGroupText>
</InputGroup>
</FormGroup>
<FormGroup className='pf-m-6-col-on-md' label={_("Allowed IPs")} fieldId={idPrefix + '-allowedips-peer-' + i}>
<TextInput
value={peer.allowedIps}
onChange={(_, val) => {
Expand All @@ -324,6 +348,22 @@ export function WireGuardDialog({ settings, connection, dev }) {
id={idPrefix + '-allowedips-peer-' + i}
/>
</FormGroup>
<FormGroup className='pf-m-6-col-on-md' label={_("Preshared key")} fieldId={idPrefix + '-presharedkey-peer-' + i} labelIcon={
<Popover
bodyContent={_("Preshared key should be a random 32 byte bas64 encoded.")}
>
<Button variant='link' isInline><HelpIcon /></Button>
</Popover>
}>
<TextInput
value={peer.presharedKey}
onChange={(_, val) => {
setPeers(peers => peers.map((peer, index) => i === index ? { ...peer, presharedKey: val } : peer));
}}
placeholder={_("optional")}
id={idPrefix + '-presharedkey-peer-' + i}
/>
</FormGroup>
<FormGroup className='pf-m-1-col-on-md remove-button-group'>
<Button
variant='plain'
Expand Down
33 changes: 27 additions & 6 deletions test/verify/check-networkmanager-wireguard
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,29 @@ class TestWireGuard(packagelib.PackageCase, netlib.NetworkCase):
# peer
b.click("button:contains('Add peer')")
b.wait_visible("#network-wireguard-settings-peer-0")
b.set_input_text("#network-wireguard-settings-publickey-peer-0", m2_pubkey)
b.click("button:contains('Add peer')")
b.wait_visible("#network-wireguard-settings-peer-1")
b.set_input_text("#network-wireguard-settings-publickey-peer-1", m2_pubkey)
b.set_input_text("#network-wireguard-settings-endpoint-peer-1", f"192.168.100.12:{m2_port}")
b.set_input_text("#network-wireguard-settings-allowedips-peer-1", m2_ip4)

test_pubkey = m1.execute("head -c 32 /dev/random | base64").strip()
b.set_input_text("#network-wireguard-settings-publickey-peer-0", test_pubkey)
b.set_input_text("#network-wireguard-settings-endpoint-peer-0", " 192.168.100.12 ") # test that the extra spaces are trimmed
b.set_input_text("#network-wireguard-settings-allowedips-peer-0", f" {m2_ip4} ") # test that the extra spaces are trimmed
b.click("#network-wireguard-settings-save")
b.wait_visible(".pf-v5-c-alert:contains('Peer #1 has invalid endpoint. It must be specified as host:port, e.g. 1.2.3.4:51820 or example.com:51820')")
b.set_input_text("#network-wireguard-settings-endpoint-peer-0", "192.168.100.12:somestring")
b.click("#network-wireguard-settings-save")
b.wait_visible(".pf-v5-c-alert:contains('Peer #1 has invalid endpoint port. Port must be a number.')")
b.click("button:contains('Add peer')")
b.wait_visible("#network-wireguard-settings-peer-1")
b.set_input_text("#network-wireguard-settings-publickey-peer-1", m2_pubkey)
b.set_input_text("#network-wireguard-settings-endpoint-peer-1", f"192.168.100.12:{m2_port}")
b.set_input_text("#network-wireguard-settings-allowedips-peer-1", m2_ip4)
b.set_input_text("#network-wireguard-settings-endpoint-peer-0", "192.168.100.12:51820")
b.set_input_text("#network-wireguard-settings-keepalive-peer-0", "asdf")
b.click("#network-wireguard-settings-save")
b.wait_visible(".pf-v5-c-alert:contains('Peer #1 has invalid persistent keepalive. It must be a number.')")
b.set_input_text("#network-wireguard-settings-keepalive-peer-0", "60")
b.set_input_text("#network-wireguard-settings-presharedkey-peer-0", "invalidpsk")
b.click("#network-wireguard-settings-save")
b.wait_visible(".pf-v5-c-alert:contains('invalid preshared-key for peer')")
b.click("button#network-wireguard-settings-btn-close-peer-0")
b.wait_not_present("#network-wireguard-settings-peer-1")
b.assert_pixels("#network-wireguard-settings-dialog", "networking-wireguard-add-generated",
Expand All @@ -127,6 +137,16 @@ class TestWireGuard(packagelib.PackageCase, netlib.NetworkCase):
b.wait_not_present("#network-wireguard-settings-dialog")
b.wait_in_text(f"#networking-interfaces th:contains('{iface_name}') + td", f"1.2.3.4/32, {m1_ip4}/24")

b.click(f"#networking-interfaces button:contains('{iface_name}')")
b.wait_visible("#network-interface")
b.click("#networking-edit-wg")
b.wait_visible("#network-wireguard-settings-dialog")
b.set_input_text("#network-wireguard-settings-keepalive-peer-0", "120")
psk = m1.execute("head -c 32 /dev/random | base64").strip()
b.set_input_text("#network-wireguard-settings-presharedkey-peer-0", psk)
b.click("#network-wireguard-settings-save")
b.wait_not_present("#network-wireguard-settings-dialog")

# if some wg properties are not valid, for example, if it was changed by some external tool, don't crash
m1.execute("sed -i '/allowed-ips/d' /etc/NetworkManager/system-connections/con-wg0.nmconnection")
m1.execute("systemctl restart NetworkManager")
Expand All @@ -149,6 +169,7 @@ class TestWireGuard(packagelib.PackageCase, netlib.NetworkCase):
b2.click("button:contains('Add peer')")
b2.set_input_text("#network-wireguard-settings-publickey-peer-0", m1_pubkey)
b2.set_input_text("#network-wireguard-settings-allowedips-peer-0", f"{m1_ip4}/32")
b2.set_input_text("#network-wireguard-settings-presharedkey-peer-0", psk)
b2.click("#network-wireguard-settings-save")
b2.wait_not_present("#network-wireguard-settings-dialog")
b2.wait_in_text(f"#networking-interfaces th:contains('{m2_iface_name}') + td", f"{m2_ip4}/24")
Expand Down

0 comments on commit 30ae48d

Please sign in to comment.