From a6da233005cef270e65bcdae9c6bbc58d5bdf0e3 Mon Sep 17 00:00:00 2001 From: Mitchell Riedstra Date: Fri, 12 Dec 2025 17:43:17 -0500 Subject: Update the 'age' backend to be a bit more user friendly --- dpw-age | 81 ++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 23 deletions(-) (limited to 'dpw-age') diff --git a/dpw-age b/dpw-age index 1d98303..3966621 100755 --- a/dpw-age +++ b/dpw-age @@ -22,6 +22,9 @@ umask "$UMASK" DPW_AGE_DIR="${DPW_AGE_DIR:-$HOME/.dpw-age}" DPW_AGE_KEY="${DPW_AGE_KEY:-$HOME/.dpw-age-key}" +DPW_AGE_RECIPIENT_SUFFIX="${DPW_AGE_RECIPIENT_SUFFIX:-.recipients}" +# No user overrides +DPW_AGE_RECIPIENTS_FILE="" USE_GIT=0 [ -e "${DPW_AGE_DIR}/.git" ] && USE_GIT=1 @@ -36,17 +39,11 @@ _git_commit() { } _set_age_recipients() { -if [ -n "$DPW_AGE_RECIPIENTS" ] ; then - DPW_AGE_RECIPIENTS="$(echo "$DPW_AGE_RECIPIENTS" | tr ' ' '\n' \ - | sed -e's/^/ -r/' | tr '\n' ' ')" - return -fi _pth="$1"; shift _pth="${DPW_AGE_DIR}/$_pth" - -id_file="$(dirname "${_pth}")/.recipients" +id_file="$(dirname "${_pth}")/${DPW_AGE_RECIPIENT_SUFFIX}" while true ; do # Break if id_file is above our password store directory @@ -56,22 +53,16 @@ while true ; do esac if [ -e "$id_file" ] ; then - keys="" - while read -r key ; do - if [ -z "$key" ] ; then continue ; fi - keys="$keys -r $key" - done < "$id_file" - - export DPW_AGE_RECIPIENTS="$keys" + export DPW_AGE_RECIPIENTS_FILE="$id_file" return fi # Pop this up a directory level for the next time 'round id_file="$(dirname "$id_file")" - id_file="$(dirname "$id_file")/.recipients" + id_file="$(dirname "$id_file")/${DPW_AGE_RECIPIENT_SUFFIX}" done -echo "No '.recipients' files found, is '$DPW_AGE_DIR' initialized?" +echo "No '${DPW_AGE_RECIPIENT_SUFFIX}' files found, is '$DPW_AGE_DIR' initialized?" exit 1 } @@ -90,7 +81,7 @@ pth="$1"; shift _set_age_recipients "$pth" mkdir -p "$DPW_AGE_DIR/$(dirname "$pth")" #shellcheck disable=SC2086 -age -e ${DPW_AGE_RECIPIENTS} \ +age -R "$DPW_AGE_RECIPIENTS_FILE" -e \ > "${DPW_AGE_DIR}/${pth}.age" _git_commit "Insert: $pth" } @@ -133,7 +124,7 @@ _git_commit "Remove: $*" _init_help() { cat <... +Usage: $0 init [--[no-]git] [--[no-]gen-key] [--[no-]pass] [-r ...] Git is the default. @@ -142,10 +133,14 @@ Gen key will generate a passphrase protected private key for you and place it in No pass disables the default for a passphrase protected key file -The key will automatically be added to the recipients list. +If generating a key it will automatically be added to the recipients list, +if not generating a key a recipient must be supplied. Multiple recipients may be specified +Init will also check that you can decrypt the secrets, otherwise it will fail. +( But not clean up after itself ) + See: https://github.com/FiloSottile/age for more information on 'age' itself. EOF exit 1 @@ -162,8 +157,10 @@ recipients= genkey=1 passphrase=1 while [ $# -gt 0 ] ; do case $1 in + --git) USE_GIT=1 ; shift ;; --no-git) USE_GIT=0 ; shift ;; --gen-key) genkey=1; shift ;; + --no-gen-key) genkey=0; shift ;; --pass) passphrase=1; shift ;; --no-pass) passphrase=0; shift ;; -r|--recipient) recipients="$recipients:$2"; shift ; shift ;; @@ -178,7 +175,7 @@ echo "genkey: $genkey passphrase: $passphrase" if [ $genkey -eq 1 ] && [ $passphrase -eq 1 ] ; then touch "${DPW_AGE_KEY}.pub" # Let the user's UMASK bet set umask 077 # but override it for the key - age-keygen 2>"${DPW_AGE_KEY}.pub" | age -p > "${DPW_AGE_KEY}" 2>&2 + age-keygen 2>"${DPW_AGE_KEY}.pub" | age --armor -p > "${DPW_AGE_KEY}" 2>&2 sed -i.bak -e's/^Public key: //g' "${DPW_AGE_KEY}.pub" rm "${DPW_AGE_KEY}.pub.bak" umask "$UMASK" @@ -187,12 +184,27 @@ elif [ $genkey -eq 1 ] ; then umask 077 # but override it for the key age-keygen >"${DPW_AGE_KEY}" sed -ne's/^# public key: //gp' < "${DPW_AGE_KEY}" > "${DPW_AGE_KEY}.pub" + cat < "${DPW_AGE_KEY}.pub" >> "${DPW_AGE_DIR}/${DPW_AGE_RECIPIENT_SUFFIX}" umask "$UMASK" fi +if [ $genkey -eq 1 ] ; then + recipients="$recipients:$(cat "${DPW_AGE_KEY}.pub")" +fi mkdir -p "${DPW_AGE_DIR}" cd "${DPW_AGE_DIR}" +DPW_AGE_RECIPIENTS_FILE="${DPW_AGE_DIR}/${DPW_AGE_RECIPIENT_SUFFIX}" +echo "$recipients" | tr ':' '\n' >> "${DPW_AGE_RECIPIENTS_FILE}" + +grep -q YUBIKEY "${DPW_AGE_KEY}" \ + && echo "Detected yubikey, you may need to tap it..." +# Test the key and recipients before we get too far along +tmpf="$(mktemp)" +echo "testing our key... works!" | age -R "${DPW_AGE_RECIPIENTS_FILE}" -e \ + > "$tmpf" +age -i "${DPW_AGE_KEY}" -d < "$tmpf" + if [ $USE_GIT -eq 1 ] ; then git init cat >> .git/config <> .gitattributes fi -cat < "${DPW_AGE_KEY}.pub" > "${DPW_AGE_DIR}/.recipients" -echo "$recipients" | tr ':' '\n' >> "${DPW_AGE_DIR}/.recipients" _git_commit echo "Age Password store initialized in ${DPW_AGE_DIR}" } +_help() { +cat <