passwords: Only read passwords if needs updating

No need for unlocking keys on each rebuild anymore!
This commit is contained in:
Geoffrey Frogeye 2024-06-29 01:50:18 +02:00
parent 7b9c4fb004
commit a6a1e32ade
Signed by: geoffrey
GPG key ID: C72403E7F82E6AD8

View file

@ -56,29 +56,59 @@ in
else " | tail -n +2 | yq -r '.${password.selector}'")
);
readPassword = password: (readPasswordClear password) + (lib.strings.optionalString (password.transform != null) " | ${password.transform}");
isGeneratedPassword = password: ''test -f "$PASSWORD_STORE_DIR"/${lib.strings.escapeShellArg password.path}.gpg'';
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})")'' + " ";
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}'';
raiseCantGenerate = password: ''echo "Error: no generator" ; exit 1'';
ensurePassword = password: ''
if ! ${isGeneratedPassword password}
syncPasswordStore = password: ''
# ${describePassword password}
write=false
if ${isInStore password}
then
echo Generating ${lib.strings.escapeShellArg (describePassword password)}
${(if password.generator != null then generatePassword else raiseCantGenerate) password}
if ${isGeneratedPassword password}
then
date_store="$(${dateStore password})"
date_git="$(${dateGit password})"
if [ "$date_git" -eq "$date_store" ]
then
echo ${lib.strings.escapeShellArg (describePassword password)}: up-to-date
elif [ "$date_git" -gt "$date_store" ]
then
echo ${lib.strings.escapeShellArg (describePassword password)}: updating
write=true
else
echo ERROR ${lib.strings.escapeShellArg (describePassword password)}: store is more recent than git
exit 1
fi
else
echo ERROR ${lib.strings.escapeShellArg (describePassword password)}: exists in store but not in git
exit 1
fi
else
if ${isGeneratedPassword password}
then
echo ${lib.strings.escapeShellArg (describePassword password)}: installing
else
echo ${lib.strings.escapeShellArg (describePassword password)}: generating
${(if password.generator != null then generatePassword else raiseCantGenerate) password}
fi
write=true
fi
if [ "$write" = true ]
then
temp="$(mktemp)"
trap 'rm "$temp"' ERR
${readPassword password} > "$temp"
touch -d @"$(${dateGit password})" "$temp"
sudo install -o root -g root -m u=rw -p -T "$temp" ${lib.strings.escapeShellArg (passwordStorePath password)}
rm "$temp"
trap - ERR
fi
'';
writePasswordStore = password: ''
# ${describePassword password}
${ensurePassword password}
echo Updating ${lib.strings.escapeShellArg (describePassword password)} in password store
temp="$(mktemp)"
trap 'rm "$temp"' ERR
${readPassword password} > "$temp"
sudo install -C -o root -g root -m u=rw -T "$temp" ${lib.strings.escapeShellArg (passwordStorePath password)}
rm "$temp"
trap - ERR
'';
# TODO Only read password if timestamp didn't change from git repository (and alert if in future, exists on fs but not in git, etc.)
allFilenames = builtins.map (password: "${passwordStoreDir}/${passwordHash password}") passwords;
in
''
@ -88,7 +118,7 @@ in
test -d "$PASSWORD_STORE_DIR"
sudo install -C -o root -g root -m u=rwx -d "${passwordStoreDir}"
${lib.strings.concatLines (builtins.map writePasswordStore passwords)}
${lib.strings.concatLines (builtins.map syncPasswordStore passwords)}
comm -23 <(sudo find ${passwordStoreDir} -type f | sort) <(echo ${lib.strings.escapeShellArg (lib.strings.concatLines allFilenames)} | sort) | while read -r file
do