mirror of
https://github.com/oddlama/nix-config.git
synced 2025-10-11 07:10:39 +02:00
sad: this will be useless, but it has been a nice journey.
This commit is contained in:
parent
92cf272cd1
commit
9d1253c03b
3 changed files with 86 additions and 69 deletions
|
@ -33,7 +33,7 @@ in {
|
||||||
rekey.agePlugins = with pkgs; [age-plugin-yubikey];
|
rekey.agePlugins = with pkgs; [age-plugin-yubikey];
|
||||||
|
|
||||||
rekey.secrets.yolo.file = ./yolo.age;
|
rekey.secrets.yolo.file = ./yolo.age;
|
||||||
environment.etc."YOLO" = config.rekey.secrets.yolo.path;
|
environment.etc."YOLO".source = config.rekey.secrets.yolo.path;
|
||||||
|
|
||||||
home-manager = {
|
home-manager = {
|
||||||
useGlobalPkgs = true;
|
useGlobalPkgs = true;
|
||||||
|
|
|
@ -6,79 +6,98 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
with lib; {
|
with lib; {
|
||||||
config.environment.systemPackages = with pkgs; [rage];
|
# TODO add /run to sandbox only for THIS derivation
|
||||||
config.age = {
|
# TODO interactiveness how
|
||||||
secrets = let
|
# TODO yubikeySupport=true convenience option
|
||||||
rekeyedSecrets = lazyDerivation {
|
# TODO rekeyed secrets should only strip store path, not do basename
|
||||||
derivation = pkgs.stdenv.mkDerivation rec {
|
|
||||||
pname = "host-secrets";
|
|
||||||
version = "1.0.0";
|
|
||||||
description = "Rekeyed secrets for this host.";
|
|
||||||
|
|
||||||
allSecrets = mapAttrsToList (_: value: value.file) config.rekey.secrets;
|
config = let
|
||||||
hostPubkeyStr =
|
rekeyedSecrets = pkgs.stdenv.mkDerivation rec {
|
||||||
if isPath config.rekey.hostPubkey
|
pname = "host-secrets";
|
||||||
then readFile config.rekey.hostPubkey
|
version = "1.0.0";
|
||||||
else config.rekey.hostPubkey;
|
description = "Rekeyed secrets for this host.";
|
||||||
|
|
||||||
dontMakeSourcesWritable = true;
|
allSecrets = mapAttrsToList (_: value: value.file) config.rekey.secrets;
|
||||||
dontUnpack = true;
|
hostPubkeyStr =
|
||||||
dontConfigure = true;
|
if isPath config.rekey.hostPubkey
|
||||||
dontBuild = true;
|
then readFile config.rekey.hostPubkey
|
||||||
|
else config.rekey.hostPubkey;
|
||||||
|
|
||||||
installPhase = let
|
dontMakeSourcesWritable = true;
|
||||||
masterIdentityArgs = concatMapStrings (x: ''-i "${x}" '') config.rekey.masterIdentityPaths;
|
dontUnpack = true;
|
||||||
rekeyCommand = secret: ''
|
dontConfigure = true;
|
||||||
echo "Rekeying ${secret}" >&2
|
dontBuild = true;
|
||||||
${pkgs.rage}/bin/rage ${masterIdentityArgs} -d ${secret}
|
|
||||||
| ${pkgs.rage}/bin/rage -r "${hostPubkeyStr}" -o "$out/${baseNameOf secret}" -e
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
set -euo pipefail
|
|
||||||
mkdir "$out"
|
|
||||||
|
|
||||||
# Enable selected age plugins
|
installPhase = let
|
||||||
export PATH="$PATH${concatMapStrings (x: ":${x}/bin") config.rekey.agePlugins}"
|
masterIdentityArgs = concatMapStrings (x: ''-i "${x}" '') config.rekey.masterIdentityPaths;
|
||||||
|
rekeyCommand = secret: ''
|
||||||
|
echo "Rekeying ${secret}" >&2
|
||||||
|
${pkgs.rage}/bin/rage ${masterIdentityArgs} -d ${secret} \
|
||||||
|
| ${pkgs.rage}/bin/rage -r "${hostPubkeyStr}" -o "$out/${baseNameOf secret}" -e \
|
||||||
|
|| { echo 1 > $out/status ; echo "error while rekeying secret!" | ${pkgs.rage}/bin/rage -r "${hostPubkeyStr}" -o "$out/${baseNameOf secret}" -e ; }
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir "$out"
|
||||||
|
echo 0 > $out/status
|
||||||
|
|
||||||
${concatStringsSep "\n" (map rekeyCommand allSecrets)}
|
# Enable selected age plugins
|
||||||
'';
|
export PATH="$PATH${concatMapStrings (x: ":${x}/bin") config.rekey.agePlugins}"
|
||||||
};
|
|
||||||
};
|
|
||||||
rekeyedSecretPath = secret: "${rekeyedSecrets}/${baseNameOf secret}";
|
|
||||||
in
|
|
||||||
# Produce a rekeyed age secret for each of the secrets defined in our secrets
|
|
||||||
mapAttrs (_: secret:
|
|
||||||
mapAttrs (name: value:
|
|
||||||
if name == "file"
|
|
||||||
then rekeyedSecretPath value
|
|
||||||
else value)
|
|
||||||
secret)
|
|
||||||
config.rekey.secrets;
|
|
||||||
|
|
||||||
identityPaths = mkForce config.rekey.agePubkey;
|
${concatStringsSep "\n" (map rekeyCommand allSecrets)}
|
||||||
};
|
'';
|
||||||
config.assertions = mkIf (config.rekey.secrets != {}) [
|
};
|
||||||
{
|
rekeyedSecretPath = secret: "${rekeyedSecrets}/${baseNameOf secret}";
|
||||||
assertion = pathExists config.rekey.hostPubkey;
|
|
||||||
message = "The public key required to rekey secrets for this host doesn't exist. If this is the first deploy, use a mock key until you know the real one.";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
assertion = config.rekey.masterIdentityPaths != [];
|
|
||||||
message = "rekey.masterIdentityPaths must be set.";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
config.warnings = let
|
|
||||||
hasGoodSuffix = x: strings.hasSuffix ".age" x || strings.hasSuffix ".pub" x;
|
|
||||||
in
|
in
|
||||||
mkIf (!all hasGoodSuffix config.rekey.masterIdentityPaths) [
|
mkIf (config.rekey.secrets != {}) {
|
||||||
''
|
environment.systemPackages = with pkgs; [rage];
|
||||||
It seems like at least one of your rekey.masterIdentityPaths contains an
|
|
||||||
unencrypted age identity. These files will be copied to the nix store, so
|
|
||||||
make sure they don't contain any secret information!
|
|
||||||
|
|
||||||
To silence this warning, encrypt your keys and name them *.pub or *.age.
|
# This polkit rule allows the nixbld users to access the pcsc-lite daemon,
|
||||||
''
|
# which is necessary to rekey the secrets.
|
||||||
];
|
security.polkit.extraConfig = mkIf (elem pkgs.age-plugin-yubikey config.rekey.agePlugins) ''
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
'';
|
||||||
|
|
||||||
|
age.secrets =
|
||||||
|
# Produce a rekeyed age secret for each of the secrets defined in our secrets
|
||||||
|
mapAttrs (_:
|
||||||
|
mapAttrs (name: value:
|
||||||
|
if name == "file"
|
||||||
|
then rekeyedSecretPath value
|
||||||
|
else value))
|
||||||
|
config.rekey.secrets;
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = pathExists config.rekey.hostPubkey;
|
||||||
|
message = ''
|
||||||
|
The path config.rekey.hostPubkey (${toString config.rekey.hostPubkey}) doesn't exist, but is required to rekey secrets for this host.
|
||||||
|
If this is the first deploy, use a mock key until you know the real one.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = config.rekey.masterIdentityPaths != [];
|
||||||
|
message = "rekey.masterIdentityPaths must be set.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
warnings = let
|
||||||
|
hasGoodSuffix = x: strings.hasSuffix ".age" x || strings.hasSuffix ".pub" x;
|
||||||
|
in
|
||||||
|
optional (toInt (readFile "${rekeyedSecrets}/status") == 1) "Failed to rekey secrets! Run nix log ${rekeyedSecrets}.drv for more information."
|
||||||
|
++ optional (!all hasGoodSuffix config.rekey.masterIdentityPaths)
|
||||||
|
''
|
||||||
|
It seems like at least one of your rekey.masterIdentityPaths contains an
|
||||||
|
unencrypted age identity. These files will be copied to the nix store, so
|
||||||
|
make sure they don't contain any secret information!
|
||||||
|
|
||||||
|
To silence this warning, encrypt your keys and name them *.pub or *.age.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
rekey.secrets = options.age.secrets;
|
rekey.secrets = options.age.secrets;
|
||||||
|
@ -128,6 +147,3 @@ with lib; {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#rekey.secrets.my_secret.file = ./secrets/somekey.age;
|
|
||||||
#pwdfile = rekey.secrets.mysecret.path;
|
|
||||||
|
|
||||||
|
|
1
secrets/pubkeys/ward.pub
Normal file
1
secrets/pubkeys/ward.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIES9HTyQjzIDPkMP90MV5f1zwearLFPF8KkLpAnEYEfJ
|
Loading…
Add table
Add a link
Reference in a new issue