327 lines
10 KiB
Bash
327 lines
10 KiB
Bash
![]() |
#!/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 "$@"
|