aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Riedstra <mitch@riedstra.dev>2025-12-12 17:43:17 -0500
committerMitchell Riedstra <mitch@riedstra.dev>2025-12-12 17:43:17 -0500
commita6da233005cef270e65bcdae9c6bbc58d5bdf0e3 (patch)
treea6e057be5816f51fa12b8cf6a8f2967e91980c96
parentcc9c098a7b42abbcc1fad9f59d1cc436deba5c9e (diff)
downloaddpw-a6da233005cef270e65bcdae9c6bbc58d5bdf0e3.tar.gz
dpw-a6da233005cef270e65bcdae9c6bbc58d5bdf0e3.tar.xz
Update the 'age' backend to be a bit more user friendly
-rwxr-xr-xdpw-age81
1 files changed, 58 insertions, 23 deletions
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 <<EOF
-Usage: $0 [--no-git] [--gen-key] [--[no-]pass] <recipients>...
+Usage: $0 init [--[no-]git] [--[no-]gen-key] [--[no-]pass] [-r <recipient>...]
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 <<EOF
@@ -200,18 +212,41 @@ if [ $USE_GIT -eq 1 ] ; then
binary = true
textconv = age --decrypt -i "${DPW_AGE_KEY}"
EOF
+ cp .git/config gitconfig
echo "*.age diff=age" >> .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 <<EOF
+Usage: $0 [command] [args]
+
+Where command may be one of:
+ show
+ list
+ insert
+ rm
+ init
+
+The 'init' command has its own help page.
+
+dpw-age is influnced by the following enviornment variables:
+
+DPW_AGE_DIR="${DPW_AGE_DIR}"
+DPW_AGE_KEY="${DPW_AGE_KEY}
+DPW_AGE_RECIPIENT_SUFFIX="${DPW_AGE_RECIPIENT_SUFFIX}"
+PASSWORD_STORE_UMASK="${UMASK}"
+
+If the above are unset, defaults are shown.
+EOF
+}
+
act="$1"; shift
case $act in
show) show "$@" ;;
@@ -219,5 +254,5 @@ case $act in
insert) insert "$@" ;;
rm) remove "$@" ;;
init) _init "$@" ;;
- *) echo "Bad command $act"; exit 1; ;;
+ *) _help; echo "Bad command $act"; exit 1; ;;
esac