Files
roa2web-service-auto/scripts/restore-secrets.sh
Marius Mutu 60346ff7da Add encrypted secrets backup and restore utilities
Implements secure backup system for environment configuration files (.env, .env.prod)
containing sensitive credentials using AES-256-CBC encryption with OpenSSL.

New utilities:
- scripts/backup-secrets.sh: Encrypts and backs up all .env files to timestamped directory
- scripts/restore-secrets.sh: Decrypts and restores .env files from backup
- scripts/README.md: Complete documentation with usage examples and best practices

Features:
- AES-256-CBC encryption with PBKDF2 key derivation (strong encryption)
- Interactive password prompts with confirmation
- Non-interactive mode via BACKUP_PASSWORD environment variable
- Automatic README generation in each backup with restore instructions
- Color-coded output for better UX
- Validation and error handling

Backup structure:
secrets-backup/
└── YYYY-MM-DD_HH-MM-SS/
    ├── backend-.env.enc
    ├── backend-.env.prod.enc
    ├── telegram-bot-.env.enc
    ├── telegram-bot-.env.prod.enc
    └── README.md

Updated .gitignore to allow committing encrypted .gpg/.enc files while
blocking decrypted .env files in secrets-backup directory.

Usage:
./scripts/backup-secrets.sh                    # Create encrypted backup
./scripts/restore-secrets.sh [backup-date]     # Restore from backup

Tested with OpenSSL (pre-installed on most systems). Provides secure way to
version control and sync credentials across development and production environments.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 12:36:43 +02:00

159 lines
4.5 KiB
Bash

#!/bin/bash
# ============================================================================
# ROA2WEB - Restore Environment Secrets (From Encrypted Backup)
# ============================================================================
# This script restores .env files from encrypted backups
# Usage:
# ./scripts/restore-secrets.sh [backup-date] # Interactive (prompts for password)
# BACKUP_PASSWORD="your-pass" ./scripts/restore-secrets.sh [backup-date] # Non-interactive
#
# Example: ./scripts/restore-secrets.sh 2025-01-15_10-30-00
# ./scripts/restore-secrets.sh (uses latest backup)
set -e
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}=== ROA2WEB Secrets Restore Tool ===${NC}"
echo ""
# Check if openssl is installed
if ! command -v openssl &> /dev/null; then
echo -e "${RED}Error: openssl is not installed${NC}"
echo "Install with: sudo apt-get install openssl"
exit 1
fi
# Check if secrets-backup directory exists
if [ ! -d "secrets-backup" ]; then
echo -e "${RED}Error: No backups found${NC}"
echo "Run ./scripts/backup-secrets.sh first"
exit 1
fi
# Determine which backup to use
if [ -z "$1" ]; then
# Use latest backup
BACKUP_DATE=$(ls -t secrets-backup | head -1)
echo -e "${YELLOW}Using latest backup: ${BACKUP_DATE}${NC}"
else
BACKUP_DATE="$1"
echo -e "${YELLOW}Using specified backup: ${BACKUP_DATE}${NC}"
fi
BACKUP_DIR="secrets-backup/${BACKUP_DATE}"
# Check if backup exists
if [ ! -d "$BACKUP_DIR" ]; then
echo -e "${RED}Error: Backup not found: ${BACKUP_DIR}${NC}"
echo ""
echo "Available backups:"
ls -1 secrets-backup
exit 1
fi
echo ""
echo -e "${BLUE}Backup location: ${BACKUP_DIR}${NC}"
echo ""
# List encrypted files in backup
ENCRYPTED_FILES=()
for file in "${BACKUP_DIR}"/*.enc; do
if [ -f "$file" ]; then
ENCRYPTED_FILES+=("$file")
fi
done
if [ ${#ENCRYPTED_FILES[@]} -eq 0 ]; then
echo -e "${RED}Error: No encrypted files found in backup${NC}"
exit 1
fi
echo "Found ${#ENCRYPTED_FILES[@]} encrypted file(s):"
for file in "${ENCRYPTED_FILES[@]}"; do
echo " - $(basename "$file")"
done
echo ""
# Ask for confirmation
echo -e "${YELLOW}⚠️ This will overwrite existing .env files!${NC}"
read -p "Continue? (y/N): " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Restore cancelled"
exit 0
fi
# Get password
if [ -z "$BACKUP_PASSWORD" ]; then
echo ""
echo -e "${YELLOW}Enter decryption password:${NC}"
read -s BACKUP_PASSWORD
echo ""
if [ -z "$BACKUP_PASSWORD" ]; then
echo -e "${RED}Error: Password cannot be empty${NC}"
exit 1
fi
fi
echo ""
# Counter for restored files
RESTORED=0
FAILED=0
# Restore each file
for encrypted_file in "${ENCRYPTED_FILES[@]}"; do
filename=$(basename "$encrypted_file" .enc)
# Determine target path based on filename
if [[ "$filename" == "backend-.env" ]]; then
target="reports-app/backend/.env"
elif [[ "$filename" == "backend-.env.prod" ]]; then
target="reports-app/backend/.env.prod"
elif [[ "$filename" == "telegram-bot-.env" ]]; then
target="reports-app/telegram-bot/.env"
elif [[ "$filename" == "telegram-bot-.env.prod" ]]; then
target="reports-app/telegram-bot/.env.prod"
else
echo -e "${YELLOW}Skipping unknown file: $filename${NC}"
continue
fi
echo -e "Decrypting: ${GREEN}$filename${NC}"
echo -e " Target: $target"
# Create target directory if needed
mkdir -p "$(dirname "$target")"
# Decrypt
if echo "$BACKUP_PASSWORD" | openssl enc -aes-256-cbc -d -pbkdf2 \
-in "$encrypted_file" -out "$target" -pass stdin 2>/dev/null; then
echo -e " ✅ Restored successfully"
RESTORED=$((RESTORED + 1))
else
echo -e " ${RED}❌ Failed to decrypt (wrong password?)${NC}"
FAILED=$((FAILED + 1))
fi
echo ""
done
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [ $FAILED -eq 0 ]; then
echo -e "${GREEN}✅ Restore completed successfully${NC}"
else
echo -e "${YELLOW}⚠️ Restore completed with errors${NC}"
fi
echo ""
echo "📊 Summary:"
echo " - Restored: ${RESTORED} files"
echo " - Failed: ${FAILED} files"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"