From 3bc11384b38879091df0671fa4231c31cca9c58d Mon Sep 17 00:00:00 2001 From: Subho Date: Mon, 26 Jun 2023 21:34:29 +0530 Subject: [PATCH] network: wireguard WIP --- pkg/networkmanager/dialogs-common.jsx | 33 ++- pkg/networkmanager/interfaces.js | 65 ++++- pkg/networkmanager/network-interface.jsx | 16 +- pkg/networkmanager/network-main.jsx | 1 + pkg/networkmanager/wireguard.jsx | 262 +++++++++++++++++++++ pkg/networkmanager/wireguard.scss | 28 +++ test/run | 2 +- test/verify/check-networkmanager-wireguard | 58 +++++ 8 files changed, 447 insertions(+), 18 deletions(-) create mode 100644 pkg/networkmanager/wireguard.jsx create mode 100644 pkg/networkmanager/wireguard.scss create mode 100755 test/verify/check-networkmanager-wireguard diff --git a/pkg/networkmanager/dialogs-common.jsx b/pkg/networkmanager/dialogs-common.jsx index 8d403295cf3b..ad1c9feba397 100644 --- a/pkg/networkmanager/dialogs-common.jsx +++ b/pkg/networkmanager/dialogs-common.jsx @@ -35,11 +35,14 @@ import { IpSettingsDialog } from './ip-settings.jsx'; import { TeamDialog, getGhostSettings as getTeamGhostSettings } from './team.jsx'; import { TeamPortDialog } from './teamport.jsx'; import { VlanDialog, getGhostSettings as getVlanGhostSettings } from './vlan.jsx'; +import { WireGuardDialog, getWireGuardGhostSettings } from './wireguard.jsx'; import { MtuDialog } from './mtu.jsx'; import { MacDialog } from './mac.jsx'; import { ModalError } from 'cockpit-components-inline-notification.jsx'; import { ModelContext } from './model-context.jsx'; import { useDialogs } from "dialogs.jsx"; +import { install_dialog } from "cockpit-components-install-dialog.jsx"; +import { read_os_release } from "os-release.js"; import { apply_group_member, @@ -141,7 +144,7 @@ export const Name = ({ idPrefix, iface, setIface }) => { ); }; -export const NetworkModal = ({ dialogError, help, idPrefix, title, onSubmit, children, isFormHorizontal }) => { +export const NetworkModal = ({ dialogError, help, idPrefix, title, onSubmit, children, isFormHorizontal, submitDisabled = false }) => { const Dialogs = useDialogs(); return ( @@ -152,7 +155,7 @@ export const NetworkModal = ({ dialogError, help, idPrefix, title, onSubmit, chi title={title} footer={ <> - + + + + {publicKey} + + + { setListenPort(val) }} /> + + + { setAddresses(val) }} placeholder={_("E.g. 10.0.0.1/24")} /> + + setPeers(peers => [...peers, { publicKey: '', endpoint: '', allowedIps: '' }])} + > + {_("Add peer")} + + } + /> + } + className='dynamic-form-group' + > + {(peers.length !== 0) + ? peers.map((peer, i) => ( + + + { + setPeers(peers => peers.map((peer, index) => i === index ? { ...peer, publicKey: val } : peer)); + }} + id={idPrefix + '-publickey-peer-' + i} + /> + + + { + setPeers(peers => peers.map((peer, index) => i === index ? { ...peer, endpoint: val } : peer)); + }} + id={idPrefix + '-endpoint-peer-' + i} + /> + + + { + setPeers(peers => peers.map((peer, index) => i === index ? { ...peer, allowedIps: val } : peer)); + }} + id={idPrefix + '-allowedips-peer-' + i} + /> + + + + + + )) + : + {_("No peers added.")} + + } + + + ); +} + +export function getWireGuardGhostSettings({ newIfaceName }) { + return { + connection: { + id: `con-${newIfaceName}`, + interface_name: newIfaceName + }, + wireguard: { + listen_port: "", + private_key: "", + peers: [] + }, + ipv4: { + addresses: [] + } + }; +} diff --git a/pkg/networkmanager/wireguard.scss b/pkg/networkmanager/wireguard.scss new file mode 100644 index 000000000000..06071ee48ff8 --- /dev/null +++ b/pkg/networkmanager/wireguard.scss @@ -0,0 +1,28 @@ +.dynamic-form-group { + .pf-v5-c-empty-state { + padding: 0; + } + + .pf-v5-c-form__field-group-body { + .pf-v5-c-form__group { + display: block; + } + + .remove-button-group { + // Move 'Remove' button the the end of the row + grid-column: -1; + // Move 'Remove' button to the bottom of the line so as to align with the other form fields + display: flex; + align-items: flex-end; + } + } + + // We use FormFieldGroup PF component for the nested look and for ability to add buttons to the header + // However we want to save space and not add indent to the left so we need to override it + .pf-v5-c-form__field-group-body { + // Stretch content fully + --pf-v5-c-form__field-group-body--GridColumn: 1 / -1; + // Reduce padding at the top + --pf-v5-c-form__field-group-body--PaddingTop: var(--pf-v5-global--spacer--xs); + } +} diff --git a/test/run b/test/run index f6871c919caf..94712145899d 100755 --- a/test/run +++ b/test/run @@ -12,7 +12,7 @@ PREPARE_OPTS="" RUN_OPTS="" ALL_TESTS="$(test/common/run-tests --test-dir test/verify -l)" -RE_NETWORKING='Networking|Bonding|TestBridge|Firewall|Team|IPA|AD' +RE_NETWORKING='Networking|Bonding|TestBridge|Firewall|Team|IPA|AD|WireGuard' RE_STORAGE='Storage' RE_EXPENSIVE='HostSwitching|MultiMachine|Updates|Superuser|Kdump|Pages' diff --git a/test/verify/check-networkmanager-wireguard b/test/verify/check-networkmanager-wireguard new file mode 100755 index 000000000000..a61f61867831 --- /dev/null +++ b/test/verify/check-networkmanager-wireguard @@ -0,0 +1,58 @@ +#!/usr/bin/python3 -cimport os, sys; os.execv(os.path.dirname(sys.argv[1]) + "/../common/pywrap", sys.argv) + +import testlib + + +class TestWireGuard(testlib.MachineCase): + provision = { + "machine1": {"address": "192.168.100.11/24", "restrict": False}, + "machine2": {"address": "192.168.100.12/24", "restrict": False}, + } + + def testVPN(self): + m1 = self.machines["machine1"] + m2 = self.machines["machine2"] + b = self.browser + + self.login_and_go("/network") + + + # Peer 2 (server) + if not m2.ostree_image: + m2.execute("systemctl stop firewalld") # TODO: Fix it + m2.execute("wg genkey > private") + m2_port = 51820 + m2_pubkey = m2.execute("wg pubkey < private").strip() + + m2.execute("ip link add dev wg0 type wireguard") + m2.execute("ip addr add 10.0.0.2/24 dev wg0") + m2.execute("wg set wg0 private-key ./private") + m2.execute(f"wg set wg0 listen-port {m2_port}") + m2.execute("ip link set wg0 up") + + # Peer 1 (client) + b.click("button:contains('Add WireGuard')") + b.wait_visible("#network-wireguard-settings-dialog") + b.click("button:contains('Generate private key')") + b.wait_not_val("#network-wireguard-settings-dialog .pf-v5-c-clipboard-copy input", "") + m1_pubkey = b.val("#network-wireguard-settings-dialog .pf-v5-c-clipboard-copy input") + b.set_input_text("#network-wireguard-settings-listen-port-input", "51820") + b.set_input_text("#network-wireguard-settings-addresses-input", "10.0.0.1/24") + b.click("button:contains('Add peer')") + b.set_input_text("#network-wireguard-settings-publickey-peer-0", m2_pubkey) + b.set_input_text("#network-wireguard-settings-endpoint-peer-0", f"192.168.100.12:{m2_port}") + b.set_input_text("#network-wireguard-settings-allowedips-peer-0", "10.0.0.2") + b.click("button:contains('Save')") + + m2.execute(f"wg set wg0 peer {m1_pubkey} allowed-ips 10.0.0.1/32") # endpoint and port is not necessary for a peer if that peer estalishes the connectio first (i.e. the client) + + try: + m1.execute("ping -c 5 10.0.0.2") + except: + m1.execute("ip a >&2; ip route >&2; nmcli c >&2; wg >&2") + m2.execute("ip a >&2; ip route >&2; nmcli c >&2; wg >&2") + raise + + +if __name__ == "__main__": + testlib.test_main()