feat: rekey funktioniert.
This commit is contained in:
parent
4fa6cc7d79
commit
6666d56b65
79
apps/rekey.nix
Normal file
79
apps/rekey.nix
Normal file
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
...
|
||||
}: system:
|
||||
with nixpkgs.lib; let
|
||||
pkgs = import nixpkgs {inherit system;};
|
||||
|
||||
rekeyCommandForHost = hostName: hostAttrs: let
|
||||
secretPath = "/tmp/nix-rekey.d/${hostName}/";
|
||||
masterIdentities = strings.concatMapStrings (x: "-i ${x} ") hostAttrs.config.rekey.masterIdentityPaths;
|
||||
|
||||
rekeyCommand = secretName: secretAttrs: let
|
||||
pubKeyStr = let
|
||||
key = hostAttrs.config.rekey.pubKey;
|
||||
in
|
||||
if isPath key
|
||||
then readFile key
|
||||
else key;
|
||||
in ''
|
||||
echo "Rekeying secret ${secretName} for host ${hostName}"
|
||||
echo "${secretAttrs.file}"
|
||||
${pkgs.rage}/bin/rage ${masterIdentities} -d ${secretAttrs.file} \
|
||||
| ${pkgs.rage}/bin/rage -r "${pubKeyStr}" -o "${secretPath}/${secretName}.age" -e \
|
||||
|| { echo "[1;3mCould not rekey secrets. Inserting dummy values[m" \
|
||||
; echo "Invalide due to failure when rekeying." \
|
||||
| ${pkgs.rage}/bin/rage -r "${pubKeyStr}" -o "${secretPath}/${secretName}.age" -e ;}
|
||||
'';
|
||||
in
|
||||
if masterIdentities == ""
|
||||
then ''
|
||||
echo "[1;3mNo Identities set for host ${hostName}. Can not decrypt.\n\
|
||||
Make sure you set 'config.rekey.masterIdentityPaths'[m"
|
||||
''
|
||||
else if
|
||||
let
|
||||
key = hostAttrs.config.rekey.pubKey;
|
||||
in
|
||||
isPath key && (! pathExists key)
|
||||
then ''
|
||||
echo "[1;3mNo public keys available for host ${hostName}. Can not decrypt.\n\
|
||||
Make sure the public keys are reachable by the building system'[m"
|
||||
''
|
||||
else ''
|
||||
mkdir -p ${secretPath}
|
||||
# TODO
|
||||
${concatStringsSep "\n" (mapAttrsToList rekeyCommand (hostAttrs.config.rekey.secrets))}
|
||||
|
||||
nix run --extra-sandbox-paths /tmp/nix-rekey.d/ "${../.}#rekey-copy-secrets"
|
||||
'';
|
||||
|
||||
rekeyScript = ''
|
||||
set -euo pipefail
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList rekeyCommandForHost self.nixosConfigurations)}
|
||||
|
||||
'';
|
||||
|
||||
rekey-exe = pkgs.writeShellScript "rekey.sh" rekeyScript;
|
||||
|
||||
rekey-copy-secretsForHost = hostName: hostAttrs: let
|
||||
secretFiles = mapAttrsToList (_: x: x.file) hostAttrs.config.rekey.secrets;
|
||||
drv = import ../modules/rekey-drv.nix pkgs secretFiles;
|
||||
in ''
|
||||
echo ${drv}
|
||||
'';
|
||||
rekey-copy-secrets-exe = pkgs.writeShellScript "rekey-copy-secrets.sh" ''
|
||||
${concatStringsSep "\n" (mapAttrsToList rekey-copy-secretsForHost self.nixosConfigurations)}
|
||||
'';
|
||||
in {
|
||||
rekey = {
|
||||
type = "app";
|
||||
program = "${rekey-exe}";
|
||||
};
|
||||
rekey-copy-secrets = {
|
||||
type = "app";
|
||||
program = "${rekey-copy-secrets-exe}";
|
||||
};
|
||||
}
|
|
@ -28,7 +28,6 @@
|
|||
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;
|
||||
|
@ -87,17 +86,8 @@
|
|||
|
||||
#TODO sollte nur bestimmte packages sein nicht alle
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
# services.xserver.xkbOptions = {
|
||||
# "eurosign:e";
|
||||
# "caps:escape" # map caps to escape.
|
||||
# };
|
||||
|
||||
# Enable CUPS to print documents.
|
||||
# services.printing.enable = true;
|
||||
|
||||
# Enable sound.
|
||||
# sound.enable = true;
|
||||
# hardware.pulseaudio.enable = true;
|
||||
powerManagement.powertop.enable = true;
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users.patrick = {
|
||||
|
|
16
flake.lock
16
flake.lock
|
@ -20,6 +20,21 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1667395993,
|
||||
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -60,6 +75,7 @@
|
|||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"home-manager": "home-manager",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
|
|
13
flake.nix
13
flake.nix
|
@ -10,6 +10,8 @@
|
|||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
|
@ -17,10 +19,12 @@
|
|||
nixpkgs,
|
||||
home-manager,
|
||||
agenix,
|
||||
flake-utils,
|
||||
...
|
||||
}: let
|
||||
} @ inputs: let
|
||||
system = "x86_64-linux";
|
||||
in {
|
||||
in
|
||||
{
|
||||
nixosConfigurations.patricknix = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
|
@ -40,5 +44,8 @@
|
|||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
// flake-utils.lib.eachSystem [system] (localSystem: {
|
||||
apps = import ./apps/rekey.nix inputs localSystem;
|
||||
});
|
||||
}
|
||||
|
|
20
modules/rekey-drv.nix
Normal file
20
modules/rekey-drv.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
pkgs: secretFiles:
|
||||
(
|
||||
pkgs.stdenv.mkDerivation rec {
|
||||
pname = "host-secrets";
|
||||
version = "1";
|
||||
description = "Rekeyed secrets for this host";
|
||||
|
||||
srcs = secretFiles;
|
||||
sourceRoot = ".";
|
||||
|
||||
dontMakeSourcesWriteable = true;
|
||||
dontUnpack = true;
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
cp -r /tmp/nix-rekey.d/ $out
|
||||
'';
|
||||
}
|
||||
)
|
|
@ -6,88 +6,19 @@
|
|||
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)}
|
||||
|
||||
'';
|
||||
};
|
||||
config = with lib; let
|
||||
secretFiles = mapAttrsToList (_: x: x.file) config.rekey.secrets;
|
||||
drv = import ./rekey-drv.nix pkgs secretFiles;
|
||||
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
|
||||
];
|
||||
|
||||
mkIf (config.rekey.secrets != {}) {
|
||||
age = {
|
||||
secrets = let
|
||||
newPath = x: "${rekeyedSecrets}/${builtins.baseNameOf x}";
|
||||
hostName = config.networking.hostName;
|
||||
secretPath = "${drv}/${hostName}/";
|
||||
newPath = x: "${secretPath}/${x}.age";
|
||||
in
|
||||
builtins.mapAttrs (_:
|
||||
builtins.mapAttrs (name: value:
|
||||
if name == "file"
|
||||
then "${newPath value}"
|
||||
else value))
|
||||
config.rekey.secrets;
|
||||
mapAttrs (name: value: value // {file = newPath name;}) 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; {
|
||||
|
@ -103,22 +34,12 @@
|
|||
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
|
||||
Only use yubikeys or password encrypted age keys
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue