From 7c2ab92302f10e7664a4af70610d8ea4a1f3d1e1 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 20 Jan 2023 06:57:49 +0000 Subject: [PATCH] wg-home: derive wireguard key from ssh privkey --- hosts/common/secrets.nix | 3 -- hosts/modules/default.nix | 1 + hosts/modules/derived-secrets.nix | 47 +++++++++++++++++++++++++++++++ hosts/modules/hosts.nix | 2 +- hosts/modules/wg-home.nix | 16 +++++++++-- secrets/universal.yaml | 5 ++-- 6 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 hosts/modules/derived-secrets.nix diff --git a/hosts/common/secrets.nix b/hosts/common/secrets.nix index 57b6e70b..811e32bd 100644 --- a/hosts/common/secrets.nix +++ b/hosts/common/secrets.nix @@ -67,9 +67,6 @@ sops.secrets."wg_ovpnd_ukr_privkey" = { sopsFile = ../../secrets/universal.yaml; }; - sops.secrets."wg_home_privkey" = { - sopsFile = ../../secrets/universal.yaml; - }; sops.secrets."snippets" = { sopsFile = ../../secrets/universal/snippets.bin; diff --git a/hosts/modules/default.nix b/hosts/modules/default.nix index eb5508b4..3ea1b997 100644 --- a/hosts/modules/default.nix +++ b/hosts/modules/default.nix @@ -2,6 +2,7 @@ { imports = [ + ./derived-secrets.nix ./hardware ./hosts.nix ./roles diff --git a/hosts/modules/derived-secrets.nix b/hosts/modules/derived-secrets.nix new file mode 100644 index 00000000..ba53862d --- /dev/null +++ b/hosts/modules/derived-secrets.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: + +let + inherit (builtins) toString; + inherit (lib) mapAttrs mkOption types; + cfg = config.sane.derived-secrets; + secret = types.submodule { + options = { + len = mkOption { + type = types.int; + }; + encoding = mkOption { + type = types.enum [ "base64" ]; + }; + }; + }; +in +{ + options = { + sane.derived-secrets = mkOption { + type = types.attrsOf secret; + default = {}; + description = '' + fs path => secret options. + for each entry, we create an item at the given path whose value is deterministic, + but also pseudo-random and not predictable by anyone without root access to the machine. + as PRNG source we use the host ssh key, and derived secrets are salted based on the destination path. + ''; + }; + }; + + config = { + sane.fs = mapAttrs (path: c: { + generated.script.script = '' + echo "$1" | cat /dev/stdin /etc/ssh/host_keys/ssh_host_ed25519_key \ + | sha512sum \ + | cut -c 1-${toString (c.len * 2)} \ + | tr a-z A-Z \ + | basenc -d --base16 \ + | basenc --${c.encoding} \ + > "$1" + ''; + generated.script.scriptArgs = [ path ]; + generated.acl.mode = "0600"; + }) cfg; + }; +} diff --git a/hosts/modules/hosts.nix b/hosts/modules/hosts.nix index 2af1891d..c3a43a0a 100644 --- a/hosts/modules/hosts.nix +++ b/hosts/modules/hosts.nix @@ -52,7 +52,7 @@ in sane.hosts.by-name."lappy" = { ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu"; ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc"; - wg-home.pubkey = "pWtnKW7f7sNIZQ2M83uJ7cHg3IL1tebE3IoVkCgjkXM="; + wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk="; }; sane.hosts.by-name."moby" = { diff --git a/hosts/modules/wg-home.nix b/hosts/modules/wg-home.nix index d3d75478..88dfe2fc 100644 --- a/hosts/modules/wg-home.nix +++ b/hosts/modules/wg-home.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: let inherit (lib) mkIf mkMerge mkOption optionalAttrs types; @@ -17,6 +17,12 @@ in config = mkIf cfg.enable (mkMerge [ { + # generate a (deterministic) wireguard private key + sane.derived-secrets."/run/wg-home.priv" = { + len = 32; + encoding = "base64"; + }; + # wireguard VPN which allows everything on my domain to speak to each other even when # not behind a shared LAN. # this config defines both the endpoint (server) and client configs @@ -25,12 +31,17 @@ in networking.firewall.allowedUDPPorts = [ 51820 ]; networking.wireguard.interfaces.wg-home = { listenPort = 51820; + privateKeyFile = "/run/wg-home.priv"; + preSetup = + let + gen-key = config.sane.fs."/run/wg-home.priv".unit; + in + "${pkgs.systemd}/bin/systemctl start '${gen-key}'"; }; } { networking.wireguard.interfaces.wg-home = lib.mkIf (cfg.role == "client") { - privateKeyFile = config.sops.secrets.wg_home_privkey.path; # client IP (TODO: make host-specific) ips = [ "10.0.10.20/24" ]; @@ -54,7 +65,6 @@ in } { networking.wireguard.interfaces.wg-home = lib.mkIf (cfg.role == "server") { - privateKeyFile = config.sops.secrets.wg_home_server_privkey.path; ips = [ "10.0.10.5/24" ]; diff --git a/secrets/universal.yaml b/secrets/universal.yaml index 8fb1f7ff..be5aad79 100644 --- a/secrets/universal.yaml +++ b/secrets/universal.yaml @@ -9,7 +9,6 @@ wg_ovpnd_us_privkey: ENC[AES256_GCM,data:5YkQ4r7HNWiRr/5pa1XfexxtJAz6kDjX+hNiZch wg_ovpnd_us-atl_privkey: ENC[AES256_GCM,data:NMguzx35VvOAo37U9pGD5bYa/ghWeSK5tVh2XRNsfKjMPhMa44lm3pTscdU=,iv:f9hBhMksL0VGT8k2RsztU9AjR2AIIL+Z2Ls24UOPeNA=,tag:C46xDGb2d32mmHWl7WQb2g==,type:str] wg_ovpnd_us-mi_privkey: ENC[AES256_GCM,data:uEC3UOOqn1l7KwGmOxKvXccPR9Gu8/BNTlpXxXlNWf19/pIX1CLPORUWme0=,iv:cnPGghGBAsIsR86F1hPZawLWlY/pLCNF/1cg6gjrIKE=,tag:LqMbpGklQH0GX7dNNV3/8Q==,type:str] wg_ovpnd_ukr_privkey: ENC[AES256_GCM,data:5zfhsZnBk0Kb9Nb/3igsV/fN0ZDjwTAGTKyMLMly/l7MlJe6MEmd5Lv+JT8=,iv:Mov9eUP8WfvzfZ6NljgLolJ49GSqR7eSV+k0dgE1+1I=,tag:O9UtGX2qt+qEvabcsA0vIA==,type:str] -wg_home_privkey: ENC[AES256_GCM,data:c8wabBMlip3QlJ6P0ZMU/Y1Sp5V9NjVRB0sQGr9BGm1LFoSs9pkS+Su+SD8=,iv:hnIjd15g+zWqPnXu4puLrKSn2N4zVrXp32xnb315VQk=,tag:hFKSV6qb5ns9CvvuXBWLLg==,type:str] #ENC[AES256_GCM,data:qlF8rpSMUv6Z/YrOTp7WYs0lcpmSIi/r+gCuiw==,iv:cneNp/0av/ttQvnW4JVX9mj3261QFAzkLIzEMwiKwE8=,tag:FFsPUQBsSeImtymawY4eSg==,type:comment] router_passwd: ENC[AES256_GCM,data:Tya3Pd75Yu4=,iv:lqi7SavFnymL+uOQXDEzGxgikB6/ckNOBifjhyjXn1Q=,tag:HG3kf6e2g53uNUGI9FXyqQ==,type:str] jackett_apikey: ENC[AES256_GCM,data:2oGczau3f/w/5iCx3aft0V/t0tO5zsr5Xi/HQ1koTTo=,iv:33VPT8GYCPPJ2RUBP6yuLep9YX/VMW9Kt3MyQPmZuO0=,tag:TUIbutJKV5e3Kc9INk5VUA==,type:str] @@ -91,8 +90,8 @@ sops: YmhsY0FaSW5oWVNJMlhUSDRCeWQ4KzAKaQp321XYtAZ98f4QMl5PxivAYm6VMF43 wCThiQgvYAP59jvVDTZngvfWAD5PyWVVvMNbjHGvAzK5WnsTPmxlsg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-01-19T09:45:50Z" - mac: ENC[AES256_GCM,data:v+gQu9PFcLXxatllrlMX67ZaIr4MIn7v0YuQEfw2ZnIgcxlukW/wInCf8aOt+172Yme1e/YVf4X8KePUNQlFwPdfw4S+NDUSC92Kuu3/ZD3tYk46VGNPGfhiz9APeCej6oBebo4RBrIhFq5HUJe5pm2W5So/YAldUnCmfgSNyBs=,iv:plMcyLC3fj7KpOBbYcSDmY7vZpV/klHre12jbTKUhVw=,tag:yiJR3HmVYApF9CXruGGq4g==,type:str] + lastmodified: "2023-01-20T06:57:29Z" + mac: ENC[AES256_GCM,data:J/yLlcmlX6st/d6c8eL/6DKZiHAELb0/zj+5qOjoE2uAgTTFnojaP4ssrmt7BaLQF1MQNnvkchvuwRv+dAVTXkuYPuDWS3YriAKQIXUx9sHIEoY6Aqa37eBwUNUBuxoR6FvfOGtXrIZuS0f7hZr+ddBZgCSBBE54yeH68Va1tZk=,iv:Y/T8qykrqRVQ8eMkNH2DZa6XoGd5nL18h/2SJucVAD8=,tag:OwZfOyLc29c1bJJIA9IW3Q==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.3