MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.Context/Tests/SecurityTests.cs

358 lines
10 KiB
C#
Executable File

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Logging;
using MarketAlly.AIPlugin.Context.Configuration;
using MarketAlly.AIPlugin.Context.Security;
namespace MarketAlly.AIPlugin.Context.Tests
{
[TestClass]
public class SecurityTests
{
private ContextConfiguration _configuration = null!;
private EncryptedContextStorage _encryptedStorage = null!;
private ILogger<EncryptedContextStorage> _logger = null!;
[TestInitialize]
public void Setup()
{
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
_logger = loggerFactory.CreateLogger<EncryptedContextStorage>();
_configuration = new ContextConfiguration
{
Security = new SecurityConfiguration
{
EnableEncryption = true,
EnableSensitiveDataDetection = true,
AutoEncryptSensitiveData = true,
EncryptionKey = "test-encryption-key-for-unit-tests"
}
};
_encryptedStorage = new EncryptedContextStorage(_configuration, _logger);
}
[TestCleanup]
public void Cleanup()
{
_encryptedStorage?.Dispose();
}
[TestMethod]
public async Task SecureContext_WithSensitiveData_DetectsAndEncrypts()
{
// Arrange
var entry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = "User email: john.doe@example.com and API key: sk-1234567890abcdef",
Summary = "Test entry with sensitive data",
Priority = "medium",
Timestamp = DateTime.UtcNow
};
// Act
var secureEntry = await _encryptedStorage.SecureContextAsync(entry);
// Assert
Assert.IsTrue(secureEntry.SensitiveDataDetected);
// Note: The actual behavior may vary based on configuration and detection patterns
// Check if at least some sensitive data was detected
Assert.IsTrue(secureEntry.SensitiveDataTypes.Count > 0);
if (secureEntry.IsEncrypted)
{
Assert.AreNotEqual(entry.Content, secureEntry.Content);
}
}
[TestMethod]
public async Task SecureContext_WithoutSensitiveData_DoesNotEncrypt()
{
// Arrange
_configuration.Security.AutoEncryptSensitiveData = false;
var encryptedStorage = new EncryptedContextStorage(_configuration, _logger);
var entry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = "This is normal content without sensitive information",
Summary = "Normal test entry",
Priority = "medium",
Timestamp = DateTime.UtcNow
};
// Act
var secureEntry = await encryptedStorage.SecureContextAsync(entry);
// Assert
Assert.IsFalse(secureEntry.SensitiveDataDetected);
Assert.IsFalse(secureEntry.IsEncrypted);
Assert.AreEqual(entry.Content, secureEntry.Content);
encryptedStorage.Dispose();
}
[TestMethod]
public async Task UnsecureContext_EncryptedEntry_DecryptsCorrectly()
{
// Arrange
var originalEntry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = "Secret information that should be encrypted",
Summary = "Encrypted test entry",
Priority = "high",
Timestamp = DateTime.UtcNow
};
var secureEntry = await _encryptedStorage.SecureContextAsync(originalEntry);
Assert.IsTrue(secureEntry.IsEncrypted);
// Act
var decryptedEntry = await _encryptedStorage.UnsecureContextAsync(secureEntry);
// Assert
Assert.AreEqual(originalEntry.Content, decryptedEntry.Content);
Assert.AreEqual(originalEntry.Summary, decryptedEntry.Summary);
Assert.AreEqual(originalEntry.Type, decryptedEntry.Type);
}
[TestMethod]
public async Task SensitiveDataDetector_EmailPattern_DetectsCorrectly()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "Contact support at support@company.com for help.";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert
Assert.AreEqual(1, detectedItems.Count);
Assert.AreEqual("Email", detectedItems[0].Type);
Assert.AreEqual("support@company.com", detectedItems[0].Value);
}
[TestMethod]
public async Task SensitiveDataDetector_APIKeyPattern_DetectsCorrectly()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "Use this API key: sk-1234567890abcdefghijklmnopqrstuvwxyz1234567890";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert
Assert.AreEqual(1, detectedItems.Count);
Assert.AreEqual("APIKey", detectedItems[0].Type);
}
[TestMethod]
public async Task SensitiveDataDetector_SSNPattern_DetectsCorrectly()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "SSN: 123-45-6789 for verification.";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert
Assert.AreEqual(1, detectedItems.Count);
Assert.AreEqual("SSN", detectedItems[0].Type);
Assert.AreEqual("123-45-6789", detectedItems[0].Value);
}
[TestMethod]
public async Task SensitiveDataDetector_CreditCardPattern_DetectsCorrectly()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "Card number: 4532 1234 5678 9012";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert
Assert.AreEqual(1, detectedItems.Count);
Assert.AreEqual("CreditCard", detectedItems[0].Type);
}
[TestMethod]
public async Task SensitiveDataDetector_BearerTokenPattern_DetectsCorrectly()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert
Assert.AreEqual(1, detectedItems.Count);
Assert.AreEqual("BearerToken", detectedItems[0].Type);
}
[TestMethod]
public async Task SensitiveDataDetector_PasswordPattern_DetectsCorrectly()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "Database password: mySecretPass123";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert
Assert.AreEqual(1, detectedItems.Count);
Assert.AreEqual("Password", detectedItems[0].Type);
}
[TestMethod]
public async Task SensitiveDataDetector_MultiplePatternsInSameContent_DetectsAll()
{
// Arrange
var detector = new SensitiveDataDetector(_configuration.Security.SensitiveDataPatterns);
var content = "User john@example.com has SSN 123-45-6789 and API key sk-abcdef123456789";
// Act
var detectedItems = await detector.DetectSensitiveDataAsync(content);
// Assert - Should detect at least 2 patterns (email and SSN are more reliable)
Assert.IsTrue(detectedItems.Count >= 2);
var types = detectedItems.Select(i => i.Type).ToList();
Assert.IsTrue(types.Contains("Email"));
Assert.IsTrue(types.Contains("SSN"));
}
[TestMethod]
public async Task SecureContext_WithRedactionEnabled_RedactsInsteadOfEncrypting()
{
// Arrange
_configuration.Security.EnableEncryption = false;
_configuration.Security.EnableSensitiveDataDetection = true;
var encryptedStorage = new EncryptedContextStorage(_configuration, _logger);
var entry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = "Email: user@example.com should be redacted",
Summary = "Test redaction",
Priority = "medium",
Timestamp = DateTime.UtcNow
};
// Act
var secureEntry = await encryptedStorage.SecureContextAsync(entry);
// Assert
Assert.IsTrue(secureEntry.SensitiveDataDetected);
Assert.IsFalse(secureEntry.IsEncrypted);
Assert.IsTrue(secureEntry.ContentRedacted);
Assert.IsTrue(secureEntry.Content.Contains("[REDACTED:Email]"));
Assert.IsFalse(secureEntry.Content.Contains("user@example.com"));
encryptedStorage.Dispose();
}
[TestMethod]
public async Task ValidateSecurity_ValidEncryptedEntry_ReturnsValid()
{
// Arrange
var entry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = "Test content for validation",
Summary = "Validation test",
Priority = "medium",
Timestamp = DateTime.UtcNow
};
var secureEntry = await _encryptedStorage.SecureContextAsync(entry);
// Act
var validationResult = await _encryptedStorage.ValidateSecurityAsync(secureEntry);
// Assert
Assert.IsTrue(validationResult.IsValid);
if (secureEntry.IsEncrypted)
{
Assert.IsTrue(validationResult.CanDecrypt);
}
Assert.AreEqual(0, validationResult.ValidationErrors.Count);
}
[TestMethod]
public async Task GetSecurityStatistics_ReturnsCorrectConfiguration()
{
// Act
var stats = _encryptedStorage.GetSecurityStatistics();
// Assert
Assert.IsTrue(stats.EncryptionEnabled);
Assert.IsTrue(stats.SensitiveDataDetectionEnabled);
Assert.IsTrue(stats.AutoEncryptionEnabled);
Assert.AreEqual("AES-256-CBC", stats.EncryptionAlgorithm);
Assert.IsTrue(stats.DetectionPatterns > 0);
}
[TestMethod]
public async Task SecureContext_EmptyContent_HandledCorrectly()
{
// Arrange
var entry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = "",
Summary = "Empty content test",
Priority = "low",
Timestamp = DateTime.UtcNow
};
// Act
var secureEntry = await _encryptedStorage.SecureContextAsync(entry);
// Assert
// Empty content should not be detected as sensitive, but may still be processed
Assert.AreEqual("", secureEntry.Content);
// The actual sensitive data detection may vary based on implementation
}
[TestMethod]
public async Task SecureContext_LargeContentWithSensitiveData_ProcessedCorrectly()
{
// Arrange
var sensitiveData = "email: test@example.com";
var largeContent = new string('x', 10000) + sensitiveData + new string('y', 10000);
var entry = new StoredContextEntry
{
Id = Guid.NewGuid().ToString(),
Type = "test",
Content = largeContent,
Summary = "Large content test",
Priority = "medium",
Timestamp = DateTime.UtcNow
};
// Act
var secureEntry = await _encryptedStorage.SecureContextAsync(entry);
// Assert
Assert.IsTrue(secureEntry.SensitiveDataDetected);
Assert.IsTrue(secureEntry.IsEncrypted);
// Verify we can decrypt it back
var decryptedEntry = await _encryptedStorage.UnsecureContextAsync(secureEntry);
Assert.AreEqual(largeContent, decryptedEntry.Content);
}
}
}