171 lines
4.3 KiB
Bash
Executable File
171 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Euo pipefail
|
|
|
|
# Script to update sops keys for all secrets.yaml files in the project
|
|
# Uses .sops.yaml configuration to determine encryption keys
|
|
|
|
AGE_KEY_FILE=""
|
|
DRY_RUN=false
|
|
VERBOSE=false
|
|
|
|
# Parse options
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-k|--age-key-file)
|
|
AGE_KEY_FILE="$2"
|
|
shift 2
|
|
;;
|
|
-n|--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
-v|--verbose)
|
|
VERBOSE=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
cat <<EOF
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Updates sops encryption keys for all secrets.yaml files in the project.
|
|
Uses .sops.yaml configuration to determine which keys to use.
|
|
|
|
OPTIONS:
|
|
-k, --age-key-file PATH Path to age key file for decryption (default: uses SOPS_AGE_KEY_FILE env var)
|
|
-n, --dry-run Show which files would be updated without making changes
|
|
-v, --verbose Show detailed output
|
|
-h, --help Show this help message
|
|
|
|
EXAMPLES:
|
|
# Update all secrets using default age key
|
|
$0
|
|
|
|
# Use specific age key file
|
|
$0 --age-key-file ~/.config/sops/age/keys.txt
|
|
|
|
# Dry run to see which files would be updated
|
|
$0 --dry-run --verbose
|
|
|
|
ENVIRONMENT:
|
|
SOPS_AGE_KEY_FILE Default age key file location (if -k not specified)
|
|
EOF
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "ERROR: Unknown option: $1" >&2
|
|
echo "Use --help for usage information." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Check if 'sops' command is available
|
|
if ! command -v sops > /dev/null; then
|
|
echo "ERROR: 'sops' command not found. Please ensure it is installed and in your PATH." >&2
|
|
echo "Install with: nix-shell -p sops" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Determine the absolute directory where the script itself is located
|
|
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
PROJECT_ROOT=$(readlink -f "$SCRIPT_DIR/..")
|
|
|
|
# Check if .sops.yaml exists
|
|
SOPS_CONFIG="$PROJECT_ROOT/.sops.yaml"
|
|
if [ ! -f "$SOPS_CONFIG" ]; then
|
|
echo "ERROR: .sops.yaml not found at '$SOPS_CONFIG'" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Export age key file if provided
|
|
if [ -n "$AGE_KEY_FILE" ]; then
|
|
if [ ! -f "$AGE_KEY_FILE" ]; then
|
|
echo "ERROR: Age key file not found at '$AGE_KEY_FILE'" >&2
|
|
exit 1
|
|
fi
|
|
export SOPS_AGE_KEY_FILE="$AGE_KEY_FILE"
|
|
if [ "$VERBOSE" = true ]; then
|
|
echo "INFO: Using age key file: $AGE_KEY_FILE"
|
|
fi
|
|
elif [ -z "${SOPS_AGE_KEY_FILE:-}" ]; then
|
|
echo "WARNING: SOPS_AGE_KEY_FILE not set. You may not be able to decrypt secrets." >&2
|
|
echo " Use --age-key-file to specify a key file, or set SOPS_AGE_KEY_FILE environment variable." >&2
|
|
fi
|
|
|
|
# Find all secrets.yaml files
|
|
echo "INFO: Searching for secrets.yaml files in $PROJECT_ROOT..."
|
|
mapfile -t SECRET_FILES < <(find "$PROJECT_ROOT" -name "secrets.yaml" -type f | sort)
|
|
|
|
if [ ${#SECRET_FILES[@]} -eq 0 ]; then
|
|
echo "WARNING: No secrets.yaml files found in the project." >&2
|
|
exit 0
|
|
fi
|
|
|
|
echo "INFO: Found ${#SECRET_FILES[@]} secrets.yaml file(s)"
|
|
if [ "$VERBOSE" = true ] || [ "$DRY_RUN" = true ]; then
|
|
for file in "${SECRET_FILES[@]}"; do
|
|
relative_path="${file#$PROJECT_ROOT/}"
|
|
echo " - $relative_path"
|
|
done
|
|
fi
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
echo "INFO: Dry-run mode enabled. No files will be modified."
|
|
exit 0
|
|
fi
|
|
|
|
# Update keys for each file
|
|
UPDATED_COUNT=0
|
|
FAILED_COUNT=0
|
|
SKIPPED_COUNT=0
|
|
|
|
for file in "${SECRET_FILES[@]}"; do
|
|
relative_path="${file#$PROJECT_ROOT/}"
|
|
|
|
if [ "$VERBOSE" = true ]; then
|
|
echo "INFO: Updating keys for: $relative_path"
|
|
else
|
|
echo -n "Updating $relative_path... "
|
|
fi
|
|
|
|
# Check if file is encrypted with sops
|
|
if ! grep -q "^sops:" "$file" 2>/dev/null; then
|
|
echo "SKIP (not encrypted)"
|
|
((SKIPPED_COUNT++))
|
|
continue
|
|
fi
|
|
|
|
# Run sops updatekeys
|
|
if sops updatekeys --yes "$file" 2>&1 | {
|
|
if [ "$VERBOSE" = true ]; then
|
|
cat
|
|
else
|
|
grep -v "^$" || true
|
|
fi
|
|
}; then
|
|
if [ "$VERBOSE" != true ]; then
|
|
echo "OK"
|
|
fi
|
|
((UPDATED_COUNT++))
|
|
else
|
|
EXIT_STATUS=$?
|
|
echo "FAILED (exit code: $EXIT_STATUS)" >&2
|
|
((FAILED_COUNT++))
|
|
fi
|
|
done
|
|
|
|
# Summary
|
|
echo ""
|
|
echo "===== Summary ====="
|
|
echo "Total files found: ${#SECRET_FILES[@]}"
|
|
echo "Successfully updated: $UPDATED_COUNT"
|
|
echo "Failed: $FAILED_COUNT"
|
|
echo "Skipped: $SKIPPED_COUNT"
|
|
|
|
if [ $FAILED_COUNT -gt 0 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
echo "INFO: All secrets.yaml files have been updated successfully."
|
|
exit 0
|