# Configuration Encryption System Tests # Comprehensive test suite for encryption functionality # Error handling: Guard patterns (no try-catch for field access) # Selective imports (ADR-025 Phase 3 Layer 2). use domain/config/encryption.nu [ contains-sensitive-data decrypt-config decrypt-config-memory encrypt-config is-encrypted-config load-encrypted-config validate-encryption-config ] use platform/kms/client.nu [kms-status] # Test suite runner export def run-encryption-tests [ --verbose (-v) # Verbose output --test: string = "" # Run specific test (empty = all) ] { print "๐Ÿงช Configuration Encryption Test Suite" print "======================================" print "" mut results = [] # Test 1: Encryption detection if ($test == "" or $test == "detection") { print "๐Ÿ” Test 1: Encryption Detection" let result = (test-encryption-detection) $results = ($results | append $result) show-test-result $result print "" } # Test 2: Encrypt/Decrypt round-trip if ($test == "" or $test == "roundtrip") { print "๐Ÿ” Test 2: Encrypt/Decrypt Round-trip" let result = (test-encrypt-decrypt-roundtrip) $results = ($results | append $result) show-test-result $result print "" } # Test 3: Memory-only decryption if ($test == "" or $test == "memory") { print "๐Ÿ” Test 3: Memory-Only Decryption" let result = (test-memory-only-decryption) $results = ($results | append $result) show-test-result $result print "" } # Test 4: Sensitive data detection if ($test == "" or $test == "sensitive") { print "๐Ÿ” Test 4: Sensitive Data Detection" let result = (test-sensitive-data-detection) $results = ($results | append $result) show-test-result $result print "" } # Test 5: KMS backend integration if ($test == "" or $test == "kms") { print "๐Ÿ” Test 5: KMS Backend Integration" let result = (test-kms-backend-integration) $results = ($results | append $result) show-test-result $result print "" } # Test 6: Config loader integration if ($test == "" or $test == "loader") { print "๐Ÿ” Test 6: Config Loader Integration" let result = (test-config-loader-integration) $results = ($results | append $result) show-test-result $result print "" } # Test 7: Validation if ($test == "" or $test == "validation") { print "๐Ÿ” Test 7: Encryption Validation" let result = (test-encryption-validation) $results = ($results | append $result) show-test-result $result print "" } # Summary print "๐Ÿ“Š Test Summary" print "==============" let total = ($results | length) let passed = ($results | where passed == true | length) let failed = ($total - $passed) print $" Total tests: ($total)" print $" Passed: ($passed)" print $" Failed: ($failed)" print $" Success rate: (($passed * 100) / $total)%" if $failed == 0 { print "" print "โœ… All tests passed!" } else { print "" print "โŒ Some tests failed:" for result in ($results | where passed == false) { print $" โ€ข ($result.test_name): ($result.error)" } } { total: $total passed: $passed failed: $failed results: $results } } # Test 1: Encryption detection def test-encryption-detection [] { let test_name = "Encryption Detection" let result = (do { # Create test file let test_file = "/tmp/test_plain.yaml" "test: value" | save --force $test_file # Should detect as not encrypted let is_enc = (is-encrypted-config $test_file) rm --force $test_file if $is_enc { error make { msg: "Plain file incorrectly detected as encrypted" } } "success" } | complete) if $result.exit_code == 0 { { test_name: $test_name passed: true error: null } } else { { test_name: $test_name passed: false error: $result.stderr } } } # Test 2: Encrypt/Decrypt round-trip def test-encrypt-decrypt-roundtrip [] { let test_name = "Encrypt/Decrypt Round-trip" let result = (do { # Create test file let test_file = "/tmp/test_roundtrip.yaml" let original_content = "test_key: secret_value" $original_content | save --force $test_file # Check if age is available let age_check = (^which age | complete) if $age_check.exit_code != 0 { rm --force $test_file return { test_name: $test_name passed: true error: "Skipped: Age not installed" skipped: true } } # Check if SOPS recipients configured let recipients = ($env.SOPS_AGE_RECIPIENTS? | default "") if ($recipients | is-empty) { rm --force $test_file return { test_name: $test_name passed: true error: "Skipped: SOPS_AGE_RECIPIENTS not configured" skipped: true } } # Encrypt the file let encrypted_file = $"($test_file).enc" encrypt-config $test_file $encrypted_file --kms="age" # Verify it's encrypted if not (is-encrypted-config $encrypted_file) { rm --force $test_file $encrypted_file error make { msg: "File not encrypted after encrypt-config" } } # Decrypt the file let decrypted_file = $"($test_file).dec" decrypt-config $encrypted_file $decrypted_file # Verify content matches let decrypted_content = (open $decrypted_file --raw) # Cleanup rm --force $test_file $encrypted_file $decrypted_file if $decrypted_content != $original_content { error make { msg: "Decrypted content doesn't match original" } } { test_name: $test_name passed: true error: null } } | complete) if $result.exit_code == 0 { $result.stdout | from json } else { { test_name: $test_name passed: false error: $result.stderr } } } # Test 3: Memory-only decryption def test-memory-only-decryption [] { let test_name = "Memory-Only Decryption" let result = (do { # Check if age is available let age_check = (^which age | complete) if $age_check.exit_code != 0 { return { test_name: $test_name passed: true error: "Skipped: Age not installed" skipped: true } } # Check if SOPS recipients configured let recipients = ($env.SOPS_AGE_RECIPIENTS? | default "") if ($recipients | is-empty) { return { test_name: $test_name passed: true error: "Skipped: SOPS_AGE_RECIPIENTS not configured" skipped: true } } # Create and encrypt test file let test_file = "/tmp/test_memory.yaml" let original_content = "secret: memory_test" $original_content | save --force $test_file let encrypted_file = $"($test_file).enc" encrypt-config $test_file $encrypted_file --kms="age" # Decrypt in memory let decrypted_memory = (decrypt-config-memory $encrypted_file) # Cleanup rm --force $test_file $encrypted_file # Verify no decrypted file was created if ($"($encrypted_file).dec" | path exists) { error make { msg: "Decrypted file was created (should be memory-only)" } } # Verify decrypted content if $decrypted_memory != $original_content { error make { msg: "Memory-decrypted content doesn't match original" } } { test_name: $test_name passed: true error: null } } | complete) if $result.exit_code == 0 { $result.stdout | from json } else { { test_name: $test_name passed: false error: $result.stderr } } } # Test 4: Sensitive data detection def test-sensitive-data-detection [] { let test_name = "Sensitive Data Detection" let result = (do { # Create test file with sensitive data let test_file = "/tmp/test_sensitive.yaml" let sensitive_content = "api_key: secret123\npassword: mypassword" $sensitive_content | save --force $test_file # Should detect sensitive data let has_sensitive = (contains-sensitive-data $test_file) # Create test file without sensitive data let test_file_safe = "/tmp/test_safe.yaml" let safe_content = "name: test\nvalue: 123" $safe_content | save --force $test_file_safe # Should not detect sensitive data let has_no_sensitive = not (contains-sensitive-data $test_file_safe) # Cleanup rm --force $test_file $test_file_safe if not ($has_sensitive and $has_no_sensitive) { error make { msg: "Sensitive data detection not working correctly" } } { test_name: $test_name passed: true error: null } } | complete) if $result.exit_code == 0 { $result.stdout | from json } else { { test_name: $test_name passed: false error: $result.stderr } } } # Test 5: KMS backend integration def test-kms-backend-integration [] { let test_name = "KMS Backend Integration" let result = (do { # Test detection let backend = (detect-kms-backend) if ($backend | is-empty) { error make { msg: "Failed to detect KMS backend" } } # Test status let status = (kms-status) if ($status.backend | is-empty) { error make { msg: "KMS status check failed" } } { test_name: $test_name passed: true error: null details: { detected_backend: $backend status: $status } } } | complete) if $result.exit_code == 0 { $result.stdout | from json } else { { test_name: $test_name passed: false error: $result.stderr } } } # Test 6: Config loader integration def test-config-loader-integration [] { let test_name = "Config Loader Integration" let result = (do { # Create test directory mkdir /tmp/test_config_loader # Create plain config let plain_config = "/tmp/test_config_loader/plain.yaml" {test: "plain", value: 123} | to yaml | save --force $plain_config # Load plain config (should work) use loader.nu let loaded_plain = (loader load-config-file $plain_config false false "yaml") if ($loaded_plain.test != "plain") { rm --force --recursive /tmp/test_config_loader error make { msg: "Failed to load plain config through loader" } } # Cleanup rm --force --recursive /tmp/test_config_loader { test_name: $test_name passed: true error: null } } | complete) if $result.exit_code == 0 { $result.stdout | from json } else { { test_name: $test_name passed: false error: $result.stderr } } } # Test 7: Encryption validation def test-encryption-validation [] { let test_name = "Encryption Validation" let result = (do { # Run validation let validation = (validate-encryption-config) # Check that validation returns expected structure if not (($validation | columns) | all { |col| $col in ["valid", "errors", "warnings", "summary"] }) { error make { msg: "Validation result structure incorrect" } } { test_name: $test_name passed: true error: null details: $validation.summary } } | complete) if $result.exit_code == 0 { $result.stdout | from json } else { { test_name: $test_name passed: false error: $result.stderr } } } # Show test result def show-test-result [result: record] { if $result.passed { print $" โœ… ($result.test_name)" # Guard: Check if skipped field exists in result if ("skipped" in ($result | columns)) and ($result | get skipped) == true { print $" โš ๏ธ ($result.error)" } } else { print $" โŒ ($result.test_name)" print $" Error: ($result.error)" } } # Integration test with full workflow export def test-full-encryption-workflow [] { print "๐Ÿงช Full Encryption Workflow Test" print "=================================" print "" let test_dir = "/tmp/test_encryption_workflow" mkdir $test_dir let result = (do { # Step 1: Create test config with sensitive data print "๐Ÿ“ Step 1: Creating test configuration" let config_file = $"($test_dir)/secure.yaml" { database: { host: "localhost" password: "supersecret123" api_key: "key_abc123" } aws: { access_key: "AKIAIOSFODNN7EXAMPLE" secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" } } | to yaml | save --force $config_file print " โœ… Config created" # Step 2: Detect sensitive data print "๐Ÿ” Step 2: Detecting sensitive data" let has_sensitive = (contains-sensitive-data $config_file) if $has_sensitive { print " โœ… Sensitive data detected" } else { print " โŒ Failed to detect sensitive data" rm --force --recursive $test_dir return } # Step 3: Check encryption prerequisites print "๐Ÿ”ง Step 3: Checking encryption prerequisites" let validation = (validate-encryption-config) if $validation.valid { print " โœ… Encryption system configured" } else { print " โš ๏ธ Encryption system has issues:" for error in $validation.errors { print $" โ€ข ($error.message)" } } # Step 4: Encrypt config (if possible) print "๐Ÿ”’ Step 4: Encrypting configuration" let recipients = ($env.SOPS_AGE_RECIPIENTS? | default "") if ($recipients | is-not-empty) { let encrypt_result = (do { encrypt-config $config_file --in-place --kms="age" } | complete) if $encrypt_result.exit_code == 0 { print " โœ… Configuration encrypted" # Step 5: Verify encryption print "๐Ÿ” Step 5: Verifying encryption" let is_enc = (is-encrypted-config $config_file) if $is_enc { print " โœ… Encryption verified" } else { print " โŒ File not encrypted" } # Step 6: Load encrypted config print "๐Ÿ“– Step 6: Loading encrypted config" let loaded = (load-encrypted-config $config_file) if ($loaded.database.password == "supersecret123") { print " โœ… Decrypted and loaded correctly" } else { print " โŒ Failed to load encrypted config" } } else { print $" โŒ Encryption failed: ($encrypt_result.stderr)" } } else { print " โš ๏ธ Skipped: SOPS_AGE_RECIPIENTS not configured" } print "" print "โœ… Workflow test completed" } | complete) if $result.exit_code != 0 { print $"โŒ Workflow test failed: ($result.stderr)" } # Cleanup rm --force --recursive $test_dir } # Main help export def main [] { print "Configuration Encryption Tests" print "==============================" print "" print "Commands:" print " run-encryption-tests Run all tests" print " run-encryption-tests --test Run specific test" print " test-full-encryption-workflow Run complete workflow test" print "" print "Available tests:" print " detection - Encryption detection" print " roundtrip - Encrypt/decrypt round-trip" print " memory - Memory-only decryption" print " sensitive - Sensitive data detection" print " kms - KMS backend integration" print " loader - Config loader integration" print " validation - Encryption validation" }