improve script to recursively decrypt everything if able to

This commit is contained in:
Mark Kaulertz 2025-06-20 10:41:20 +02:00
parent 536831f8d9
commit 0bb416984d
3 changed files with 52 additions and 32 deletions

View File

@ -4,6 +4,12 @@ FROM alpine:latest
# Install only the tools we need: SOPS and GnuPG # Install only the tools we need: SOPS and GnuPG
RUN apk add --no-cache sops gnupg RUN apk add --no-cache sops gnupg
# Create the .gnupg directory with correct permissions first
RUN mkdir -m 700 /root/.gnupg
# Copy our GPG agent config file into the image
COPY gpg.conf /root/.gnupg/gpg.conf
# Set a working directory # Set a working directory
WORKDIR /app WORKDIR /app

View File

@ -1,54 +1,66 @@
#!/bin/sh #!/bin/sh
# Exit immediately if any command fails
set -e set -e
# --- Configuration (from Environment Variables) --- # --- Configuration (from Environment Variables) ---
# Use ':-' to set a default value if the variable is unset or null.
APP_NAME="${APP_NAME:-sops-init}" APP_NAME="${APP_NAME:-sops-init}"
GPG_KEY_PATH="${GPG_KEY_PATH:-/run/secrets/gpg_key}" GPG_KEY_PATH="${GPG_KEY_PATH:-/run/secrets/gpg_key}"
GPG_PASSPHRASE_PATH="${GPG_PASSPHRASE_PATH}"
# The directory containing encrypted files.
SOPS_INPUT_DIR="${SOPS_INPUT_DIR:-/config_in}" SOPS_INPUT_DIR="${SOPS_INPUT_DIR:-/config_in}"
# The directory where decrypted files will be written.
SOPS_OUTPUT_DIR="${SOPS_OUTPUT_DIR:-/config_out}" SOPS_OUTPUT_DIR="${SOPS_OUTPUT_DIR:-/config_out}"
# The suffix of files to search for.
SOPS_FILE_SUFFIX="${SOPS_FILE_SUFFIX:-.sops.yaml}"
# --- Script Logic --- # --- Script Logic ---
echo "$APP_NAME: Decryption container started." echo "$APP_NAME: Configuration materializer started."
echo "➡️ $APP_NAME: Input Dir: '$SOPS_INPUT_DIR', Output Dir: '$SOPS_OUTPUT_DIR', Suffix: '$SOPS_FILE_SUFFIX'" echo "➡️ $APP_NAME: Input Dir: '$SOPS_INPUT_DIR', Output Dir: '$SOPS_OUTPUT_DIR'"
# --- GPG Key Import and Unlocking ---
# (This section is unchanged as it is working correctly)
echo "🔄 $APP_NAME: Starting GPG Agent..."
unset GPG_AGENT_INFO
eval $(gpg-agent --daemon --pinentry-mode loopback)
# Validate that the required files/directories exist
if [ ! -f "$GPG_KEY_PATH" ]; then if [ ! -f "$GPG_KEY_PATH" ]; then
echo "$APP_NAME: ERROR: GPG secret key not found at '$GPG_KEY_PATH'" echo "$APP_NAME: ERROR: GPG secret key not found at '$GPG_KEY_PATH'"
exit 1 exit 1
fi fi
if [ ! -d "$SOPS_INPUT_DIR" ]; then
echo "$APP_NAME: ERROR: Input directory not found at '$SOPS_INPUT_DIR'"
exit 1
fi
# Ensure the output directory exists
mkdir -p "$SOPS_OUTPUT_DIR"
echo "🔐 $APP_NAME: Importing GPG private key..." echo "🔐 $APP_NAME: Importing GPG private key..."
gpg --batch --import "$GPG_KEY_PATH" gpg --batch --import "$GPG_KEY_PATH"
echo "🔎 $APP_NAME: Searching for files ending in '$SOPS_FILE_SUFFIX'..." if [ -n "$GPG_PASSPHRASE_PATH" ]; then
if [ ! -f "$GPG_PASSPHRASE_PATH" ]; then
echo "$APP_NAME: ERROR: GPG passphrase file not found at '$GPG_PASSPHRASE_PATH'"
exit 1
fi
echo "🔑 $APP_NAME: Unlocking key to cache passphrase with GPG Agent..."
KEY_FINGERPRINT=$(gpg --with-colons --import-options import-show --import < "$GPG_KEY_PATH" | awk -F: '/^sec:/ { print $5 }')
if [ -z "$KEY_FINGERPRINT" ]; then
echo "$APP_NAME: Could not determine GPG key fingerprint from key file."
exit 1
fi
echo " - Unlocking key with fingerprint: $KEY_FINGERPRINT"
echo "test" | gpg --quiet --batch --pinentry-mode loopback --passphrase-file "$GPG_PASSPHRASE_PATH" --sign -u "$KEY_FINGERPRINT" > /dev/null
echo " - Key unlocked and passphrase cached successfully."
fi
# Use 'find' to locate all target files and loop through them
find "$SOPS_INPUT_DIR" -type f -name "*${SOPS_FILE_SUFFIX}" | while read -r encrypted_file; do
# Get the filename without the full path
base_filename_with_suffix=$(basename "$encrypted_file")
# Remove the suffix to get the clean output filename
output_filename=$(basename "$encrypted_file" "$SOPS_FILE_SUFFIX")
# Construct the full output path
decrypted_file="${SOPS_OUTPUT_DIR}/${output_filename}"
echo " - Decrypting '$base_filename_with_suffix' to '$decrypted_file'" # --- File Processing Loop ---
sops --decrypt "$encrypted_file" > "$decrypted_file" echo "🔎 $APP_NAME: Processing all files in '$SOPS_INPUT_DIR'..."
# Find ALL files (-type f) in the input directory
find "$SOPS_INPUT_DIR" -type f | while read -r source_file; do
relative_path="${source_file#$SOPS_INPUT_DIR/}"
destination_file="${SOPS_OUTPUT_DIR}/${relative_path}"
# Ensure the destination directory exists
mkdir -p "$(dirname "$destination_file")"
# Attempt to decrypt the file. Redirect stderr to /dev/null to keep logs clean.
if sops --decrypt "$source_file" > "$destination_file" 2>/dev/null; then
# If decryption succeeds, log it.
echo " decrypted ✅ $relative_path"
else
# If decryption fails, it's not a SOPS file. Copy it verbatim instead.
echo " copied ↪️ $relative_path"
cp "$source_file" "$destination_file"
fi
done done
echo "🎉 $APP_NAME: All files decrypted. Exiting." echo "🎉 $APP_NAME: All files processed. Exiting."

2
gpg.conf Normal file
View File

@ -0,0 +1,2 @@
use-agent
pinentry-mode loopback