twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
13.36k stars 493 forks source link

Skip template interpolation for run_once_, run_onchange_ script templates #3701

Closed vaygr closed 6 months ago

vaygr commented 6 months ago

What exactly are you trying to do?

My use-case is simple: I want to import SSH keys from the password manager only once using chezmoi's password manager functions (specifically keepassxcAttachment()).

run_once_ seems like a perfect solution, however chezmoi renders the template regardless whether it starts with run_once_ or not, asking for the password on every apply, status, etc. and then does nothing (expected). I realize chezmoi does that to compare sha256 of the script in the state bucket.

But maybe you could consider a setting or something else to skip template rendering for scripts starting with run_once_ or run_onchange_? Or maybe introduce state bucket for templated scripts? Open to suggestions here.

What have you tried so far?

N/A

Where else have you checked for solutions?

Output of any commands you've tried with --verbose flag

N/A

Output of chezmoi doctor

N/A

Additional context

N/A

twpayne commented 6 months ago

As you identify, chezmoi needs to execute the template to see if its contents have changed. The contents can also change if you change your SSH keys in KeePassXC, so chezmoi has to invoke your password manager to retrieve your SSH keys each time.

For your use case, you can use a run_ script instead, something like (warning untested):

#!/bin/bash

if [ ! -f ~/.ssh/id_rsa ] ; then
    keepassxc-cli attachment-export "SSH config" "key.txt" ~/.ssh/id_rsa
fi

This will only invoke keepassxc-cli if ~/.ssh/id_rsa does not already exist.

vaygr commented 6 months ago

Yeah, I was thinking about executing plain keepassxc-cli. I guess that'll suffice.

vaygr commented 6 months ago

So then come inconveniences:

halostatue commented 6 months ago

So then come inconveniences:

  • N keys == N password prompts / database unlocks
  • non-standard password prompts instead of using pinentry or whatever you can specify for chezmoi to use

The password prompts should be keepassxc-cli standard password prompts.

If you know all the keys that you’re going to work with and how to transform them, you can do so with interactive mode — but you’d be working against the grain for keepassxc-cli, where the inconvenience is at least part of the point of keepassxc.

Chezmoi uses interactive mode to request the password once and deal with the vault on an open thread until application is complete in order to prevent many password requests.

See the open command: https://www.mankier.com/1/keepassxc-cli#Commands-open

vaygr commented 6 months ago

@halostatue thanks, I tried open a few hours ago, but it didn't work for me. It showed prompt instead of just opening the database. What I ended up doing was a script that pipes the password to keepassxc-cli. This way I just ask the password once:

#!/bin/sh

set -eo pipefail

database="$HOME/Sync/Keys.kdbx"
keys_ssh=("id_ed25519" "id_ed25519_1" "id_ed25519_2" "id_rsa_backup")
password=$(getpin "$database password:")

[ $? -eq 0 ] || exit 2

for key in "${keys_ssh[@]}"; do
  dst_key="$HOME/.ssh/test_${key}"

  if [ ! -f "${dst_key}" ] ; then
    printf "%s" "$password" | keepassxc-cli attachment-export "${database}" "SSH/${key}" "${key}" "${dst_key}"

    [ $? -eq 0 ] && chmod 600 "${dst_key}" || exit 3
  fi

  if [ -f "${dst_key}" -a ! -f "${dst_key}.pub" ] ; then
    printf "%s\n" "Generating public key from ${dst_key}"

    pub_key=$(ssh-keygen -y -f "${dst_key}")

    [ $? -eq 0 ] && printf "%s\n" "${pub_key}" > "${dst_key}.pub" || exit 4
  fi
done

I have a separate script (getpin) that asks for a password using pinentry / pinentry-dmenu.