#!/bin/bash # Configuration Encryption Setup Script # This script helps set up the encryption system for configuration values set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Default values ROOT_PATH="." CONFIG_FILE="" INTERACTIVE=false FORCE=false BACKUP=true ENVIRONMENT="production" # Function to print colored output print_color() { printf "${1}${2}${NC}\n" } print_success() { print_color "$GREEN" "✓ $1" } print_error() { print_color "$RED" "✗ $1" } print_warning() { print_color "$YELLOW" "⚠ $1" } print_info() { print_color "$BLUE" "ℹ $1" } # Function to show help show_help() { cat << EOF Configuration Encryption Setup Script This script helps you set up and manage the configuration encryption system for securing sensitive configuration values. Usage: $0 [OPTIONS] Options: -h, --help Show this help message -r, --root-path PATH Set root path for encryption key (default: .) -c, --config FILE Configuration file to encrypt values in -i, --interactive Run in interactive mode -f, --force Force overwrite existing encryption key -e, --environment ENV Environment (dev, staging, prod) (default: production) --no-backup Don't create backups when modifying files --verify-only Only verify existing encryption setup Examples: $0 # Basic setup with interactive prompts $0 -i # Full interactive setup $0 -c config.prod.toml # Encrypt values in specific config file $0 -r /app --environment prod # Setup for production in /app directory $0 --verify-only # Just verify current setup The script will: 1. Generate encryption key if it doesn't exist 2. Help you encrypt sensitive configuration values 3. Update configuration files with encrypted values 4. Verify the encryption setup works correctly Security Notes: - Never commit the .k file to version control - Use different keys for different environments - Backup encryption keys securely - Rotate keys regularly in production EOF } # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_help exit 0 ;; -r|--root-path) ROOT_PATH="$2" shift 2 ;; -c|--config) CONFIG_FILE="$2" shift 2 ;; -i|--interactive) INTERACTIVE=true shift ;; -f|--force) FORCE=true shift ;; -e|--environment) ENVIRONMENT="$2" shift 2 ;; --no-backup) BACKUP=false shift ;; --verify-only) VERIFY_ONLY=true shift ;; *) print_error "Unknown option: $1" show_help exit 1 ;; esac done # Check if we're in a Rust project if [ ! -f "Cargo.toml" ]; then print_error "This script must be run from the root of a Rust project" exit 1 fi # Check if the crypto tool is available if ! cargo bin --list | grep -q "config_crypto_tool"; then print_error "config_crypto_tool binary not found. Please ensure it's built:" print_info "cargo build --bin config_crypto_tool" exit 1 fi # Function to check if encryption key exists check_encryption_key() { if [ -f "$ROOT_PATH/.k" ]; then return 0 else return 1 fi } # Function to generate encryption key generate_encryption_key() { print_info "Generating encryption key..." if check_encryption_key && [ "$FORCE" = false ]; then print_warning "Encryption key already exists at $ROOT_PATH/.k" read -p "Do you want to overwrite it? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then print_info "Keeping existing encryption key" return 0 fi fi local force_flag="" if [ "$FORCE" = true ]; then force_flag="--force" fi if cargo run --bin config_crypto_tool -- --root-path "$ROOT_PATH" generate-key $force_flag; then print_success "Encryption key generated at $ROOT_PATH/.k" # Set proper permissions chmod 600 "$ROOT_PATH/.k" print_success "Set secure permissions on encryption key file" # Verify the key works if cargo run --bin config_crypto_tool -- --root-path "$ROOT_PATH" verify; then print_success "Encryption key verification successful" else print_error "Encryption key verification failed" return 1 fi else print_error "Failed to generate encryption key" return 1 fi } # Function to encrypt a value encrypt_value() { local value="$1" local description="$2" print_info "Encrypting $description..." if encrypted_value=$(cargo run --bin config_crypto_tool -- --root-path "$ROOT_PATH" encrypt "$value" 2>/dev/null); then echo "$encrypted_value" return 0 else print_error "Failed to encrypt $description" return 1 fi } # Function to show common values to encrypt show_common_values() { cat << EOF Common configuration values that should be encrypted: - Database passwords - Session secrets - API keys (SendGrid, OAuth providers, etc.) - SMTP passwords - Redis URLs with credentials - JWT secrets - Third-party service credentials EOF } # Function to encrypt values in configuration file encrypt_config_values() { local config_file="$1" if [ ! -f "$config_file" ]; then print_error "Configuration file not found: $config_file" return 1 fi print_info "Analyzing configuration file: $config_file" # Create backup if requested if [ "$BACKUP" = true ]; then local backup_file="${config_file}.backup.$(date +%Y%m%d_%H%M%S)" cp "$config_file" "$backup_file" print_success "Created backup: $backup_file" fi # Common sensitive keys that should be encrypted local sensitive_keys=( "session.secret" "database.url" "oauth.google.client_secret" "oauth.github.client_secret" "email.smtp_password" "email.sendgrid_api_key" "redis.url" ) print_info "Checking for sensitive values to encrypt..." for key in "${sensitive_keys[@]}"; do # Check if this key exists in the config and is not already encrypted if grep -q "^${key//./\\.}" "$config_file" 2>/dev/null; then # Extract the current value local current_value=$(grep "^${key//./\\.}" "$config_file" | cut -d'"' -f2) if [[ "$current_value" =~ ^\$\{.*\}$ ]]; then print_info "Skipping $key (uses environment variable)" continue elif [[ "$current_value" == @* ]]; then print_info "Skipping $key (already encrypted)" continue elif [ -n "$current_value" ] && [ "$current_value" != "your-secret-here" ]; then print_warning "Found potentially sensitive value for $key" if [ "$INTERACTIVE" = true ]; then read -p "Encrypt this value? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then if encrypted_value=$(encrypt_value "$current_value" "$key"); then # Update the configuration file sed -i.tmp "s|^${key//./\\.}.*|${key} = \"$encrypted_value\"|" "$config_file" rm -f "$config_file.tmp" print_success "Encrypted $key" fi fi fi fi fi done } # Function to verify encryption setup verify_encryption_setup() { print_info "Verifying encryption setup..." # Check if key exists if ! check_encryption_key; then print_error "Encryption key not found at $ROOT_PATH/.k" return 1 fi # Check key permissions if [ "$(stat -c %a "$ROOT_PATH/.k" 2>/dev/null)" != "600" ]; then print_warning "Encryption key file permissions are not secure" print_info "Setting secure permissions..." chmod 600 "$ROOT_PATH/.k" fi # Verify key works if cargo run --bin config_crypto_tool -- --root-path "$ROOT_PATH" verify; then print_success "Encryption key verification successful" else print_error "Encryption key verification failed" return 1 fi # Check if .k is in .gitignore if [ -f ".gitignore" ]; then if grep -q "^\.k$" ".gitignore" || grep -q "^\.k " ".gitignore"; then print_success "Encryption key is properly ignored in .gitignore" else print_error "Encryption key is NOT in .gitignore - this is a security risk!" read -p "Add .k to .gitignore? (Y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Nn]$ ]]; then echo ".k" >> .gitignore print_success "Added .k to .gitignore" fi fi else print_warning ".gitignore file not found" fi return 0 } # Function to run interactive setup run_interactive_setup() { print_info "Starting interactive encryption setup..." echo # Step 1: Generate or verify encryption key if check_encryption_key; then print_success "Encryption key already exists" read -p "Do you want to verify it? (Y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Nn]$ ]]; then verify_encryption_setup fi else print_info "No encryption key found" read -p "Generate new encryption key? (Y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Nn]$ ]]; then generate_encryption_key fi fi echo # Step 2: Encrypt individual values print_info "You can now encrypt individual values:" while true; do read -p "Enter a value to encrypt (or 'skip' to continue): " value if [ "$value" = "skip" ] || [ -z "$value" ]; then break fi if encrypted_value=$(encrypt_value "$value" "custom value"); then print_success "Encrypted value: $encrypted_value" echo "Use this in your configuration file:" echo "some_key = \"$encrypted_value\"" fi echo done # Step 3: Encrypt configuration file values if [ -n "$CONFIG_FILE" ]; then print_info "Encrypting values in configuration file: $CONFIG_FILE" encrypt_config_values "$CONFIG_FILE" else echo print_info "Available configuration files:" for file in config*.toml; do if [ -f "$file" ]; then echo " - $file" fi done read -p "Enter configuration file to encrypt values in (or 'skip'): " config_file if [ "$config_file" != "skip" ] && [ -n "$config_file" ]; then encrypt_config_values "$config_file" fi fi echo print_success "Interactive setup completed!" } # Function to show security recommendations show_security_recommendations() { cat << EOF ${GREEN}Security Recommendations:${NC} 1. ${YELLOW}Never commit the .k file to version control${NC} - The .k file contains your encryption key - Add it to .gitignore immediately - Use different keys for different environments 2. ${YELLOW}Backup your encryption keys securely${NC} - Store backups in a secure, separate location - Consider using encrypted backup storage - Document your backup procedures 3. ${YELLOW}Use proper file permissions${NC} - Key files should be readable only by the application user - Use chmod 600 for the .k file - Monitor file access regularly 4. ${YELLOW}Rotate keys regularly${NC} - Consider quarterly or yearly key rotation - Have a key rotation procedure documented - Test key rotation in staging first 5. ${YELLOW}Monitor and audit${NC} - Log encryption/decryption operations - Monitor key file access - Regular security audits 6. ${YELLOW}Environment separation${NC} - Use different encryption keys for dev/staging/prod - Never use production keys in development - Secure key distribution procedures EOF } # Main execution main() { echo print_info "Configuration Encryption Setup Script" print_info "Environment: $ENVIRONMENT" print_info "Root Path: $ROOT_PATH" echo # Change to root path cd "$ROOT_PATH" # Verify-only mode if [ "$VERIFY_ONLY" = true ]; then verify_encryption_setup exit $? fi # Interactive mode if [ "$INTERACTIVE" = true ]; then run_interactive_setup echo show_security_recommendations exit 0 fi # Non-interactive mode print_info "Running automated setup..." # Generate encryption key if it doesn't exist if ! check_encryption_key; then generate_encryption_key else print_success "Encryption key already exists" verify_encryption_setup fi # Encrypt configuration file if specified if [ -n "$CONFIG_FILE" ]; then encrypt_config_values "$CONFIG_FILE" fi echo print_success "Encryption setup completed!" # Show next steps cat << EOF ${GREEN}Next Steps:${NC} 1. Test your configuration: cargo run --bin config_crypto_tool verify 2. Encrypt sensitive values: cargo run --bin config_crypto_tool encrypt "your-secret" 3. Update your configuration files with encrypted values 4. Ensure .k file is in .gitignore 5. Backup your encryption key securely ${BLUE}Useful Commands:${NC} - Encrypt value: cargo run --bin config_crypto_tool encrypt "value" - Decrypt value: cargo run --bin config_crypto_tool decrypt "@encrypted" - Find encrypted values: cargo run --bin config_crypto_tool find-encrypted -c config.toml - Interactive mode: cargo run --bin config_crypto_tool interactive EOF show_security_recommendations } # Run main function main "$@"