Platform restructured into crates/, added AI service and detector,
migrated control-center-ui to Leptos 0.8
489 lines
14 KiB
Rust
489 lines
14 KiB
Rust
//! SecretumVault KMS Integration Tests
|
|
//! Tests cover embedded library mode and service mode operations
|
|
|
|
use std::str::FromStr;
|
|
|
|
use vault_service::types::*;
|
|
use vault_service::KmsService;
|
|
|
|
/// Test configuration for embedded mode (filesystem)
|
|
#[allow(dead_code)]
|
|
fn embedded_config() -> KmsBackendConfig {
|
|
KmsBackendConfig::Secretumvault {
|
|
server_url: "http://localhost:8200".to_string(),
|
|
storage_backend: "filesystem".to_string(),
|
|
auth_token: None,
|
|
mount_point: "transit".to_string(),
|
|
key_name: "test-key".to_string(),
|
|
tls_verify: false,
|
|
}
|
|
}
|
|
|
|
/// Test configuration for service mode
|
|
fn service_config() -> KmsBackendConfig {
|
|
KmsBackendConfig::Secretumvault {
|
|
server_url: std::env::var("SECRETUMVAULT_URL")
|
|
.unwrap_or_else(|_| "http://localhost:8200".to_string()),
|
|
storage_backend: "surrealdb".to_string(),
|
|
auth_token: std::env::var("SECRETUMVAULT_TOKEN").ok(),
|
|
mount_point: "transit".to_string(),
|
|
key_name: "test-key".to_string(),
|
|
tls_verify: false,
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_service_health_check() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let health = service.health_check().await.expect("Health check failed");
|
|
assert!(health, "SecretumVault service should be healthy");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_get_version() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let version = service.get_version().await.expect("Failed to get version");
|
|
assert!(!version.is_empty(), "Version should not be empty");
|
|
println!("SecretumVault version: {}", version);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_encrypt_decrypt() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let plaintext = b"secret data to encrypt";
|
|
let context = EncryptionContext::new();
|
|
|
|
// Encrypt
|
|
let ciphertext = service
|
|
.encrypt(plaintext, &context)
|
|
.await
|
|
.expect("Encryption failed");
|
|
|
|
assert!(!ciphertext.is_empty(), "Ciphertext should not be empty");
|
|
assert_ne!(
|
|
plaintext,
|
|
&ciphertext[..],
|
|
"Ciphertext should differ from plaintext"
|
|
);
|
|
|
|
// Decrypt
|
|
let decrypted = service
|
|
.decrypt(&ciphertext, &context)
|
|
.await
|
|
.expect("Decryption failed");
|
|
|
|
assert_eq!(
|
|
plaintext,
|
|
&decrypted[..],
|
|
"Decrypted data should match original plaintext"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_encrypt_decrypt_large_data() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
// Large data (1 MB)
|
|
let plaintext = vec![0x42u8; 1024 * 1024];
|
|
let context = EncryptionContext::new();
|
|
|
|
// Encrypt
|
|
let ciphertext = service
|
|
.encrypt(&plaintext, &context)
|
|
.await
|
|
.expect("Encryption failed");
|
|
|
|
// Decrypt
|
|
let decrypted = service
|
|
.decrypt(&ciphertext, &context)
|
|
.await
|
|
.expect("Decryption failed");
|
|
|
|
assert_eq!(
|
|
plaintext, decrypted,
|
|
"Decrypted large data should match original"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_encrypt_with_context() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let plaintext = b"sensitive data";
|
|
let mut context = EncryptionContext::new();
|
|
context.add("environment", "production");
|
|
context.add("service", "api-gateway");
|
|
|
|
// Encrypt with context
|
|
let ciphertext = service
|
|
.encrypt(plaintext, &context)
|
|
.await
|
|
.expect("Encryption with context failed");
|
|
|
|
// Decrypt with same context
|
|
let decrypted = service
|
|
.decrypt(&ciphertext, &context)
|
|
.await
|
|
.expect("Decryption with context failed");
|
|
|
|
assert_eq!(
|
|
plaintext,
|
|
&decrypted[..],
|
|
"Decrypted data should match original"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_generate_aes128_key() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let data_key = service
|
|
.generate_data_key(&KeySpec::Aes128)
|
|
.await
|
|
.expect("Data key generation failed");
|
|
|
|
assert_eq!(
|
|
data_key.plaintext.len(),
|
|
16,
|
|
"AES-128 key should be 16 bytes"
|
|
);
|
|
assert!(
|
|
!data_key.ciphertext.is_empty(),
|
|
"Encrypted key should not be empty"
|
|
);
|
|
assert_eq!(
|
|
data_key.key_id, "test-key",
|
|
"Key ID should match configuration"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_generate_aes256_key() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let data_key = service
|
|
.generate_data_key(&KeySpec::Aes256)
|
|
.await
|
|
.expect("Data key generation failed");
|
|
|
|
assert_eq!(
|
|
data_key.plaintext.len(),
|
|
32,
|
|
"AES-256 key should be 32 bytes"
|
|
);
|
|
assert!(
|
|
!data_key.ciphertext.is_empty(),
|
|
"Encrypted key should not be empty"
|
|
);
|
|
assert_eq!(
|
|
data_key.key_id, "test-key",
|
|
"Key ID should match configuration"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_generate_rsa2048_key() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let data_key = service
|
|
.generate_data_key(&KeySpec::Rsa2048)
|
|
.await
|
|
.expect("Data key generation failed");
|
|
|
|
assert_eq!(
|
|
data_key.plaintext.len(),
|
|
256,
|
|
"RSA-2048 key should be 256 bytes"
|
|
);
|
|
assert!(
|
|
!data_key.ciphertext.is_empty(),
|
|
"Encrypted key should not be empty"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_generate_rsa4096_key() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let data_key = service
|
|
.generate_data_key(&KeySpec::Rsa4096)
|
|
.await
|
|
.expect("Data key generation failed");
|
|
|
|
assert_eq!(
|
|
data_key.plaintext.len(),
|
|
512,
|
|
"RSA-4096 key should be 512 bytes"
|
|
);
|
|
assert!(
|
|
!data_key.ciphertext.is_empty(),
|
|
"Encrypted key should not be empty"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_multiple_operations() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let context = EncryptionContext::new();
|
|
|
|
// Perform multiple operations
|
|
for i in 0..5 {
|
|
let plaintext = format!("data-{}", i).into_bytes();
|
|
let ciphertext = service
|
|
.encrypt(&plaintext, &context)
|
|
.await
|
|
.expect("Encryption failed");
|
|
|
|
let decrypted = service
|
|
.decrypt(&ciphertext, &context)
|
|
.await
|
|
.expect("Decryption failed");
|
|
|
|
assert_eq!(plaintext, decrypted, "Data mismatch on iteration {}", i);
|
|
}
|
|
|
|
// Generate multiple keys
|
|
for _ in 0..3 {
|
|
let _key = service
|
|
.generate_data_key(&KeySpec::Aes256)
|
|
.await
|
|
.expect("Key generation failed");
|
|
}
|
|
|
|
// Health check after operations
|
|
let health = service.health_check().await.expect("Health check failed");
|
|
assert!(health, "Service should still be healthy");
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_binary_data() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
// Binary data with null bytes and special chars
|
|
let plaintext: Vec<u8> = vec![
|
|
0x00, 0x01, 0x02, 0x03, 0xFF, 0xFE, 0xFD, 0xFC, 0x7F, 0x80, 0x00, 0xFF, 0xAB, 0xCD, 0xEF,
|
|
0x12,
|
|
];
|
|
let context = EncryptionContext::new();
|
|
|
|
let ciphertext = service
|
|
.encrypt(&plaintext, &context)
|
|
.await
|
|
.expect("Binary encryption failed");
|
|
|
|
let decrypted = service
|
|
.decrypt(&ciphertext, &context)
|
|
.await
|
|
.expect("Binary decryption failed");
|
|
|
|
assert_eq!(
|
|
plaintext, decrypted,
|
|
"Binary data should match after round-trip"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_empty_data() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let plaintext: Vec<u8> = vec![];
|
|
let context = EncryptionContext::new();
|
|
|
|
// Empty data encryption might be rejected, which is acceptable
|
|
let result = service.encrypt(&plaintext, &context).await;
|
|
|
|
// Either it succeeds and empty data encrypts, or it fails gracefully
|
|
if let Ok(ciphertext) = result {
|
|
let decrypted = service
|
|
.decrypt(&ciphertext, &context)
|
|
.await
|
|
.expect("Empty data decryption failed");
|
|
assert!(decrypted.is_empty(), "Decrypted empty data should be empty");
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_backend_name() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let backend_name = service.get_backend_name();
|
|
assert_eq!(
|
|
backend_name, "secretumvault",
|
|
"Backend name should be 'secretumvault'"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_operations_counter() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
let initial_count = service.get_operations_count().await;
|
|
|
|
let context = EncryptionContext::new();
|
|
let plaintext = b"test";
|
|
|
|
// Perform operations
|
|
let _ = service.encrypt(plaintext, &context).await;
|
|
let _ = service.health_check().await;
|
|
let _ = service.get_version().await;
|
|
|
|
let final_count = service.get_operations_count().await;
|
|
assert!(
|
|
final_count > initial_count,
|
|
"Operations counter should increment"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore] // Requires SecretumVault service running
|
|
async fn test_secretumvault_uptime() {
|
|
let config = service_config();
|
|
let service = KmsService::new(config)
|
|
.await
|
|
.expect("Failed to initialize KMS service");
|
|
|
|
// get_uptime() returns u64, always >= 0 by type
|
|
let _uptime = service.get_uptime();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_secretumvault_config_validation() {
|
|
// Invalid storage backend
|
|
let config = KmsBackendConfig::Secretumvault {
|
|
server_url: "http://localhost:8200".to_string(),
|
|
storage_backend: "invalid_backend".to_string(),
|
|
auth_token: None,
|
|
mount_point: "transit".to_string(),
|
|
key_name: "test-key".to_string(),
|
|
tls_verify: false,
|
|
};
|
|
|
|
let result = KmsService::new(config).await;
|
|
assert!(
|
|
result.is_err(),
|
|
"Invalid storage backend should fail validation"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_secretumvault_encryption_context_add() {
|
|
let mut context = EncryptionContext::new();
|
|
|
|
context.add("key1", "value1");
|
|
context.add("key2", "value2");
|
|
|
|
assert_eq!(context.context.len(), 2, "Context should have 2 entries");
|
|
assert_eq!(context.context.get("key1").unwrap(), "value1");
|
|
assert_eq!(context.context.get("key2").unwrap(), "value2");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_secretumvault_encryption_context_from_str() {
|
|
let context_str = "environment=prod,service=api";
|
|
let context = EncryptionContext::from_str(context_str).expect("Failed to parse context");
|
|
|
|
assert_eq!(context.context.len(), 2);
|
|
assert_eq!(context.context.get("environment").unwrap(), "prod");
|
|
assert_eq!(context.context.get("service").unwrap(), "api");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_secretumvault_encryption_context_to_string() {
|
|
let mut context = EncryptionContext::new();
|
|
context.add("environment", "prod");
|
|
context.add("service", "api");
|
|
|
|
let context_str = context.to_string();
|
|
assert!(
|
|
!context_str.is_empty(),
|
|
"Context string should not be empty"
|
|
);
|
|
assert!(
|
|
context_str.contains("environment=prod"),
|
|
"Context should include environment"
|
|
);
|
|
assert!(
|
|
context_str.contains("service=api"),
|
|
"Context should include service"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_key_spec_sizes() {
|
|
assert_eq!(KeySpec::Aes128.key_size(), 16);
|
|
assert_eq!(KeySpec::Aes256.key_size(), 32);
|
|
assert_eq!(KeySpec::Rsa2048.key_size(), 256);
|
|
assert_eq!(KeySpec::Rsa4096.key_size(), 512);
|
|
}
|
|
|
|
// Integration test runner helper - run with:
|
|
// cargo test --package vault-service --test secretumvault_integration --
|
|
// --ignored --test-threads=1
|
|
//
|
|
// Before running tests, start SecretumVault:
|
|
// secretumvault server --storage-backend filesystem
|
|
//
|
|
// Optional: set environment variables for service mode tests:
|
|
// export SECRETUMVAULT_URL=http://localhost:8200
|
|
// export SECRETUMVAULT_TOKEN=your-token
|