generated from coulomb/repo-seed
105 lines
3.2 KiB
Bash
Executable File
105 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# encrypt-secrets.sh — encrypt secrets/ directory to secrets.enc/ using age
|
|
#
|
|
# Usage:
|
|
# ./encrypt-secrets.sh [SECRETS_DIR] [AGE_RECIPIENT_OR_KEY_FILE]
|
|
#
|
|
# SECRETS_DIR plaintext secrets directory (default: ./secrets)
|
|
# AGE_RECIPIENT_OR_KEY_FILE age public key, public-key file, or private-key
|
|
# file with public-key comment
|
|
# (default: ~/.config/net-kingdom/age.key)
|
|
#
|
|
# Encrypts each *.env file (and pi.enc if present) to
|
|
# secrets.enc/<component>/<filename>.age. Prefer passing a public age recipient
|
|
# for normal bootstrap; the private key is needed only for decrypt/apply.
|
|
#
|
|
# After a successful encrypt, shreds the plaintext secrets directory unless
|
|
# --no-shred is passed.
|
|
#
|
|
# Run after gen-secrets.sh to store secrets safely in the repo.
|
|
# Commit secrets.enc/ to git.
|
|
|
|
set -euo pipefail
|
|
|
|
SECRETS_DIR="${1:-./secrets}"
|
|
AGE_RECIPIENT_OR_KEY="${2:-$HOME/.config/net-kingdom/age.key}"
|
|
NO_SHRED=false
|
|
for arg in "$@"; do [[ "$arg" == "--no-shred" ]] && NO_SHRED=true; done
|
|
|
|
if [[ ! -d "$SECRETS_DIR" ]]; then
|
|
echo "ERROR: secrets directory not found: $SECRETS_DIR" >&2
|
|
echo "Run gen-secrets.sh first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
resolve_recipient() {
|
|
local source="$1"
|
|
if [[ "$source" == age1* ]]; then
|
|
printf '%s\n' "$source"
|
|
return 0
|
|
fi
|
|
if [[ ! -f "$source" ]]; then
|
|
echo "ERROR: age recipient/key file not found: $source" >&2
|
|
echo "Pass an age public recipient such as age1... or a file containing it." >&2
|
|
return 1
|
|
fi
|
|
local recipient
|
|
recipient=$(grep -m1 '^age1' "$source" || true)
|
|
if [[ -n "$recipient" ]]; then
|
|
printf '%s\n' "$recipient"
|
|
return 0
|
|
fi
|
|
recipient=$(grep -m1 'public key:' "$source" | awk '{print $NF}' || true)
|
|
if [[ -n "$recipient" ]]; then
|
|
printf '%s\n' "$recipient"
|
|
return 0
|
|
fi
|
|
if grep -q 'AGE-SECRET-KEY-1' "$source"; then
|
|
recipient=$(age-keygen -y "$source" 2>/dev/null || true)
|
|
if [[ -n "$recipient" ]]; then
|
|
printf '%s\n' "$recipient"
|
|
return 0
|
|
fi
|
|
fi
|
|
echo "ERROR: could not resolve an age public recipient from $source" >&2
|
|
return 1
|
|
}
|
|
|
|
PUBKEY=$(resolve_recipient "$AGE_RECIPIENT_OR_KEY")
|
|
|
|
ENC_DIR="$(dirname "$SECRETS_DIR")/secrets.enc"
|
|
mkdir -p "$ENC_DIR"
|
|
|
|
echo "Encrypting secrets → $ENC_DIR/"
|
|
echo "Recipient: $PUBKEY"
|
|
echo ""
|
|
|
|
count=0
|
|
for component_dir in "$SECRETS_DIR"/*/; do
|
|
component=$(basename "$component_dir")
|
|
mkdir -p "$ENC_DIR/$component"
|
|
for f in "$component_dir"*; do
|
|
[[ -f "$f" ]] || continue
|
|
fname=$(basename "$f")
|
|
out="$ENC_DIR/$component/$fname.age"
|
|
age -r "$PUBKEY" -o "$out" "$f"
|
|
echo " encrypted: $component/$fname → secrets.enc/$component/$fname.age"
|
|
count=$((count + 1))
|
|
done
|
|
done
|
|
|
|
echo ""
|
|
echo "$count file(s) encrypted to $ENC_DIR/"
|
|
echo ""
|
|
|
|
if [[ "$NO_SHRED" == false ]]; then
|
|
echo "Shredding plaintext secrets..."
|
|
find "$SECRETS_DIR" -type f -exec shred -u {} \;
|
|
rm -rf "$SECRETS_DIR"
|
|
echo "Done. Plaintext secrets shredded."
|
|
else
|
|
echo "(--no-shred: plaintext kept at $SECRETS_DIR)"
|
|
fi
|
|
echo ""
|
|
echo "Next: commit secrets.enc/ to git."
|