WIP: rekey module to rekey all secrets using the yubikey
Work apart from interactivity. Pins are thus currently unsopported Will be supperseeded by a flake runable to rekey secrets on demand
This commit is contained in:
parent
f355c527ee
commit
4fa6cc7d79
5
README.md
Normal file
5
README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Meine wundervolle nix config
|
||||||
|
|
||||||
|
For secrets:
|
||||||
|
- encrypt using: `rage -R recipients.txt -o [OUT] -e [IN] `
|
||||||
|
- decrypt using: `rage -R recipients.txt -o [OUT] -d [IN] `
|
|
@ -4,7 +4,7 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
age,
|
lib,
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
imports = [
|
imports = [
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
./users
|
./users
|
||||||
#
|
#
|
||||||
./modules/pipewire.nix
|
./modules/pipewire.nix
|
||||||
|
./modules/rekey.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Use the systemd-boot EFI boot loader.
|
# Use the systemd-boot EFI boot loader.
|
||||||
|
@ -22,20 +23,24 @@
|
||||||
|
|
||||||
networking.hostName = "patricknix"; # Define your hostname.
|
networking.hostName = "patricknix"; # Define your hostname.
|
||||||
networking.hostId = "68438432";
|
networking.hostId = "68438432";
|
||||||
# Pick only one of the below networking options.
|
|
||||||
|
# Identities with which all secrets are encrypted
|
||||||
|
rekey.masterIdentityPaths = [./secrets/NIXOSc.key ./secrets/NIXOSa.key];
|
||||||
|
|
||||||
|
rekey.pubKey = ./keys + "/${config.networking.hostName}.pub";
|
||||||
|
rekey.privKey = "/etc/ssh/ssh_host_ed25519_key";
|
||||||
|
rekey.plugins = [pkgs.age-plugin-yubikey];
|
||||||
|
|
||||||
networking.wireless.iwd.enable = true;
|
networking.wireless.iwd.enable = true;
|
||||||
age.identityPaths = [ ./secrets/NIXOSc.key ./secrets/NIXOSa.key ];
|
rekey.secrets.eduroam = {
|
||||||
age.plugins = [ pkgs.age-plugin-yubikey ];
|
|
||||||
age.secrets.eduroam = {
|
|
||||||
file = ./secrets/iwd/eduroam.8021x.age;
|
file = ./secrets/iwd/eduroam.8021x.age;
|
||||||
path = "/etc/iwd/eduroam.8021x";
|
path = "/etc/iwd/eduroam.8021x";
|
||||||
};
|
};
|
||||||
age.secrets.devoloog = {
|
rekey.secrets.devoloog = {
|
||||||
file = ./secrets/iwd/devolo-og.psk.age;
|
file = ./secrets/iwd/devolo-og.psk.age;
|
||||||
path = "/etc/iwd/devolo-og.psk";
|
path = "/etc/iwd/devolo-og.psk";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
networking.useNetworkd = true;
|
networking.useNetworkd = true;
|
||||||
networking.dhcpcd.enable = false;
|
networking.dhcpcd.enable = false;
|
||||||
systemd.network.wait-online.anyInterface = true;
|
systemd.network.wait-online.anyInterface = true;
|
||||||
|
@ -139,6 +144,9 @@
|
||||||
};
|
};
|
||||||
hostKeys = [
|
hostKeys = [
|
||||||
{
|
{
|
||||||
|
# never set this to an actual nix type path
|
||||||
|
# or else .....
|
||||||
|
# it will end up in the nix store
|
||||||
path = "/etc/ssh/ssh_host_ed25519_key";
|
path = "/etc/ssh/ssh_host_ed25519_key";
|
||||||
type = "ed25519";
|
type = "ed25519";
|
||||||
}
|
}
|
||||||
|
@ -196,6 +204,10 @@
|
||||||
];
|
];
|
||||||
cores = 0;
|
cores = 0;
|
||||||
max-jobs = "auto";
|
max-jobs = "auto";
|
||||||
|
|
||||||
|
# If the yubikey is needed for rekeying my secrets the sandbox need acces to the pcscd daemon socket
|
||||||
|
# TODO only give the one derivation access to this path
|
||||||
|
extra-sandbox-paths = lib.mkIf (lib.elem pkgs.age-plugin-yubikey config.rekey.plugins) ["/run/pcscd/"];
|
||||||
};
|
};
|
||||||
daemonCPUSchedPolicy = "batch";
|
daemonCPUSchedPolicy = "batch";
|
||||||
daemonIOSchedPriority = 5;
|
daemonIOSchedPriority = 5;
|
||||||
|
|
22
flake.lock
22
flake.lock
|
@ -7,15 +7,15 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1674681075,
|
"lastModified": 1673301561,
|
||||||
"narHash": "sha256-hXbIv9WHHEQvoXtK4hWKx4EzmTLUzMdjV8e/x/R9nP8=",
|
"narHash": "sha256-gRUWHbBAtMuPDJQXotoI8u6+3DGBIUZHkyQWpIv7WpM=",
|
||||||
"owner": "oddlama",
|
"owner": "ryantm",
|
||||||
"repo": "agenix",
|
"repo": "agenix",
|
||||||
"rev": "12d1b138188dda50704c2816be73d6e183f45797",
|
"rev": "42d371d861a227149dc9a7e03350c9ab8b8ddd68",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "oddlama",
|
"owner": "ryantm",
|
||||||
"repo": "agenix",
|
"repo": "agenix",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,11 @@
|
||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1674556204,
|
"lastModified": 1674771519,
|
||||||
"narHash": "sha256-HCRmkZsq01h2Evch08zpgE9jeHdMtGdT1okWotyvuhY=",
|
"narHash": "sha256-U0W3S1nX6yEvLh3Vq70EORbmXecAKXfmEfCfaA4A+I8=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "c59f0eac51da91c6989fd13a68e156f63c0e60b6",
|
"rev": "bb4b25b302dbf0f527f190461b080b5262871756",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -43,11 +43,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1674459583,
|
"lastModified": 1674641431,
|
||||||
"narHash": "sha256-L0UZl/u2H3HGsrhN+by42c5kNYeKtdmJiPzIRvEVeiM=",
|
"narHash": "sha256-qfo19qVZBP4qn5M5gXc/h1MDgAtPA5VxJm9s8RUAkVk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "1b1f50645af2a70dc93eae18bfd88d330bfbcf7f",
|
"rev": "9b97ad7b4330aacda9b2343396eb3df8a853b4fc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
31
flake.nix
31
flake.nix
|
@ -1,17 +1,27 @@
|
||||||
{
|
{
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
inputs = {
|
||||||
inputs.home-manager = {
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
home-manager = {
|
||||||
url = "github:nix-community/home-manager";
|
url = "github:nix-community/home-manager";
|
||||||
# should use system nixpkgs instead of their own
|
# should use system nixpkgs instead of their own
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
inputs.agenix.url = "github:oddlama/agenix";
|
agenix = {
|
||||||
inputs.agenix.inputs.nixpkgs.follows = "nixpkgs";
|
url = "github:ryantm/agenix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, home-manager, agenix, ... }: let
|
outputs = {
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
home-manager,
|
||||||
|
agenix,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
in {nixosConfigurations.patricknix =
|
in {
|
||||||
nixpkgs.lib.nixosSystem {
|
nixosConfigurations.patricknix = nixpkgs.lib.nixosSystem {
|
||||||
inherit system;
|
inherit system;
|
||||||
modules = [
|
modules = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
|
@ -21,6 +31,13 @@
|
||||||
home-manager.useUserPackages = true;
|
home-manager.useUserPackages = true;
|
||||||
}
|
}
|
||||||
agenix.nixosModule
|
agenix.nixosModule
|
||||||
|
{
|
||||||
|
nix.registry = {
|
||||||
|
nixpkgs.flake = nixpkgs;
|
||||||
|
p.flake = nixpkgs;
|
||||||
|
pkgs.flake = nixpkgs;
|
||||||
|
};
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
1
keys/patricknix.pub
Normal file
1
keys/patricknix.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJrr6bJgWzCuS+00EEBQRoylwput69tqvotgPjSF5xhz root@patricknix
|
134
modules/rekey.nix
Normal file
134
modules/rekey.nix
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
stdenv,
|
||||||
|
options,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
# TODO add a with lib um mir die ganzen lib. zu ersparen
|
||||||
|
config = let
|
||||||
|
masterIdentities = lib.strings.concatMapStrings (x: "-i ${x} ") config.rekey.masterIdentityPaths;
|
||||||
|
rekeyedSecrets = pkgs.stdenv.mkDerivation rec {
|
||||||
|
pname = "age-rekey";
|
||||||
|
version = "1.0.0";
|
||||||
|
allSecrets = lib.mapAttrsToList (_: x: x.file) config.rekey.secrets;
|
||||||
|
pubKeyStr =
|
||||||
|
if builtins.isPath config.rekey.pubKey
|
||||||
|
then builtins.readFile config.rekey.pubKey
|
||||||
|
else config.rekey.pubKey;
|
||||||
|
dontMakeSourceWriteable = 1;
|
||||||
|
dontUnpack = true;
|
||||||
|
dontPatch = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
installPhase = let
|
||||||
|
pluginPaths = lib.strings.concatMapStrings (x: ":${x}/bin") config.rekey.plugins;
|
||||||
|
|
||||||
|
rekeyCommand = secret: ''
|
||||||
|
echo "Rekeying secret ${secret}" >&2
|
||||||
|
${pkgs.rage}/bin/rage ${masterIdentities} -d ${secret} \
|
||||||
|
| ${pkgs.rage}/bin/rage -r "${pubKeyStr}" -o "$out/${builtins.baseNameOf secret}" -e \
|
||||||
|
|| { echo 1 > "$out"/status; echo "disabled due to failure in rekey.nix" | ${pkgs.rage}/bin/rage -r "${pubKeyStr}" -o "$out/${builtins.baseNameOf secret}" -e ;}
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir $out
|
||||||
|
echo 0 > "$out"/status
|
||||||
|
|
||||||
|
export PATH=$PATH${pluginPaths}
|
||||||
|
${lib.concatStringsSep "\n" (map rekeyCommand allSecrets)}
|
||||||
|
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.mkIf (config.rekey.secrets != {}) {
|
||||||
|
# Polkit rule to enable the build process to access the keys saved on a yubikey
|
||||||
|
# This rule allows any user named nixbld<num> to accesst pcscd
|
||||||
|
security.polkit.extraConfig = lib.mkIf (lib.elem pkgs.age-plugin-yubikey config.rekey.plugins) ''
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
if ((action.id == "org.debian.pcsc-lite.access_pcsc" || action.id == "org.debian.pcsc-lite.access_card") &&
|
||||||
|
subject.user.match(/^nixbld\d+$/)) {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
rage
|
||||||
|
];
|
||||||
|
|
||||||
|
age = {
|
||||||
|
secrets = let
|
||||||
|
newPath = x: "${rekeyedSecrets}/${builtins.baseNameOf x}";
|
||||||
|
in
|
||||||
|
builtins.mapAttrs (_:
|
||||||
|
builtins.mapAttrs (name: value:
|
||||||
|
if name == "file"
|
||||||
|
then "${newPath value}"
|
||||||
|
else value))
|
||||||
|
config.rekey.secrets;
|
||||||
|
};
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = builtins.pathExists config.rekey.pubKey;
|
||||||
|
message = "Did not find key file: ${config.rekey.pubKey}.
|
||||||
|
Make sure your public key is available for rekeying.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = config.rekey.masterIdentityPaths != [];
|
||||||
|
message = "rekey.masterIdentityPaths must be set!";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
warnings =
|
||||||
|
lib.optional (builtins.any (x: !(lib.strings.hasSuffix ".pub" x || lib.strings.hasSuffix ".age" x)) config.rekey.masterIdentityPaths) ''
|
||||||
|
It seems at least one of your master masterIdentities files is not encrypted or not a public handle.
|
||||||
|
Please make sure it does not contain any secret Information.
|
||||||
|
''
|
||||||
|
++ lib.optional (lib.toInt (builtins.readFile "${rekeyedSecrets}/status") == 1) ''
|
||||||
|
Could not rekey. Might be due to a chicken/egg problem, then a retry will fix this.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
options = with lib; {
|
||||||
|
rekey.secrets = options.age.secrets;
|
||||||
|
rekey.pubKey = mkOption {
|
||||||
|
type = types.either types.path types.str;
|
||||||
|
description = ''
|
||||||
|
The age public key set as a recipient when rekeying.
|
||||||
|
either a path to a public key file or a string public key
|
||||||
|
**NEVER set this to a private key part**
|
||||||
|
~~This will end up in the nix store.~~
|
||||||
|
'';
|
||||||
|
example = /etc/ssh/ssh_host_ed25519_key.pub;
|
||||||
|
};
|
||||||
|
|
||||||
|
rekey.privKey = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
The age private key part, corresponding to the public key set in "rekey.pubKey".
|
||||||
|
Used by agenix for decryption.
|
||||||
|
Preferably set this to your ed25519 host key.
|
||||||
|
'';
|
||||||
|
example = "/etc/ssh/ssh_host_ed25519_key";
|
||||||
|
};
|
||||||
|
|
||||||
|
rekey.masterIdentityPaths = mkOption {
|
||||||
|
type = types.listOf types.path;
|
||||||
|
description = ''
|
||||||
|
A list of Identities used for decrypting your secrets before rekeying.
|
||||||
|
**WARING this will end up in the nix-store**
|
||||||
|
Only use yubikeys or encrypted age keys
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rekey.plugins = mkOption {
|
||||||
|
type = types.listOf types.package;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
A list of plugins that should be available in your path when rekeying.
|
||||||
|
'';
|
||||||
|
example = [pkgs.age-plugin-yubikey];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
6
secrets/recipients.txt
Normal file
6
secrets/recipients.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
age1faus9en5ywxc69rewmjvz63vqpv5n08f4w7qsd97k6mldd8avqks52ghyl
|
||||||
|
# Backup Key
|
||||||
|
age1yubikey1q2w0nrz60e75shexudc0s3j8n4kggdp87cjzejvc6mzzge5h5yp9sj6sqk5
|
||||||
|
# yubikey A
|
||||||
|
age1yubikey1qfu3708kl2anypfzas7mn78z5rqnqpy0ffmg9hqn8uxlgcws5r9czuqs6y7
|
||||||
|
# yubikey C
|
|
@ -1,13 +1,14 @@
|
||||||
{config,pkgs,...}:
|
|
||||||
{
|
{
|
||||||
programs.autorandr =
|
config,
|
||||||
let
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
programs.autorandr = let
|
||||||
dpi_hd = 96;
|
dpi_hd = 96;
|
||||||
dpi_uhd = 192;
|
dpi_uhd = 192;
|
||||||
set_dpi = dpi: "echo 'Xft.dpi: ${toString dpi}' | ${pkgs.xorg.xrdb}/bin/xrdb -merge";
|
set_dpi = dpi: "echo 'Xft.dpi: ${toString dpi}' | ${pkgs.xorg.xrdb}/bin/xrdb -merge";
|
||||||
eDP-1 = "00ffffffffffff0006afeb3000000000251b0104a5221378020925a5564f9b270c50540000000101010101010101010101010101010152d000a0f0703e803020350058c11000001852d000a0f07095843020350025a51000001800000000000000000000000000000000000000000002001430ff123caa8f0e29aa202020003e";
|
eDP-1 = "00ffffffffffff0006afeb3000000000251b0104a5221378020925a5564f9b270c50540000000101010101010101010101010101010152d000a0f0703e803020350058c11000001852d000a0f07095843020350025a51000001800000000000000000000000000000000000000000002001430ff123caa8f0e29aa202020003e";
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
enable = true;
|
enable = true;
|
||||||
profiles.AStA = {
|
profiles.AStA = {
|
||||||
fingerprint = {
|
fingerprint = {
|
||||||
|
|
|
@ -42,11 +42,9 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHxD4GOrwrBTG4/qQhm5hoSB2CP7W9g1LPWP11oLGOjQ
|
||||||
'';
|
'';
|
||||||
programs.ssh = {
|
programs.ssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
matchBlocks =
|
matchBlocks = let
|
||||||
let
|
|
||||||
identityFile = ["~/.ssh/1.pub" "~/.ssh/2.pub"];
|
identityFile = ["~/.ssh/1.pub" "~/.ssh/2.pub"];
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
"elisabeth" = {
|
"elisabeth" = {
|
||||||
hostname = "lel.lol";
|
hostname = "lel.lol";
|
||||||
user = "root";
|
user = "root";
|
||||||
|
@ -107,5 +105,4 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHxD4GOrwrBTG4/qQhm5hoSB2CP7W9g1LPWP11oLGOjQ
|
||||||
signByDefault = true;
|
signByDefault = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
{ config,pkgs,...}:
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
programs.zsh = {
|
programs.zsh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
initExtra = builtins.readFile ../../data/zsh/zshrc;
|
initExtra = builtins.readFile ../../data/zsh/zshrc;
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
config,
|
config,
|
||||||
home-manager,
|
home-manager,
|
||||||
...
|
...
|
||||||
}:
|
}: {
|
||||||
{
|
|
||||||
home-manager.users.patrick.imports = [./patrick.nix];
|
home-manager.users.patrick.imports = [./patrick.nix];
|
||||||
home-manager.users.root = {
|
home-manager.users.root = {
|
||||||
imports = [./common];
|
imports = [./common];
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
common/autorandr.nix
|
common/autorandr.nix
|
||||||
common/desktop.nix
|
common/desktop.nix
|
||||||
./common
|
./common
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
home = {
|
home = {
|
||||||
|
|
Loading…
Reference in a new issue