358 lines
10 KiB
C#
Executable File
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);
|
|
}
|
|
}
|
|
} |