From a6a1e32ade6df8cd002d8402995065b9841149ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Geoffrey=20=E2=80=9CFrogeye=E2=80=9D=20Preud=27homme?= Date: Sat, 29 Jun 2024 01:50:18 +0200 Subject: [PATCH] passwords: Only read passwords if needs updating No need for unlocking keys on each rebuild anymore! --- os/password/default.nix | 66 ++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/os/password/default.nix b/os/password/default.nix index be7665d..4cfa97e 100644 --- a/os/password/default.nix +++ b/os/password/default.nix @@ -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