feat(wireguard): generate psks only if needed; add most of the qr code generator

This commit is contained in:
oddlama 2023-04-15 01:51:33 +02:00
parent 925d3856e0
commit d5f2880457
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
13 changed files with 225 additions and 108 deletions

View file

@ -52,6 +52,8 @@
... ...
} @ inputs: } @ inputs:
{ {
extraLib = import ./nix/lib.nix inputs;
# The identities that are used to rekey agenix secrets and to # The identities that are used to rekey agenix secrets and to
# decrypt all repository-wide secrets. # decrypt all repository-wide secrets.
secrets = { secrets = {

View file

@ -21,5 +21,8 @@
}; };
}; };
extra.wireguard.vms.address = ["10.0.0.10/32"]; extra.wireguard.vms = {
via = "ward";
addresses = ["10.0.0.10/32"];
};
} }

View file

@ -27,12 +27,12 @@
enable = true; enable = true;
port = 51822; port = 51822;
openFirewall = true; openFirewall = true;
externalPeers = {
test1 = ["10.0.0.91/32"];
test2 = ["10.0.0.92/32"];
test3 = ["10.0.0.93/32"];
};
}; };
address = ["10.0.0.1/24"]; addresses = ["10.0.0.1/24"];
externalPeers = {
test1 = ["10.0.0.91/32"];
test2 = ["10.0.0.92/32"];
test3 = ["10.0.0.93/32"];
};
}; };
} }

View file

@ -23,10 +23,10 @@
enable = true; enable = true;
port = 51822; port = 51822;
openFirewall = true; openFirewall = true;
externalPeers = {
zack1 = ["10.0.0.90/32"];
};
}; };
address = ["10.0.0.2/24"]; addresses = ["10.0.0.2/24"];
externalPeers = {
zack1 = ["10.0.0.90/32"];
};
}; };
} }

View file

@ -11,9 +11,11 @@
(lib) (lib)
any any
attrNames attrNames
attrValues
concatMap concatMap
concatMapStrings concatMapStrings
concatStringsSep concatStringsSep
filter
filterAttrs filterAttrs
head head
mapAttrsToList mapAttrsToList
@ -23,6 +25,7 @@
mkOption mkOption
mkEnableOption mkEnableOption
optionalAttrs optionalAttrs
optionals
splitString splitString
types types
; ;
@ -35,10 +38,12 @@
cfg = config.extra.wireguard; cfg = config.extra.wireguard;
configForNetwork = wgName: wg: let configForNetwork = wgName: wgCfg: let
inherit inherit
(extraLib.wireguard wgName nodes) (extraLib.wireguard wgName)
allPeers associatedServerNodes
associatedClientNodes
externalPeerName
peerPresharedKeyPath peerPresharedKeyPath
peerPresharedKeySecret peerPresharedKeySecret
peerPrivateKeyPath peerPrivateKeyPath
@ -46,17 +51,32 @@
peerPublicKeyPath peerPublicKeyPath
; ;
otherPeers = filterAttrs (n: _: n != nodeName) allPeers; filterSelf = filter (x: x != nodeName);
wgCfgOf = node: nodes.${node}.config.extra.wireguard.${wgName};
ourClientNodes =
optionals wgCfg.server.enable
(filter (n: (wgCfgOf n).via == nodeName) associatedClientNodes);
# The list of peers that we have to know the psk to.
neededPeers =
if wgCfg.server.enable
then
filterSelf associatedServerNodes
++ map externalPeerName (attrNames wgCfg.server.externalPeers)
++ ourClientNodes
else [wgCfg.via];
in { in {
secrets = secrets =
concatAttrs (map (other: { concatAttrs (map (other: {
${peerPresharedKeySecret nodeName other}.file = peerPresharedKeyPath nodeName other; ${peerPresharedKeySecret nodeName other}.file = peerPresharedKeyPath nodeName other;
}) (attrNames otherPeers)) })
neededPeers)
// { // {
${peerPrivateKeySecret nodeName}.file = peerPrivateKeyPath nodeName; ${peerPrivateKeySecret nodeName}.file = peerPrivateKeyPath nodeName;
}; };
netdevs."${wg.priority}-${wgName}" = { netdevs."${wgCfg.priority}-${wgName}" = {
netdevConfig = { netdevConfig = {
Kind = "wireguard"; Kind = "wireguard";
Name = "${wgName}"; Name = "${wgName}";
@ -66,27 +86,64 @@
{ {
PrivateKeyFile = config.rekey.secrets.${peerPrivateKeySecret nodeName}.path; PrivateKeyFile = config.rekey.secrets.${peerPrivateKeySecret nodeName}.path;
} }
// optionalAttrs wg.server.enable { // optionalAttrs wgCfg.server.enable {
ListenPort = wg.server.port; ListenPort = wgCfg.server.port;
}; };
wireguardPeers = wireguardPeers =
mapAttrsToList (peerName: peerAllowedIPs: { if wgCfg.server.enable
wireguardPeerConfig = then
{ # Always include all other server nodes.
map (serverNode: {
wireguardPeerConfig = {
PublicKey = builtins.readFile (peerPublicKeyPath serverNode);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName serverNode}.path;
# The allowed ips of a server node are it's own addreses,
# plus each external peer's addresses,
# plus each client's addresses that is connected via this node.
AllowedIPs =
(wgCfgOf serverNode).addresses
++ attrValues (wgCfgOf serverNode).server.externalPeers
++ map (n: (wgCfgOf n).addresses) ourClientNodes;
};
}) (filterSelf associatedServerNodes)
# All our external peers
++ mapAttrsToList (extPeer: allowedIPs: let
peerName = externalPeerName extPeer;
in {
wireguardPeerConfig = {
PublicKey = builtins.readFile (peerPublicKeyPath peerName); PublicKey = builtins.readFile (peerPublicKeyPath peerName);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName peerName}.path; PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName peerName}.path;
AllowedIPs = peerAllowedIPs; AllowedIPs = allowedIPs;
}
// optionalAttrs wg.server.enable {
PersistentKeepalive = 25; PersistentKeepalive = 25;
}; };
}) })
otherPeers; wgCfg.server.externalPeers
# All client nodes that have their via set to us.
++ mapAttrsToList (clientNode: {
wireguardPeerConfig = {
PublicKey = builtins.readFile (peerPublicKeyPath clientNode);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName clientNode}.path;
AllowedIPs = (wgCfgOf clientNode).addresses;
PersistentKeepalive = 25;
};
})
ourClientNodes
else
# We are a client node, so only include our via server.
[
{
wireguardPeerConfig = {
PublicKey = builtins.readFile (peerPublicKeyPath wgCfg.via);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName wgCfg.via}.path;
AllowedIPs = (wgCfgOf wgCfg.via).addresses;
};
}
];
}; };
networks."${wg.priority}-${wgName}" = { networks."${wgCfg.priority}-${wgName}" = {
matchConfig.Name = wgName; matchConfig.Name = wgName;
networkConfig.Address = wg.address; networkConfig.Address = wgCfg.addresses;
}; };
}; };
in { in {
@ -109,6 +166,20 @@ in {
type = types.bool; type = types.bool;
description = mdDoc "Whether to open the firewall for the specified `listenPort`, if {option}`listen` is `true`."; description = mdDoc "Whether to open the firewall for the specified `listenPort`, if {option}`listen` is `true`.";
}; };
externalPeers = mkOption {
type = types.attrsOf (types.listOf types.str);
default = {};
example = {my-android-phone = ["10.0.0.97/32"];};
description = mdDoc ''
Allows defining an extra set of peers that should be added to this wireguard network,
but will not be managed by this flake. (e.g. phones)
These external peers will only know this node as a peer, which will forward
their traffic to other members of the network if required. This requires
this node to act as a server.
'';
};
}; };
priority = mkOption { priority = mkOption {
@ -117,27 +188,22 @@ in {
description = mdDoc "The order priority used when creating systemd netdev and network files."; description = mdDoc "The order priority used when creating systemd netdev and network files.";
}; };
address = mkOption { via = mkOption {
default = null;
type = types.uniq (types.nullOr types.str);
description = mdDoc ''
The server node via which to connect to the network.
This must defined if and only if this node is not a server.
'';
};
addresses = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
description = mdDoc '' description = mdDoc ''
The addresses to configure for this interface. Will automatically be added The addresses to configure for this interface. Will automatically be added
as this peer's allowed addresses to all other peers. as this peer's allowed addresses to all other peers.
''; '';
}; };
externalPeers = mkOption {
type = types.attrsOf (types.listOf types.str);
default = {};
example = {my-android-phone = ["10.0.0.97/32"];};
description = mdDoc ''
Allows defining an extra set of peers that should be added to this wireguard network,
but will not be managed by this flake. (e.g. phones)
These external peers will only know this node as a peer, which will forward
their traffic to other members of the network if required. This requires
this node to act as a server.
'';
};
}; };
}); });
}; };
@ -148,12 +214,14 @@ in {
in { in {
assertions = concatMap (wgName: let assertions = concatMap (wgName: let
inherit inherit
(extraLib.wireguard wgName nodes) (extraLib.wireguard wgName)
externalPeerNamesRaw externalPeerNamesRaw
usedAddresses usedAddresses
associatedNodes associatedNodes
; ;
wgCfg = cfg.${wgName};
wgCfgOf = node: nodes.${node}.config.extra.wireguard.${wgName};
duplicatePeers = duplicates externalPeerNamesRaw; duplicatePeers = duplicates externalPeerNamesRaw;
duplicateAddrs = duplicates (map (x: head (splitString "/" x)) usedAddresses); duplicateAddrs = duplicates (map (x: head (splitString "/" x)) usedAddresses);
in [ in [
@ -169,9 +237,19 @@ in {
assertion = duplicateAddrs == []; assertion = duplicateAddrs == [];
message = "Wireguard network '${wgName}': Addresses used multiple times: ${concatStringsSep ", " duplicateAddrs}"; message = "Wireguard network '${wgName}': Addresses used multiple times: ${concatStringsSep ", " duplicateAddrs}";
} }
# TODO externalPeers != [] -> server.listen {
# TODO externalPeers != [] -> ip forwarding assertion = wgCfg.server.externalPeers != {} -> wgCfg.server.enable;
# TODO psks only between all nodes and each node-externalpeer pair message = "Wireguard network '${wgName}': Defining external peers requires server.enable = true.";
}
{
assertion = wgCfg.server.enable == (wgCfg.via == null);
message = "Wireguard network '${wgName}': A via server must be defined exactly iff this isn't a server node.";
}
{
assertion = wgCfg.via != null -> (wgCfgOf wgCfg.via).server.enable;
message = "Wireguard network '${wgName}': The specified via node '${wgCfg.via}' must be a wireguard server.";
}
# TODO externalPeers != {} -> ip forwarding
# TODO no overlapping allowed ip range? 0.0.0.0 would be ok to overlap though # TODO no overlapping allowed ip range? 0.0.0.0 would be ok to overlap though
]) (attrNames cfg); ]) (attrNames cfg);

View file

@ -1,36 +1,22 @@
{ {
self, self,
pkgs, pkgs,
nixpkgs,
... ...
}: let }: let
inherit inherit (nixpkgs.lib) concatStringsSep;
(pkgs.lib) inherit (extraLib) rageEncryptArgs;
concatMapStrings
concatStringsSep
escapeShellArg
substring
;
isAbsolutePath = x: substring 0 1 x == "/";
masterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities;
extraEncryptionPubkeys =
concatMapStrings (
x:
if isAbsolutePath x
then ''-R ${escapeShellArg x} ''
else ''-r ${escapeShellArg x} ''
)
self.secrets.extraEncryptionPubkeys;
in in
pkgs.writeShellScript "format-secrets" '' pkgs.writeShellScript "format-secrets" ''
set -euo pipefail set -euo pipefail
[[ -d .git ]] && [[ -f flake.nix ]] || { echo "error: Please execute this from the project's root folder (the folder with flake.nix)" >&2; exit 1; } [[ -d .git ]] && [[ -f flake.nix ]] || { echo "error: Please execute this from the project's root folder (the folder with flake.nix)" >&2; exit 1; }
for f in $(find . -type f -name '*.nix.age'); do for f in $(find . -type f -name '*.nix.age'); do
echo "Formatting $f ..." echo "Formatting $f ..."
decrypted=$(${../rage-decrypt.sh} --print-out-path "$f" ${concatStringsSep " " self.secrets.masterIdentities}) \ decrypted=$(${../rage-decrypt-and-cache.sh} --print-out-path "$f" ${concatStringsSep " " self.secrets.masterIdentities}) \
|| { echo "error: Failed to decrypt!" >&2; exit 1; } || { echo "error: Failed to decrypt!" >&2; exit 1; }
formatted=$(${pkgs.alejandra}/bin/alejandra --quiet < "$decrypted") \ formatted=$(${pkgs.alejandra}/bin/alejandra --quiet < "$decrypted") \
|| { echo "error: Failed to format $decrypted!" >&2; exit 1; } || { echo "error: Failed to format $decrypted!" >&2; exit 1; }
${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$formatted" > "$f" \ ${pkgs.rage}/bin/rage -e ${rageEncryptArgs} <<< "$formatted" > "$f" \
|| { echo "error: Failed to re-encrypt!" >&2; exit 1; } || { echo "error: Failed to re-encrypt!" >&2; exit 1; }
done done
'' ''

View file

@ -17,24 +17,14 @@
unique unique
; ;
extraLib = import ../lib.nix inputs; inherit (self.extraLib) rageEncryptArgs;
isAbsolutePath = x: substring 0 1 x == "/";
masterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities;
extraEncryptionPubkeys =
concatMapStrings (
x:
if isAbsolutePath x
then ''-R ${escapeShellArg x} ''
else ''-r ${escapeShellArg x} ''
)
self.secrets.extraEncryptionPubkeys;
nodeNames = attrNames self.nodes; nodeNames = attrNames self.nodes;
wireguardNetworks = unique (concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard) nodeNames); wireguardNetworks = unique (concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard) nodeNames);
generateNetworkKeys = wgName: let generateNetworkKeys = wgName: let
inherit inherit
(extraLib.wireguard wgName self.nodes) (self.extraLib.wireguard wgName)
allPeers allPeers
associatedNodes associatedNodes
associatedServerNodes associatedServerNodes
@ -57,7 +47,7 @@
echo "Generating "${keyBasename}".{age,pub}" echo "Generating "${keyBasename}".{age,pub}"
privkey=$(${pkgs.wireguard-tools}/bin/wg genkey) privkey=$(${pkgs.wireguard-tools}/bin/wg genkey)
echo "$privkey" | ${pkgs.wireguard-tools}/bin/wg pubkey > ${pubkeyFile} echo "$privkey" | ${pkgs.wireguard-tools}/bin/wg pubkey > ${pubkeyFile}
${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$privkey" > ${privkeyFile} \ ${pkgs.rage}/bin/rage -e ${rageEncryptArgs} <<< "$privkey" > ${privkeyFile} \
|| { echo "error: Failed to encrypt wireguard private key for peer ${peerName} on network ${wgName}!" >&2; exit 1; } || { echo "error: Failed to encrypt wireguard private key for peer ${peerName} on network ${wgName}!" >&2; exit 1; }
fi fi
''; '';
@ -73,7 +63,7 @@
mkdir -p $(dirname ${pskFile}) mkdir -p $(dirname ${pskFile})
echo "Generating "${pskFile}"" echo "Generating "${pskFile}""
psk=$(${pkgs.wireguard-tools}/bin/wg genpsk) psk=$(${pkgs.wireguard-tools}/bin/wg genpsk)
${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$psk" > ${pskFile} \ ${pkgs.rage}/bin/rage -e ${rageEncryptArgs} <<< "$psk" > ${pskFile} \
|| { echo "error: Failed to encrypt wireguard psk for peers ${peer1} and ${peer2} on network ${wgName}!" >&2; exit 1; } || { echo "error: Failed to encrypt wireguard psk for peers ${peer1} and ${peer2} on network ${wgName}!" >&2; exit 1; }
fi fi
''; '';

View file

@ -9,22 +9,57 @@
concatMap concatMap
concatStringsSep concatStringsSep
escapeShellArg escapeShellArg
filter
unique unique
; ;
extraLib = import ../lib.nix inputs; inherit (self.extraLib) rageDecryptArgs;
nodeNames = attrNames self.nodes; nodeNames = attrNames self.nodes;
wireguardNetworks = unique (concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard) nodeNames); wireguardNetworks = unique (concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard) nodeNames);
externalPeersForNet = wgName: externalPeersForNet = wgName:
map (peer: {inherit wgName peer;}) concatMap (serverNode:
(attrNames (extraLib.wireguard wgName self.nodes).allExternalPeers); map
(peer: {inherit wgName serverNode peer;})
(attrNames self.nodes.${serverNode}.config.extra.wireguard.${wgName}.server.externalPeers))
(self.extraLib.wireguard wgName).associatedServerNodes;
allExternalPeers = concatMap externalPeersForNet wireguardNetworks; allExternalPeers = concatMap externalPeersForNet wireguardNetworks;
in in
# TODO generate "classic" config and run qrencode
pkgs.writeShellScript "show-wireguard-qr" '' pkgs.writeShellScript "show-wireguard-qr" ''
set -euo pipefail set -euo pipefail
echo ${escapeShellArg (concatStringsSep "\n" (map (x: "${x.wgName}.${x.peer}") allExternalPeers))} | ${pkgs.fzf}/bin/fzf json_sel=$(echo ${escapeShellArg (concatStringsSep "\n" (map (x: "${builtins.toJSON x}\t${x.wgName}.${x.serverNode}.${x.peer}") allExternalPeers))} \
| ${pkgs.fzf}/bin/fzf --delimiter='\t' --ansi --multi --query="''${1-}" --tiebreak=end --bind=tab:down,btab:up,change:top,ctrl-space:toggle --with-nth=2.. --height='~50%' --tac \
| ${pkgs.coreutils}/bin/cut -d$'\t' -f1)
[[ -n "$json_sel" ]] || exit 1
# TODO for each output line
# TODO maybe just call a json -> make script that gives wireguard config to make this easier
wgName=$(${pkgs.jq}/bin/jq -r .wgName <<< "$json_sel")
serverNode=$(${pkgs.jq}/bin/jq -r .serverNode <<< "$json_sel")
peer=$(${pkgs.jq}/bin/jq -r .peer <<< "$json_sel")
serverPubkey=$(nix eval --raw ".#extraLib" \
--apply 'extraLib: builtins.readFile ((extraLib.wireguard "'"$wgName"'").peerPublicKeyPath "'"$serverNode"'")')
privKeyPath=$(nix eval --raw ".#extraLib" \
--apply 'extraLib: (extraLib.wireguard "'"$wgName"'").peerPrivateKeyPath "'"$peer"'"')
serverPskPath=$(nix eval --raw ".#extraLib" \
--apply 'extraLib: (extraLib.wireguard "'"$wgName"'").peerPresharedKeyPath "'"$serverNode"'" "'"$peer"'"')
privKey=$(${pkgs.rage}/bin/rage -d ${rageDecryptArgs} "$privKeyPath") \
|| { echo "error: Failed to decrypt!" >&2; exit 1; }
serverPsk=$(${pkgs.rage}/bin/rage -d ${rageDecryptArgs} "$serverPskPath") \
|| { echo "error: Failed to decrypt!" >&2; exit 1; }
cat <<EOF | tee /dev/tty | ${pkgs.qrencode}/bin/qrencode -t ansiutf8
[Interface]
Address =
PrivateKey = $privKey
[Peer]
PublicKey = $serverPubkey
PresharedKey = $serverPsk
AllowedIPs =
Endpoint =
EOF
'' ''

View file

@ -28,5 +28,5 @@ in {
rageImportEncrypted = identities: nixFile: rageImportEncrypted = identities: nixFile:
assert assertMsg (builtins.isPath nixFile) "The file to decrypt must be given as a path to prevent impurity."; assert assertMsg (builtins.isPath nixFile) "The file to decrypt must be given as a path to prevent impurity.";
assert assertMsg (hasSuffix ".nix.age" nixFile) "The content of the decrypted file must be a nix expression and should therefore end in .nix.age"; assert assertMsg (hasSuffix ".nix.age" nixFile) "The content of the decrypted file must be a nix expression and should therefore end in .nix.age";
exec ([./rage-decrypt.sh nixFile] ++ identities); exec ([./rage-decrypt-and-cache.sh nixFile] ++ identities);
} }

View file

@ -10,19 +10,14 @@
agenix-rekey, agenix-rekey,
... ...
} @ inputs: let } @ inputs: let
inherit inherit (nixpkgs.lib) optionals;
(nixpkgs.lib)
optionals
;
extraLib = import ./lib.nix inputs;
in in
nodeName: nodeMeta: { nodeName: nodeMeta: {
inherit (nodeMeta) system; inherit (nodeMeta) system;
pkgs = self.pkgs.${nodeMeta.system}; pkgs = self.pkgs.${nodeMeta.system};
specialArgs = { specialArgs = {
inherit (nixpkgs) lib; inherit (nixpkgs) lib;
inherit extraLib; inherit (self) extraLib;
inherit inputs; inherit inputs;
inherit nodeName; inherit nodeName;
inherit nodeMeta; inherit nodeMeta;

View file

@ -1,9 +1,15 @@
{nixpkgs, ...}: let {
self,
nixpkgs,
...
}: let
inherit inherit
(nixpkgs.lib) (nixpkgs.lib)
attrNames attrNames
attrValues attrValues
concatMap concatMap
concatMapStrings
escapeShellArg
filter filter
flatten flatten
foldl' foldl'
@ -12,6 +18,7 @@
mergeAttrs mergeAttrs
nameValuePair nameValuePair
partition partition
substring
unique unique
; ;
in rec { in rec {
@ -33,8 +40,24 @@ in rec {
# Concatenates all given attrsets as if calling a // b in order. # Concatenates all given attrsets as if calling a // b in order.
concatAttrs = foldl' mergeAttrs {}; concatAttrs = foldl' mergeAttrs {};
# True if the path or string starts with /
isAbsolutePath = x: substring 0 1 x == "/";
rageMasterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities;
rageExtraEncryptionPubkeys =
concatMapStrings (
x:
if isAbsolutePath x
then ''-R ${escapeShellArg x} ''
else ''-r ${escapeShellArg x} ''
)
self.secrets.extraEncryptionPubkeys;
# The arguments required to de-/encrypt a secret in this repository
rageDecryptArgs = "${rageMasterIdentityArgs}";
rageEncryptArgs = "${rageMasterIdentityArgs} ${rageExtraEncryptionPubkeys}";
# Wireguard related functions that are reused in several files of this flake # Wireguard related functions that are reused in several files of this flake
wireguard = wgName: nodes: rec { wireguard = wgName: rec {
sortedPeers = peerA: peerB: sortedPeers = peerA: peerB:
if peerA < peerB if peerA < peerB
then { then {
@ -64,25 +87,27 @@ in rec {
# All nodes that are part of this network # All nodes that are part of this network
associatedNodes = associatedNodes =
filter filter
(n: builtins.hasAttr wgName nodes.${n}.config.extra.wireguard) (n: builtins.hasAttr wgName self.nodes.${n}.config.extra.wireguard)
(attrNames nodes); (attrNames self.nodes);
# Partition nodes by whether they are servers # Partition nodes by whether they are servers
_associatedNodes_isServerPartition = _associatedNodes_isServerPartition =
partition partition
(n: nodes.${n}.config.extra.wireguard.${wgName}.server.enable) (n: self.nodes.${n}.config.extra.wireguard.${wgName}.server.enable)
associatedNodes; associatedNodes;
associatedServerNodes = _associatedNodes_isServerPartition.right; associatedServerNodes = _associatedNodes_isServerPartition.right;
associatedClientNodes = _associatedNodes_isServerPartition.wrong; associatedClientNodes = _associatedNodes_isServerPartition.wrong;
# Maps all nodes that are part of this network to their addresses # Maps all nodes that are part of this network to their addresses
nodePeers = genAttrs associatedNodes (n: nodes.${n}.config.extra.wireguard.${wgName}.address); nodePeers = genAttrs associatedNodes (n: self.nodes.${n}.config.extra.wireguard.${wgName}.addresses);
externalPeerName = p: "external-${p}";
# Only peers that are defined as externalPeers on the given node. # Only peers that are defined as externalPeers on the given node.
# Prepends "external-" to their name. # Prepends "external-" to their name.
externalPeersForNode = node: externalPeersForNode = node:
mapAttrs' (p: nameValuePair "external-${p}") nodes.${node}.config.extra.wireguard.${wgName}.externalPeers; mapAttrs' (p: nameValuePair (externalPeerName p)) self.nodes.${node}.config.extra.wireguard.${wgName}.server.externalPeers;
# All peers that are defined as externalPeers on any node. # All peers that are defined as externalPeers on any node.
# Prepends "external-" to their name. # Prepends "external-" to their name.
@ -92,11 +117,11 @@ in rec {
allPeers = nodePeers // allExternalPeers; allPeers = nodePeers // allExternalPeers;
# Concatenation of all external peer names names without any transformations. # Concatenation of all external peer names names without any transformations.
externalPeerNamesRaw = concatMap (n: attrNames nodes.${n}.config.extra.wireguard.${wgName}.externalPeers) associatedNodes; externalPeerNamesRaw = concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard.${wgName}.server.externalPeers) associatedNodes;
# A list of all occurring addresses. # A list of all occurring addresses.
usedAddresses = usedAddresses =
concatMap (n: nodes.${n}.config.extra.wireguard.${wgName}.address) associatedNodes concatMap (n: self.nodes.${n}.config.extra.wireguard.${wgName}.addresses) associatedNodes
++ flatten (concatMap (n: attrValues nodes.${n}.config.extra.wireguard.${wgName}.externalPeers) associatedNodes); ++ flatten (concatMap (n: attrValues self.nodes.${n}.config.extra.wireguard.${wgName}.server.externalPeers) associatedNodes);
}; };
} }

View file

@ -15,8 +15,11 @@
self, self,
nixpkgs, nixpkgs,
... ...
} @ inputs: } @ inputs: let
with nixpkgs.lib; let inherit
(nixpkgs.lib)
mapAttrs
;
# If the given expression is a bare set, it will be wrapped in a function, # If the given expression is a bare set, it will be wrapped in a function,
# so that the imported file can always be applied to the inputs, similar to # so that the imported file can always be applied to the inputs, similar to
# how modules can be functions or sets. # how modules can be functions or sets.