Skip to content

Commit

Permalink
networking: Add support for WireGuard
Browse files Browse the repository at this point in the history
  • Loading branch information
subhoghoshX committed Sep 5, 2023
1 parent ff5be4c commit 3f01ea5
Show file tree
Hide file tree
Showing 8 changed files with 683 additions and 15 deletions.
53 changes: 41 additions & 12 deletions pkg/networkmanager/dialogs-common.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import React, { useContext, useEffect, useState } from 'react';
import cockpit from 'cockpit';
import * as packagekit from 'packagekit.js';

import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
import { Checkbox } from "@patternfly/react-core/dist/esm/components/Checkbox/index.js";
Expand All @@ -35,11 +36,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,
Expand Down Expand Up @@ -141,7 +145,7 @@ export const Name = ({ idPrefix, iface, setIface }) => {
);
};

export const NetworkModal = ({ dialogError, help, idPrefix, title, onSubmit, children, isFormHorizontal, isCreateDialog }) => {
export const NetworkModal = ({ dialogError, help, idPrefix, title, onSubmit, children, isFormHorizontal, isCreateDialog, submitDisabled = false }) => {
const Dialogs = useDialogs();

return (
Expand All @@ -152,7 +156,7 @@ export const NetworkModal = ({ dialogError, help, idPrefix, title, onSubmit, chi
title={title}
footer={
<>
<Button variant='primary' id={idPrefix + "-save"} onClick={onSubmit}>
<Button variant='primary' id={idPrefix + "-save"} onClick={onSubmit} isDisabled={submitDisabled}>
{isCreateDialog ? _("Add") : _("Save")}
</Button>
<Button variant='link' id={idPrefix + "-cancel"} onClick={Dialogs.close}>
Expand Down Expand Up @@ -198,10 +202,26 @@ export const NetworkAction = ({ buttonText, iface, connectionSettings, type }) =
if (type == 'vlan') settings = getVlanGhostSettings();
if (type == 'team') settings = getTeamGhostSettings({ newIfaceName });
if (type == 'bridge') settings = getBridgeGhostSettings({ newIfaceName });
if (type == 'wg') settings = getWireGuardGhostSettings({ newIfaceName });
}

const properties = { connection: con, dev, settings };

async function resolveDeps(type) {
if (type === 'wg') {
try {
await cockpit.script("command -v wg");
} catch {
const packagekitExits = await packagekit.detect();
const os_release = await read_os_release();

// RHEL/CentOS 8 does not have wireguard-tools
if (packagekitExits && os_release.PLATFORM_ID !== "platform:el8")
await install_dialog("wireguard-tools");
}
}
}

function show() {
let dlg = null;
if (type == 'bond')
Expand All @@ -212,6 +232,8 @@ export const NetworkAction = ({ buttonText, iface, connectionSettings, type }) =
dlg = <TeamDialog {...properties} />;
else if (type == 'bridge')
dlg = <BridgeDialog {...properties} />;
else if (type == 'wg')
dlg = <WireGuardDialog {...properties} />;
else if (type == 'mtu')
dlg = <MtuDialog {...properties} />;
else if (type == 'mac')
Expand All @@ -224,8 +246,11 @@ export const NetworkAction = ({ buttonText, iface, connectionSettings, type }) =
dlg = <IpSettingsDialog topic="ipv4" {...properties} />;
else if (type == 'ipv6')
dlg = <IpSettingsDialog topic="ipv6" {...properties} />;

if (dlg)
Dialogs.show(dlg);
resolveDeps(type).then(() => {
Dialogs.show(dlg);
}).catch(console.error); // not-covered: OS error
}

return (
Expand Down Expand Up @@ -289,14 +314,18 @@ export const dialogSave = ({ model, dev, connection, members, membersInit, setti
rollback_on_failure: type !== 'vlan' && membersChanged
});
} else {
with_checkpoint(
model,
modify,
{
fail_text: cockpit.format(_("Creating this $0 will break the connection to the server, and will make the administration UI unavailable."), type == 'vlan' ? 'VLAN' : type),
anyway_text: _("Create it"),
hack_does_add_or_remove: true,
rollback_on_failure: type != 'vlan',
});
try {
with_checkpoint(
model,
modify,
{
fail_text: cockpit.format(_("Creating this $0 will break the connection to the server, and will make the administration UI unavailable."), type == 'vlan' ? 'VLAN' : type),
anyway_text: _("Create it"),
hack_does_add_or_remove: true,
rollback_on_failure: type != 'vlan',
});
} catch (e) {
setDialogError(typeof e === 'string' ? e : e.message);
}
}
};
38 changes: 38 additions & 0 deletions pkg/networkmanager/interfaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,17 @@ export function NetworkManagerModel() {
};
}

if (settings.wireguard) {
result.wireguard = {
listen_port: get("wireguard", "listen-port", 0),
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
})),
};
}

return result;
}

Expand Down Expand Up @@ -699,6 +710,33 @@ export function NetworkManagerModel() {
} else
delete result["802-3-ethernet"];

if (settings.wireguard) {
set("wireguard", "private-key", "s", settings.wireguard.private_key);
set("wireguard", "listen-port", "u", settings.wireguard.listen_port);
set("wireguard", "peers", "aa{sv}", settings.wireguard.peers.map(peer => {
return {
"public-key": {
t: "s",
v: peer.publicKey
},
...peer.endpoint
? {
endpoint: {
t: "s",
v: peer.endpoint
}
}
: {},
"allowed-ips": {
t: "as",
v: peer.allowedIps
}
};
}));
} else {
delete result.wireguard;
}

return result;
}

Expand Down
19 changes: 17 additions & 2 deletions pkg/networkmanager/network-interface.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,19 @@ export const NetworkInterfacePage = ({
return renderSettingsRow(_("VLAN"), rows, configure);
}

function renderWireGuardSettingsRow() {
const rows = [];
const options = settings.wireguard;

if (!options) {
return null;
}

const configure = <NetworkAction type="wg" iface={iface} connectionSettings={settings} />;

return renderSettingsRow(_("WireGuard"), rows, configure);
}

return [
render_group(),
renderAutoconnectRow(),
Expand All @@ -571,7 +584,8 @@ export const NetworkInterfacePage = ({
renderBridgePortSettingsRow(),
renderBondSettingsRow(),
renderTeamSettingsRow(),
renderTeamPortSettingsRow()
renderTeamPortSettingsRow(),
renderWireGuardSettingsRow(),
];
}

Expand Down Expand Up @@ -681,7 +695,8 @@ export const NetworkInterfacePage = ({
const isDeletable = (iface && !dev) || (dev && (dev.DeviceType == 'bond' ||
dev.DeviceType == 'team' ||
dev.DeviceType == 'vlan' ||
dev.DeviceType == 'bridge'));
dev.DeviceType == 'bridge' ||
dev.DeviceType == 'wireguard'));

const settingsRows = renderConnectionSettingsRows(iface.MainConnection, connectionSettings)
.map((component, idx) => <React.Fragment key={idx}>{component}</React.Fragment>);
Expand Down
1 change: 1 addition & 0 deletions pkg/networkmanager/network-main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export const NetworkPage = ({ privileged, operationInProgress, usage_monitor, pl

const actions = privileged && (
<>
<NetworkAction buttonText={_("Add VPN")} type='wg' />
<NetworkAction buttonText={_("Add bond")} type='bond' />
<NetworkAction buttonText={_("Add team")} type='team' />
<NetworkAction buttonText={_("Add bridge")} type='bridge' />
Expand Down
Loading

0 comments on commit 3f01ea5

Please sign in to comment.