Skip to content

Commit a6e54f5

Browse files
nixos/networkd: support systemd-creds in WireGuard (#346964)
2 parents 18d7505 + 68483a7 commit a6e54f5

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

nixos/lib/systemd-lib.nix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ let
1717
filterAttrs
1818
flatten
1919
flip
20+
hasPrefix
2021
head
2122
isInt
2223
isFloat
@@ -196,6 +197,10 @@ in rec {
196197
optional (attr ? ${name})
197198
"Systemd ${group} field `${name}' has been removed. See ${see}";
198199

200+
assertKeyIsSystemdCredential = name: group: attr:
201+
optional (attr ? ${name} && !(hasPrefix "@" attr.${name}))
202+
"Systemd ${group} field `${name}' is not a systemd credential";
203+
199204
checkUnitConfig = group: checks: attrs: let
200205
# We're applied at the top-level type (attrsOf unitOption), so the actual
201206
# unit options might contain attributes from mkOverride and mkIf that we need to

nixos/modules/system/boot/networkd.nix

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,11 +411,14 @@ let
411411
(assertValueOneOf "Layer2SpecificHeader" [ "none" "default" ])
412412
];
413413

414-
# NOTE The PrivateKey directive is missing on purpose here, please
415-
# do not add it to this list. The nix store is world-readable let's
416-
# refrain ourselves from providing a footgun.
414+
# NOTE Check whether the key starts with an @, in which case it is
415+
# interpreted as the name of the credential from which the actual key
416+
# shall be read by systemd-creds.
417+
# Do not remove this check as the nix store is world-readable.
417418
sectionWireGuard = checkUnitConfig "WireGuard" [
419+
(assertKeyIsSystemdCredential "PrivateKey")
418420
(assertOnlyFields [
421+
"PrivateKey"
419422
"PrivateKeyFile"
420423
"ListenPort"
421424
"FirewallMark"
@@ -426,12 +429,15 @@ let
426429
(assertRange "FirewallMark" 1 4294967295)
427430
];
428431

429-
# NOTE The PresharedKey directive is missing on purpose here, please
430-
# do not add it to this list. The nix store is world-readable,let's
431-
# refrain ourselves from providing a footgun.
432+
# NOTE Check whether the key starts with an @, in which case it is
433+
# interpreted as the name of the credential from which the actual key
434+
# shall be read by systemd-creds.
435+
# Do not remove this check as the nix store is world-readable.
432436
sectionWireGuardPeer = checkUnitConfigWithLegacyKey "wireguardPeerConfig" "WireGuardPeer" [
437+
(assertKeyIsSystemdCredential "PresharedKey")
433438
(assertOnlyFields [
434439
"PublicKey"
440+
"PresharedKey"
435441
"PresharedKeyFile"
436442
"AllowedIPs"
437443
"Endpoint"

nixos/tests/systemd-networkd.nix

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
let generateNodeConf = { lib, pkgs, config, privk, pubk, peerId, nodeId, ...}: {
1+
let generateNodeConf = { lib, pkgs, config, privk, pubk, systemdCreds, peerId, nodeId, ...}: {
22
imports = [ common/user-account.nix ];
33
systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
44
networking.useNetworkd = true;
55
networking.useDHCP = false;
66
networking.firewall.enable = false;
77
virtualisation.vlans = [ 1 ];
88
environment.systemPackages = with pkgs; [ wireguard-tools ];
9+
environment.etc."credstore/network.wireguard.private" = lib.mkIf systemdCreds { text = privk; };
910
systemd.network = {
1011
enable = true;
1112
config = {
@@ -15,11 +16,14 @@ let generateNodeConf = { lib, pkgs, config, privk, pubk, peerId, nodeId, ...}: {
1516
"90-wg0" = {
1617
netdevConfig = { Kind = "wireguard"; Name = "wg0"; };
1718
wireguardConfig = {
19+
# Test storing wireguard private key using systemd credentials.
20+
PrivateKey = lib.mkIf systemdCreds "@network.wireguard.private";
21+
1822
# NOTE: we're storing the wireguard private key in the
1923
# store for this test. Do not do this in the real
2024
# world. Keep in mind the nix store is
2125
# world-readable.
22-
PrivateKeyFile = pkgs.writeText "wg0-priv" privk;
26+
PrivateKeyFile = lib.mkIf (!systemdCreds) (pkgs.writeText "wg0-priv" privk);
2327
ListenPort = 51820;
2428
FirewallMark = 42;
2529
};
@@ -74,6 +78,7 @@ in import ./make-test-python.nix ({pkgs, ... }: {
7478
let localConf = {
7579
privk = "GDiXWlMQKb379XthwX0haAbK6hTdjblllpjGX0heP00=";
7680
pubk = "iRxpqj42nnY0Qz8MAQbSm7bXxXP5hkPqWYIULmvW+EE=";
81+
systemdCreds = false;
7782
nodeId = "1";
7883
peerId = "2";
7984
};
@@ -83,6 +88,7 @@ in import ./make-test-python.nix ({pkgs, ... }: {
8388
let localConf = {
8489
privk = "eHxSI2jwX/P4AOI0r8YppPw0+4NZnjOxfbS5mt06K2k=";
8590
pubk = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
91+
systemdCreds = true;
8692
nodeId = "2";
8793
peerId = "1";
8894
};

0 commit comments

Comments
 (0)