Rustelo/scripts/utils/test_encryption.sh

327 lines
10 KiB
Bash
Raw Normal View History

2025-07-07 23:53:50 +01:00
#!/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 "$@"