From a995c0d606cb3f7b31dc8d4c8aac211eeb08739b Mon Sep 17 00:00:00 2001 From: Joshua McQuistan Date: Fri, 19 Jul 2024 11:11:24 +0100 Subject: [PATCH] Add -c option to create or replace a file without decrypting it first --- pkgs/agenix.nix | 1 + pkgs/agenix.sh | 32 +++++++++++++++++++++++++++----- test/integration.nix | 4 ++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/pkgs/agenix.nix b/pkgs/agenix.nix index e51a5c6..3c0bfaf 100644 --- a/pkgs/agenix.nix +++ b/pkgs/agenix.nix @@ -55,6 +55,7 @@ in ) cd $HOME/secrets + echo hello | ${bin} -c secret1.age test $(${bin} -d secret1.age) = "hello" ''; diff --git a/pkgs/agenix.sh b/pkgs/agenix.sh index 3d0415e..ba71050 100644 --- a/pkgs/agenix.sh +++ b/pkgs/agenix.sh @@ -6,12 +6,15 @@ PACKAGE="agenix" function show_help () { echo "$PACKAGE - edit and rekey age secret files" echo " " + echo "$PACKAGE -c FILE" echo "$PACKAGE -e FILE [-i PRIVATE_KEY]" echo "$PACKAGE -r [-i PRIVATE_KEY]" echo ' ' echo 'options:' echo '-h, --help show help' # shellcheck disable=SC2016 + echo '-c, --create FILE create or replace FILE using $EDITOR' + # shellcheck disable=SC2016 echo '-e, --edit FILE edits FILE using $EDITOR' echo '-r, --rekey re-encrypts all secrets with specified recipients' echo '-d, --decrypt FILE decrypts FILE to STDOUT' @@ -46,6 +49,7 @@ function err() { test $# -eq 0 && (show_help && exit 1) REKEY=0 +ENCRYPT_ONLY=0 DECRYPT_ONLY=0 DEFAULT_DECRYPT=(--decrypt) @@ -55,6 +59,17 @@ while test $# -gt 0; do show_help exit 0 ;; + -c|--create) + shift + ENCRYPT_ONLY=1 + if test $# -gt 0; then + export FILE=$1 + else + echo "no FILE specified" + exit 1 + fi + shift + ;; -e|--edit) shift if test $# -gt 0; then @@ -153,22 +168,29 @@ function edit { CLEARTEXT_FILE="$CLEARTEXT_DIR/$(basename "$FILE")" DEFAULT_DECRYPT+=(-o "$CLEARTEXT_FILE") - decrypt "$FILE" "$KEYS" || exit 1 - - [ ! -f "$CLEARTEXT_FILE" ] || cp "$CLEARTEXT_FILE" "$CLEARTEXT_FILE.before" + # Decrypt file + if [ $ENCRYPT_ONLY -eq 0 ] + then + decrypt "$FILE" "$KEYS" || exit 1 + [ ! -f "$CLEARTEXT_FILE" ] || cp "$CLEARTEXT_FILE" "$CLEARTEXT_FILE.before" + else + touch "$CLEARTEXT_FILE.before" + fi + # Prompt file edit [ -t 0 ] || EDITOR='cp /dev/stdin' - $EDITOR "$CLEARTEXT_FILE" + # Check file status if [ ! -f "$CLEARTEXT_FILE" ] then warn "$FILE wasn't created." return fi - [ -f "$FILE" ] && [ "$EDITOR" != ":" ] && @diffBin@ -q "$CLEARTEXT_FILE.before" "$CLEARTEXT_FILE" && warn "$FILE wasn't changed, skipping re-encryption." && return + [ $ENCRYPT_ONLY -eq 0 ] && [ -f "$FILE" ] && [ "$EDITOR" != ":" ] && @diffBin@ -q "$CLEARTEXT_FILE.before" "$CLEARTEXT_FILE" && warn "$FILE wasn't changed, skipping re-encryption." && return ENCRYPT=() + # Build recipient list while IFS= read -r key do if [ -n "$key" ]; then diff --git a/test/integration.nix b/test/integration.nix index e0ee85a..3e92d32 100644 --- a/test/integration.nix +++ b/test/integration.nix @@ -120,6 +120,10 @@ pkgs.nixosTest { # and get it back out via --decrypt assert "secret1234" in system1.succeed(userDo("agenix -d passwordfile-user1.age")) + # user1 can recreate the secret without decrypting it + system1.succeed(userDo("echo 'secret5678' | agenix -c passwordfile-user1.age")) + assert "secret5678" in system1.succeed(userDo("agenix -d passwordfile-user1.age")) + # finally, the plain text should not linger around anywhere in the filesystem. system1.fail("grep -r secret1234 /tmp") '';