diff --git a/flake.nix b/flake.nix index ddf7de5..1106f3f 100644 --- a/flake.nix +++ b/flake.nix @@ -46,8 +46,15 @@ ... } @ inputs: { + # The identities that are used to rekey agenix secrets and to + # decrypt all repository-wide secrets. + secrets = { + masterIdentities = [./secrets/yk1-nix-rage.pub]; + extraEncryptionPubkeys = [./secrets/backup.pub]; + content = import ./nix/secrets.nix inputs; + }; + hosts = import ./nix/hosts.nix inputs; - secrets = import ./nix/secrets.nix inputs; colmena = import ./nix/colmena.nix inputs; overlays = import ./nix/overlay.nix inputs; homeConfigurations = import ./nix/home-manager.nix inputs; diff --git a/hosts/zackbiene/secrets/secrets.nix.age b/hosts/zackbiene/secrets/secrets.nix.age index 080e166..25625ad 100644 Binary files a/hosts/zackbiene/secrets/secrets.nix.age and b/hosts/zackbiene/secrets/secrets.nix.age differ diff --git a/nix/apps.nix b/nix/apps.nix index 6208205..389fa1b 100644 --- a/nix/apps.nix +++ b/nix/apps.nix @@ -45,4 +45,31 @@ in set -euo pipefail ${mapAttrsToLines generateHostKey self.nodes} ''); + format-secrets = let + isAbsolutePath = x: substring 0 1 x == "/"; + masterIdentityArgs = concatMapStrings (x: ''-i "${x}" '') self.secrets.masterIdentities; + extraEncryptionPubkeys = + concatMapStrings ( + x: + if isAbsolutePath x + then ''-R "${x}" '' + else ''-r "${x}" '' + ) + self.secrets.extraEncryptionPubkeys; + formatSecret = path: '' + ''; + in + mkApp (pkgs.writeShellScript "format-secrets" '' + 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; } + for f in $(find . -type f -name '*.nix.age'); do + echo "Formatting $f ..." + decrypted=$(${./rage-decrypt.sh} --print-out-path "$f" ${concatStringsSep " " self.secrets.masterIdentities}) \ + || { echo "error: Failed to decrypt!" >&2; exit 1; } + formatted=$(${pkgs.alejandra}/bin/alejandra --quiet < "$decrypted") \ + || { echo "error: Failed to format $decrypted!" >&2; exit 1; } + ${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$formatted" > "$f" \ + || { echo "error: Failed to re-encrypt!" >&2; exit 1; } + done + ''); } diff --git a/nix/colmena.nix b/nix/colmena.nix index 3469996..4490706 100644 --- a/nix/colmena.nix +++ b/nix/colmena.nix @@ -14,7 +14,7 @@ with nixpkgs.lib; let nixosHosts = filterAttrs (_: x: x.type == "nixos") self.hosts; generateColmenaNode = hostName: _: { imports = [ - ({ config, ... }: { + ({config, ...}: { # By default, set networking.hostName to the hostName networking.hostName = mkDefault hostName; # Define global flakes for this system @@ -27,8 +27,8 @@ with nixpkgs.lib; let # Setup parameters for Secrets rekey.forceRekeyOnSystem = "x86_64-linux"; rekey.hostPubkey = ../secrets/pubkeys + "/${config.networking.hostName}.pub"; - rekey.masterIdentities = [../secrets/yk1-nix-rage.pub]; - rekey.extraEncryptionPubkeys = [../secrets/backup.pub]; + rekey.masterIdentities = self.secrets.masterIdentities; + rekey.extraEncryptionPubkeys = self.secrets.extraEncryptionPubkeys; }) (../hosts + "/${hostName}") home-manager.nixosModules.default @@ -46,12 +46,12 @@ in nodeNixpkgs = mapAttrs (hostName: {system, ...}: self.pkgs.${system}) nixosHosts; nodeSpecialArgs = mapAttrs (hostName: _: { - nodeSecrets = self.secrets.nodes.${hostName}; + nodeSecrets = self.secrets.content.nodes.${hostName}; }) nixosHosts; specialArgs = { inherit (nixpkgs) lib; - inherit (self) secrets; + secrets = self.secrets.content; nixos-hardware = nixos-hardware.nixosModules; #impermanence = impermanence.nixosModules; }; diff --git a/nix/rage-decrypt.sh b/nix/rage-decrypt.sh index 5ac1780..8ee9f52 100755 --- a/nix/rage-decrypt.sh +++ b/nix/rage-decrypt.sh @@ -2,14 +2,20 @@ set -euo pipefail +print_out_path=false +if [[ "$1" == "--print-out-path" ]]; then + print_out_path=true + shift +fi + file="$1" -[[ "$file" == "/nix/store/"* ]] || { echo "Input must be a store path!"; exit 1; } shift identities=("$@") -# Strip .age suffix and store path prefix +# Strip .age suffix, and store path prefix or ./ if applicable basename="${file%".age"}" -basename="${basename#*"-"}" +[[ "$file" == "/nix/store/"* ]] && basename="${basename#*"-"}" +[[ "$file" == "./"* ]] && basename="${basename#"./"}" # Calculate a unique content-based identifier (relocations of # the source file in the nix store should not affect caching) @@ -29,5 +35,5 @@ if [[ ! -e "$out" ]]; then rage -d "${args[@]}" -o "$out" "$file" fi -# Print decrypted content -cat "$out" +# Print out path or decrypted content +[[ "$print_out_path" == true ]] && echo "$out" || cat "$out" diff --git a/nix/secrets.nix b/nix/secrets.nix index be57fd6..be99e60 100644 --- a/nix/secrets.nix +++ b/nix/secrets.nix @@ -17,8 +17,6 @@ ... } @ inputs: with nixpkgs.lib; let - # The identities that are used to decrypt any repository-wide secrets. - masterIdentities = [../secrets/yk1-nix-rage.pub]; # 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 # how modules can be functions or sets. @@ -30,7 +28,7 @@ with nixpkgs.lib; let importEncrypted = path: constSet ( if builtins.pathExists path - then builtins.extraBuiltins.rageImportEncrypted masterIdentities path + then builtins.extraBuiltins.rageImportEncrypted self.secrets.masterIdentities path else {} ); in diff --git a/secrets/secrets.nix.age b/secrets/secrets.nix.age index 624516c..5b02c71 100644 --- a/secrets/secrets.nix.age +++ b/secrets/secrets.nix.age @@ -1,9 +1,10 @@ age-encryption.org/v1 --> X25519 vyK4cXkYqS/xic3L1hVfZOm9F2dy41g0k8NtY0S7o0g -pdm+YdbPD+jg9oRGD1m/bSFwmcI6slqCg8bSSHUgyTg --> piv-p256 xqSe8Q A7Z8dLqDdsXdeMFUI0yZy7IOH+VovH4bzc2dRkCKQYoE -fa0294BZfM4wYXdF1j5BogNpVdgfhnITHIFubQq8G6M --> X-grease YRM7Gw8# 0\&Rw -SXlWKCRgatc1AAoprriaOmKPrw ---- ybnfcV0t6H0UUl6Oc5z6EYOuLxpeVqh+TcywwgevaFw -aC kz DMYw8ߛچ.O X25519 jCfz22p8CDk1U/maaSqUBJh4KsHNvu2MM54IG9bVuFI +ChPScrrrFWgg8sVFucu7u5af+BXGgYczIpoohiYQSow +-> piv-p256 xqSe8Q A64wBcZEPJKnAC9xlBc3gbosqhB9sNN/dFZDQSMcB3Kp +9ksGpeSm8WOELDHLeTrttKA1ynDEwxi+jNRWzxQfxMQ +-> DiE~<-grease +p5tg4SCVvfjsWqai9U2ABMsTwBkIa2waWtGdK4/ulHcCHR8CMvYKS9bjjsw/Z0ZH +pwDzZGosmU5vRZxy/HM +--- U08NaDLEjVxdVr4TfeFK07h6ZcaZf1XN79X6mQyLmnk +hM*$\1?gs;kɻ"w}> \ No newline at end of file