#!/bin/bash # Test script for configuration encryption system # This script tests the encryption/decryption functionality 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 # Test configuration TEST_DIR="$(mktemp -d)" TEST_VALUES=( "simple_password123" "complex_password_with_special_chars!@#$%^&*()" "database_url_postgresql://user:pass@localhost:5432/db" "sendgrid_api_key_SG.1234567890abcdef" "session_secret_very_long_random_string_for_sessions" "oauth_client_secret_github_oauth_app_secret" "redis_url_redis://user:pass@redis.example.com:6379/0" "jwt_secret_super_secret_jwt_signing_key" "smtp_password_app_specific_password_for_gmail" "encryption_test_value_with_unicode_chars_áéíóú" ) TOTAL_TESTS=0 PASSED_TESTS=0 FAILED_TESTS=0 # Function to print colored output print_color() { printf "${1}${2}${NC}\n" } print_success() { print_color "$GREEN" "✓ $1" ((PASSED_TESTS++)) } print_error() { print_color "$RED" "✗ $1" ((FAILED_TESTS++)) } print_warning() { print_color "$YELLOW" "⚠ $1" } print_info() { print_color "$BLUE" "ℹ $1" } # Function to run a test run_test() { local test_name="$1" local test_command="$2" ((TOTAL_TESTS++)) print_info "Running test: $test_name" if eval "$test_command"; then print_success "$test_name" return 0 else print_error "$test_name" return 1 fi } # Function to cleanup cleanup() { if [ -d "$TEST_DIR" ]; then rm -rf "$TEST_DIR" print_info "Cleaned up test directory: $TEST_DIR" fi } # Set up cleanup trap trap cleanup EXIT # Test 1: Check if crypto tool is available test_crypto_tool_available() { cargo bin --list | grep -q "config_crypto_tool" } # Test 2: Generate encryption key test_generate_key() { cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" generate-key --force > /dev/null 2>&1 } # Test 3: Verify key exists and has correct permissions test_key_file_permissions() { local key_file="$TEST_DIR/.k" [ -f "$key_file" ] && [ "$(stat -c %a "$key_file" 2>/dev/null || stat -f %A "$key_file" 2>/dev/null)" = "600" ] } # Test 4: Verify encryption key works test_verify_key() { cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" verify > /dev/null 2>&1 } # Test 5: Basic encryption/decryption test_basic_encryption() { local test_value="test_encryption_value_123" local encrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) local decrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted" 2>/dev/null) [ "$decrypted" = "$test_value" ] } # Test 6: Encryption produces different outputs for same input test_encryption_randomness() { local test_value="randomness_test_value" local encrypted1=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) local encrypted2=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) [ "$encrypted1" != "$encrypted2" ] } # Test 7: Encrypted values start with @ test_encrypted_format() { local test_value="format_test_value" local encrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) [[ "$encrypted" == @* ]] } # Test 8: Multiple values encryption/decryption test_multiple_values() { local all_passed=true for value in "${TEST_VALUES[@]}"; do local encrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$value" 2>/dev/null) local decrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted" 2>/dev/null) if [ "$decrypted" != "$value" ]; then print_error "Failed to encrypt/decrypt value: $value" all_passed=false fi done $all_passed } # Test 9: Invalid encrypted value handling test_invalid_encrypted_value() { local invalid_encrypted="@invalid_base64_value" if cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$invalid_encrypted" > /dev/null 2>&1; then return 1 # Should fail else return 0 # Expected failure fi } # Test 10: Key rotation test_key_rotation() { local test_value="rotation_test_value" # Encrypt with original key local encrypted_original=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) # Rotate key cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" rotate-key --confirm > /dev/null 2>&1 # Verify old encrypted value can't be decrypted with new key if cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted_original" > /dev/null 2>&1; then return 1 # Should fail with new key fi # Verify new encryption works local encrypted_new=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) local decrypted_new=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted_new" 2>/dev/null) [ "$decrypted_new" = "$test_value" ] } # Test 11: Configuration file operations test_config_operations() { local config_file="$TEST_DIR/test_config.toml" # Create test configuration cat > "$config_file" << EOF [session] secret = "plain_session_secret" [database] url = "postgresql://user:plain_password@localhost:5432/db" [oauth.google] client_secret = "plain_google_secret" [email] sendgrid_api_key = "@already_encrypted_value" EOF # Test finding encrypted values local encrypted_count=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" find-encrypted -c "$config_file" 2>/dev/null | grep -c "@already_encrypted_value" || echo "0") [ "$encrypted_count" = "1" ] } # Test 12: Interactive mode simulation (basic test) test_interactive_mode_basic() { # Test that interactive mode starts without error echo "6" | timeout 5 cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" interactive > /dev/null 2>&1 return $? } # Test 13: Empty value handling test_empty_value() { local empty_value="" local encrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$empty_value" 2>/dev/null) local decrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted" 2>/dev/null) [ "$decrypted" = "$empty_value" ] } # Test 14: Large value handling test_large_value() { local large_value=$(printf 'a%.0s' {1..1000}) # 1000 character string local encrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$large_value" 2>/dev/null) local decrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted" 2>/dev/null) [ "$decrypted" = "$large_value" ] } # Test 15: Key info command test_key_info() { cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" key-info > /dev/null 2>&1 } # Main test execution main() { print_info "Starting encryption system tests..." print_info "Test directory: $TEST_DIR" echo # Check if we're in the right directory if [ ! -f "Cargo.toml" ]; then print_error "This script must be run from the root of a Rust project" exit 1 fi # Run all tests echo "=== Basic Functionality Tests ===" run_test "Crypto tool availability" test_crypto_tool_available run_test "Generate encryption key" test_generate_key run_test "Key file permissions" test_key_file_permissions run_test "Verify encryption key" test_verify_key run_test "Basic encryption/decryption" test_basic_encryption run_test "Encryption randomness" test_encryption_randomness run_test "Encrypted value format" test_encrypted_format echo echo "=== Advanced Functionality Tests ===" run_test "Multiple values encryption" test_multiple_values run_test "Invalid encrypted value handling" test_invalid_encrypted_value run_test "Key rotation" test_key_rotation run_test "Configuration file operations" test_config_operations run_test "Interactive mode basic" test_interactive_mode_basic echo echo "=== Edge Cases Tests ===" run_test "Empty value handling" test_empty_value run_test "Large value handling" test_large_value run_test "Key info command" test_key_info echo echo "=== Test Results ===" print_info "Total tests: $TOTAL_TESTS" print_success "Passed: $PASSED_TESTS" if [ $FAILED_TESTS -gt 0 ]; then print_error "Failed: $FAILED_TESTS" echo print_error "Some tests failed. Please check the encryption system implementation." exit 1 else echo print_success "All tests passed! The encryption system is working correctly." echo print_info "Performance test with real values:" # Performance test local start_time=$(date +%s.%N) for i in {1..10}; do local test_value="performance_test_value_$i" local encrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" encrypt "$test_value" 2>/dev/null) local decrypted=$(cargo run --bin config_crypto_tool -- --root-path "$TEST_DIR" decrypt "$encrypted" 2>/dev/null) if [ "$decrypted" != "$test_value" ]; then print_error "Performance test failed for value $i" fi done local end_time=$(date +%s.%N) local duration=$(echo "$end_time - $start_time" | bc 2>/dev/null || echo "N/A") if [ "$duration" != "N/A" ]; then print_info "10 encrypt/decrypt cycles completed in ${duration}s" else print_info "10 encrypt/decrypt cycles completed" fi echo print_success "Encryption system test completed successfully!" echo print_info "You can now safely use the encryption system in your configuration files." print_info "Remember to:" print_info "1. Keep the .k file secure and never commit it to version control" print_info "2. Backup your encryption keys" print_info "3. Use different keys for different environments" print_info "4. Rotate keys regularly in production" exit 0 fi } # Run main function main "$@"