Reformat all Nix files
This commit is contained in:
parent
9e0c1102a9
commit
355b63cf73
81 changed files with 2293 additions and 1153 deletions
|
@ -1,9 +1,18 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
passwordStoreDir = "/etc/passwords";
|
||||
passwordHash = password: builtins.hashString "sha256" "${password.path}\n${builtins.toString password.selector}\n${builtins.toString password.transform}";
|
||||
passwordHash =
|
||||
password:
|
||||
builtins.hashString "sha256" "${password.path}\n${builtins.toString password.selector}\n${builtins.toString password.transform}";
|
||||
passwordStorePath = password: "${passwordStoreDir}/${passwordHash password}";
|
||||
describePassword = password: password.path
|
||||
describePassword =
|
||||
password:
|
||||
password.path
|
||||
+ (if password.selector != null then " -> ${password.selector}" else "")
|
||||
+ (if password.transform != null then " | (${password.transform})" else "");
|
||||
passwordFiles = builtins.attrValues config.vivarium.passwordFiles;
|
||||
|
@ -12,16 +21,23 @@ in
|
|||
config = {
|
||||
system = {
|
||||
activationScripts.secrets = {
|
||||
deps = [ "users" "groups" ];
|
||||
deps = [
|
||||
"users"
|
||||
"groups"
|
||||
];
|
||||
supportsDryActivation = false; # TODO
|
||||
text =
|
||||
let
|
||||
readPassword = password: "cat ${lib.strings.escapeShellArg (passwordStorePath password)}";
|
||||
# Using awk's ENVIRON so it should resist any input?
|
||||
pipeSubstitute = k: v: ''K=${lib.strings.escapeShellArg k} V="$(${v})" awk '{ gsub (ENVIRON["K"], ENVIRON["V"]); print }' '';
|
||||
pipeSubstitute =
|
||||
k: v:
|
||||
''K=${lib.strings.escapeShellArg k} V="$(${v})" awk '{ gsub (ENVIRON["K"], ENVIRON["V"]); print }' '';
|
||||
subsitutePassword = variable: password: pipeSubstitute variable (readPassword password);
|
||||
subsitutePasswordFile = passwordFile: lib.mapAttrsToList subsitutePassword passwordFile.passwords;
|
||||
renderPasswordFile = passwordFile: "${lib.strings.concatStringsSep "| " (subsitutePasswordFile passwordFile)} < ${passwordFile.template}";
|
||||
renderPasswordFile =
|
||||
passwordFile:
|
||||
"${lib.strings.concatStringsSep "| " (subsitutePasswordFile passwordFile)} < ${passwordFile.template}";
|
||||
installPasswordFile = passwordFile: ''
|
||||
install -C -o ${passwordFile.owner} -g ${passwordFile.group} -m ${passwordFile.mode} -d ${builtins.dirOf passwordFile.path}
|
||||
temp="$(mktemp)"
|
||||
|
@ -31,12 +47,15 @@ in
|
|||
rm "$temp"
|
||||
trap - ERR
|
||||
'';
|
||||
installPasswordFileApp = passwordFile: pkgs.writeShellApplication {
|
||||
name = builtins.replaceStrings ["/"] ["_"] passwordFile.path;
|
||||
runtimeInputs = with pkgs; [ gawk ];
|
||||
text = installPasswordFile passwordFile;
|
||||
};
|
||||
installPasswordFileSandboxed = passwordFile:
|
||||
installPasswordFileApp =
|
||||
passwordFile:
|
||||
pkgs.writeShellApplication {
|
||||
name = builtins.replaceStrings [ "/" ] [ "_" ] passwordFile.path;
|
||||
runtimeInputs = with pkgs; [ gawk ];
|
||||
text = installPasswordFile passwordFile;
|
||||
};
|
||||
installPasswordFileSandboxed =
|
||||
passwordFile:
|
||||
''${lib.getExe (installPasswordFileApp passwordFile)} || echo Failed to install ${lib.strings.escapeShellArg passwordFile.path}'';
|
||||
in
|
||||
''
|
||||
|
@ -47,22 +66,38 @@ in
|
|||
extraSystemBuilderCmds =
|
||||
let
|
||||
passwords = builtins.attrValues config.vivarium.passwords;
|
||||
readPasswordClear = password: "pass show ${lib.strings.escapeShellArg password.path}" + (
|
||||
if password.selector == null
|
||||
then " | head -n1"
|
||||
else
|
||||
(if password.selector == "@"
|
||||
then ""
|
||||
else " | tail -n +2 | yq -r '.${password.selector}'")
|
||||
);
|
||||
readPassword = password: (readPasswordClear password) + (lib.strings.optionalString (password.transform != null) " | ${password.transform}");
|
||||
readPasswordClear =
|
||||
password:
|
||||
"pass show ${lib.strings.escapeShellArg password.path}"
|
||||
+ (
|
||||
if password.selector == null then
|
||||
" | head -n1"
|
||||
else
|
||||
(if password.selector == "@" then "" else " | tail -n +2 | yq -r '.${password.selector}'")
|
||||
);
|
||||
readPassword =
|
||||
password:
|
||||
(readPasswordClear password)
|
||||
+ (lib.strings.optionalString (password.transform != null) " | ${password.transform}");
|
||||
gitPath = password: ''"$PASSWORD_STORE_DIR"/${lib.strings.escapeShellArg password.path}.gpg'';
|
||||
isGeneratedPassword = password: ''test -f ${gitPath password}'';
|
||||
dateGit = password: " " + ''(cd "$(dirname ${gitPath password})"; git log -n1 --format='format:%ct' "$(basename ${gitPath password})")'' + " ";
|
||||
dateGit =
|
||||
password:
|
||||
" "
|
||||
+ ''(cd "$(dirname ${gitPath password})"; git log -n1 --format='format:%ct' "$(basename ${gitPath password})")''
|
||||
+ " ";
|
||||
dateStore = password: ''sudo stat -c '%Y' ${passwordStorePath password}'';
|
||||
isInStore = password: ''sudo test -f ${passwordStorePath password}'';
|
||||
testCanGenerate = password: lib.asserts.assertMsg (builtins.elem password.selector [ "@" null ]) "Unimplemented: generator + selector ${describePassword password}";
|
||||
generatePassword = password: assert testCanGenerate password; ''${password.generator} | pass insert -m ${lib.strings.escapeShellArg password.path}'';
|
||||
testCanGenerate =
|
||||
password:
|
||||
lib.asserts.assertMsg (builtins.elem password.selector [
|
||||
"@"
|
||||
null
|
||||
]) "Unimplemented: generator + selector ${describePassword password}";
|
||||
generatePassword =
|
||||
password:
|
||||
assert testCanGenerate password;
|
||||
''${password.generator} | pass insert -m ${lib.strings.escapeShellArg password.path}'';
|
||||
raiseCantGenerate = password: ''echo "Error: no generator" ; exit 1'';
|
||||
syncPasswordStore = password: ''
|
||||
# ${describePassword password}
|
||||
|
@ -112,23 +147,27 @@ in
|
|||
allFilenames = builtins.map (password: "${passwordStoreDir}/${passwordHash password}") passwords;
|
||||
in
|
||||
''
|
||||
ln -s ${lib.getExe (pkgs.writeShellApplication {
|
||||
name = "update-password-store";
|
||||
text = ''
|
||||
test -d "$PASSWORD_STORE_DIR"
|
||||
sudo install -C -o root -g root -m u=rwx -d "${passwordStoreDir}"
|
||||
ln -s ${
|
||||
lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
name = "update-password-store";
|
||||
text = ''
|
||||
test -d "$PASSWORD_STORE_DIR"
|
||||
sudo install -C -o root -g root -m u=rwx -d "${passwordStoreDir}"
|
||||
|
||||
${lib.strings.concatLines (builtins.map syncPasswordStore passwords)}
|
||||
${lib.strings.concatLines (builtins.map syncPasswordStore passwords)}
|
||||
|
||||
comm -23 <(sudo find ${passwordStoreDir} -type f -ctime +60 | sort) <(echo ${lib.strings.escapeShellArg (lib.strings.concatLines allFilenames)} | sort) | while read -r file
|
||||
do
|
||||
echo Removing "$file" from password store
|
||||
sudo rm "$file"
|
||||
done
|
||||
'';
|
||||
# -ctime +60 is so it is possible to boot from previous nixpkgs without missing transform hashes
|
||||
# TODO Find a better mechanism, maybe à la bootspec, or something compatible with cross-arch
|
||||
})} $out/bin/
|
||||
comm -23 <(sudo find ${passwordStoreDir} -type f -ctime +60 | sort) <(echo ${lib.strings.escapeShellArg (lib.strings.concatLines allFilenames)} | sort) | while read -r file
|
||||
do
|
||||
echo Removing "$file" from password store
|
||||
sudo rm "$file"
|
||||
done
|
||||
'';
|
||||
# -ctime +60 is so it is possible to boot from previous nixpkgs without missing transform hashes
|
||||
# TODO Find a better mechanism, maybe à la bootspec, or something compatible with cross-arch
|
||||
}
|
||||
)
|
||||
} $out/bin/
|
||||
'';
|
||||
};
|
||||
vivarium.passwords =
|
||||
|
@ -144,82 +183,89 @@ in
|
|||
vivarium =
|
||||
let
|
||||
defaultvar = "@PASSWORD@";
|
||||
passwordSubmodule = lib.types.submodule ({ ... }: {
|
||||
options = {
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Path to the password store entry";
|
||||
passwordSubmodule = lib.types.submodule (
|
||||
{ ... }:
|
||||
{
|
||||
options = {
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Path to the password store entry";
|
||||
};
|
||||
selector = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "If unset, selects the first line. If '@', select everything. If any other value, will parse the password metadata as YML and use selector (yq).";
|
||||
};
|
||||
generator = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "${lib.getExe pkgs.pwgen} -s 32";
|
||||
description = "Command to generate the password. Won't work when selector is set to read metadata.";
|
||||
};
|
||||
transform = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "Shell command to transform the password with before substitution";
|
||||
};
|
||||
};
|
||||
selector = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "If unset, selects the first line. If '@', select everything. If any other value, will parse the password metadata as YML and use selector (yq).";
|
||||
};
|
||||
generator = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "${lib.getExe pkgs.pwgen} -s 32";
|
||||
description = "Command to generate the password. Won't work when selector is set to read metadata.";
|
||||
};
|
||||
transform = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "Shell command to transform the password with before substitution";
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
passwords = lib.mkOption {
|
||||
default = { };
|
||||
type = lib.types.attrsOf passwordSubmodule;
|
||||
};
|
||||
passwordFiles =
|
||||
lib.mkOption {
|
||||
default = { };
|
||||
type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
|
||||
options = {
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
description = "Where to place the file.";
|
||||
passwordFiles = lib.mkOption {
|
||||
default = { };
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule (
|
||||
{ name, config, ... }:
|
||||
{
|
||||
options = {
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
description = "Where to place the file.";
|
||||
};
|
||||
mode = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0400";
|
||||
description = "Unix permission";
|
||||
};
|
||||
owner = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = "Owner of the secret file";
|
||||
};
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = "Group of the secret file";
|
||||
};
|
||||
text = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = defaultvar;
|
||||
description = "Content of the template used to make the file. Exclusive with `template`.";
|
||||
};
|
||||
template = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = pkgs.writeText "password-template" config.text;
|
||||
description = "Content of the template used to make the file. Exclusive with `text`.";
|
||||
};
|
||||
passwords = lib.mkOption {
|
||||
default = lib.optionalAttrs (config.password != null) { ${defaultvar} = config.password; };
|
||||
type = lib.types.attrsOf passwordSubmodule;
|
||||
description = "Paths to passwords that will substitute the variables in the template. Exclusive with `password`";
|
||||
};
|
||||
password = lib.mkOption {
|
||||
type = passwordSubmodule;
|
||||
description = "Path to password that will substitute '@PASSWORD@' in the template. Exclusive with `passwords`.";
|
||||
};
|
||||
};
|
||||
mode = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0400";
|
||||
description = "Unix permission";
|
||||
};
|
||||
owner = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = "Owner of the secret file";
|
||||
};
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = "Group of the secret file";
|
||||
};
|
||||
text = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = defaultvar;
|
||||
description = "Content of the template used to make the file. Exclusive with `template`.";
|
||||
};
|
||||
template = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = pkgs.writeText "password-template" config.text;
|
||||
description = "Content of the template used to make the file. Exclusive with `text`.";
|
||||
};
|
||||
passwords = lib.mkOption {
|
||||
default = lib.optionalAttrs (config.password != null) { ${defaultvar} = config.password; };
|
||||
type = lib.types.attrsOf passwordSubmodule;
|
||||
description = "Paths to passwords that will substitute the variables in the template. Exclusive with `password`";
|
||||
};
|
||||
password = lib.mkOption {
|
||||
type = passwordSubmodule;
|
||||
description = "Path to password that will substitute '@PASSWORD@' in the template. Exclusive with `passwords`.";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue