#!/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 <&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