agenix/pkgs/agenix.nix

136 lines
3.0 KiB
Nix

{writeShellScriptBin, runtimeShell, age, yq-go} :
writeShellScriptBin "agenix" ''
set -euo pipefail
PACKAGE="agenix"
function show_help () {
echo "$PACKAGE - edit and rekey age secret files"
echo " "
echo "$PACKAGE -e FILE [-i PRIVATE_KEY]"
echo "$PACKAGE -r [-i PRIVATE_KEY]"
echo ' '
echo 'options:'
echo '-h, --help show help'
echo '-e, --edit FILE edits FILE using $EDITOR'
echo '-r, --rekey re-encrypts all secrets with specified recipients'
echo '-i, --identity identity to use when decrypting'
echo ' '
echo 'FILE an age-encrypted file'
echo ' '
echo 'PRIVATE_KEY a path to a private SSH key used to decrypt file'
echo ' '
echo 'EDITOR environment variable of editor to use when editing FILE'
echo ' '
echo 'RULES environment variable with path to YAML file specifying recipient public keys.'
echo "Defaults to 'secrets.yaml'"
}
test $# -eq 0 && (show_help && exit 1)
REKEY=0
DECRYPT=(--decrypt)
while test $# -gt 0; do
case "$1" in
-h|--help)
show_help
exit 0
;;
-e|--edit)
shift
if test $# -gt 0; then
export FILE=$1
else
echo "no FILE specified"
exit 1
fi
shift
;;
-i|--identity)
shift
if test $# -gt 0; then
DECRYPT+=(--identity "$1")
else
echo "no PRIVATE_KEY specified"
exit 1
fi
shift
;;
-r|--rekey)
shift
REKEY=1
;;
*)
show_help
exit 1
;;
esac
done
RULES=''${RULES:-secrets.yaml}
function cleanup {
if [ ! -z ''${CLEARTEXT_DIR+x} ]
then
rm -rf "$CLEARTEXT_DIR"
fi
if [ ! -z ''${REENCRYPTED_DIR+x} ]
then
rm -rf "$REENCRYPTED_DIR"
fi
}
trap "cleanup" 0 2 3 15
function edit {
FILE=$1
KEYS=$(${yq-go}/bin/yq r "$RULES" "secrets.(name==$FILE).public_keys.**")
if [ -z "$KEYS" ]
then
>&2 echo "There is no rule for $FILE in $RULES."
exit 1
fi
CLEARTEXT_DIR=$(mktemp -d)
CLEARTEXT_FILE="$CLEARTEXT_DIR/$(basename "$FILE")"
if [ -f "$FILE" ]
then
while IFS= read -r key
do
DECRYPT+=(--identity "$key")
done <<<$(find ~/.ssh -maxdepth 1 -type f -not -name "*pub" -not -name "config" -not -name "authorized_keys" -not -name "known_hosts")
DECRYPT+=(-o "$CLEARTEXT_FILE" "$FILE")
${age}/bin/age "''${DECRYPT[@]}"
fi
$EDITOR "$CLEARTEXT_FILE"
ENCRYPT=()
while IFS= read -r key
do
ENCRYPT+=(--recipient "$key")
done <<< "$KEYS"
REENCRYPTED_DIR=$(mktemp -d)
REENCRYPTED_FILE="$REENCRYPTED_DIR/$(basename "$FILE")"
ENCRYPT+=(-o "$REENCRYPTED_FILE")
cat "$CLEARTEXT_FILE" | ${age}/bin/age "''${ENCRYPT[@]}"
mv -f "$REENCRYPTED_FILE" "$1"
}
function rekey {
echo "rekeying..."
FILES=$(${yq-go}/bin/yq r "$RULES" "secrets.*.name")
for FILE in $FILES
do
EDITOR=: edit $FILE
done
}
[ $REKEY -eq 1 ] && rekey && exit 0
edit $FILE && exit 0
''