using ColaFlow.Modules.Mcp.Infrastructure.Auditing; using ColaFlow.Modules.Mcp.Infrastructure.Reporting; using ColaFlow.Modules.Mcp.Infrastructure.Validation; using FluentAssertions; using Microsoft.Extensions.Logging; using Moq; namespace ColaFlow.IntegrationTests.Mcp; /// /// Tests for multi-tenant security report generation /// public class MultiTenantSecurityReportTests { [Fact] public void SecurityReport_IsGenerated_Successfully() { // Arrange var mockLogger = new Mock>(); var auditLogger = new McpSecurityAuditLogger(mockLogger.Object); var mockValidatorLogger = new Mock>(); var tenantValidator = new TenantContextValidator(mockValidatorLogger.Object); var reportGenerator = new MultiTenantSecurityReportGenerator(auditLogger, tenantValidator); // Act var report = reportGenerator.GenerateReport(); // Assert report.Should().NotBeNull(); report.GeneratedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5)); report.SecurityChecks.Should().NotBeNull(); report.AuditStatistics.Should().NotBeNull(); report.ValidationStatistics.Should().NotBeNull(); report.OverallScore.Should().NotBeNull(); } [Fact] public void SecurityReport_TextFormat_ContainsRequiredSections() { // Arrange var reportGenerator = new MultiTenantSecurityReportGenerator(); // Act var textReport = reportGenerator.GenerateTextReport(); // Assert textReport.Should().Contain("MULTI-TENANT SECURITY VERIFICATION REPORT"); textReport.Should().Contain("OVERALL SECURITY SCORE"); textReport.Should().Contain("SECURITY CHECKS"); textReport.Should().Contain("AUDIT STATISTICS"); textReport.Should().Contain("QUERY VALIDATION STATISTICS"); } [Fact] public void SecurityReport_MarkdownFormat_ContainsRequiredSections() { // Arrange var reportGenerator = new MultiTenantSecurityReportGenerator(); // Act var markdownReport = reportGenerator.GenerateMarkdownReport(); // Assert markdownReport.Should().Contain("# Multi-Tenant Security Verification Report"); markdownReport.Should().Contain("## Overall Security Score"); markdownReport.Should().Contain("## Security Checks"); markdownReport.Should().Contain("## Audit Statistics"); } [Fact] public void SecurityScore_IsCalculated_Correctly() { // Arrange var reportGenerator = new MultiTenantSecurityReportGenerator(); // Act var report = reportGenerator.GenerateReport(); // Assert report.OverallScore.Score.Should().BeGreaterThanOrEqualTo(0); report.OverallScore.Score.Should().BeLessThanOrEqualTo(100); report.OverallScore.Grade.Should().NotBeNullOrEmpty(); report.OverallScore.Status.Should().NotBeNullOrEmpty(); } [Fact] public void SecurityChecks_AllPass_WhenNoIssues() { // Arrange var reportGenerator = new MultiTenantSecurityReportGenerator(); // Act var report = reportGenerator.GenerateReport(); // Assert report.SecurityChecks.TotalChecks.Should().BeGreaterThan(0); report.SecurityChecks.PassedChecks.Should().BeGreaterThanOrEqualTo(0); report.SecurityChecks.FailedChecks.Should().BeGreaterThanOrEqualTo(0); (report.SecurityChecks.PassedChecks + report.SecurityChecks.FailedChecks) .Should().Be(report.SecurityChecks.TotalChecks); } [Fact] public void AuditLogger_RecordsSuccess_Correctly() { // Arrange var mockLogger = new Mock>(); var auditLogger = new McpSecurityAuditLogger(mockLogger.Object); var auditEvent = new McpSecurityAuditEvent { TenantId = Guid.NewGuid(), UserId = Guid.NewGuid(), Operation = "test_operation", Success = true }; // Act auditLogger.LogSuccess(auditEvent); var stats = auditLogger.GetAuditStatistics(); // Assert stats.TotalOperations.Should().Be(1); stats.SuccessfulOperations.Should().Be(1); stats.FailedOperations.Should().Be(0); } [Fact] public void AuditLogger_RecordsCrossTenantAttempt_Correctly() { // Arrange var mockLogger = new Mock>(); var auditLogger = new McpSecurityAuditLogger(mockLogger.Object); var auditEvent = new McpSecurityAuditEvent { TenantId = Guid.NewGuid(), TargetTenantId = Guid.NewGuid(), UserId = Guid.NewGuid(), Operation = "cross_tenant_access", ResourceType = "projects", ResourceId = Guid.NewGuid() }; // Act auditLogger.LogCrossTenantAccessAttempt(auditEvent); var stats = auditLogger.GetAuditStatistics(); // Assert stats.CrossTenantAccessAttempts.Should().Be(1); stats.FailedOperations.Should().Be(1); stats.LastCrossTenantAttempt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5)); } [Fact] public void TenantValidator_DetectsQueryWithTenantFilter() { // Arrange var mockLogger = new Mock>(); var validator = new TenantContextValidator(mockLogger.Object); var queryWithFilter = "SELECT * FROM Projects WHERE TenantId = @tenantId"; // Act var result = validator.ValidateQueryIncludesTenantFilter(queryWithFilter); var stats = validator.GetValidationStats(); // Assert result.Should().BeTrue(); stats.QueriesWithTenantFilter.Should().Be(1); stats.QueriesWithoutTenantFilter.Should().Be(0); } [Fact] public void TenantValidator_DetectsQueryWithoutTenantFilter() { // Arrange var mockLogger = new Mock>(); var validator = new TenantContextValidator(mockLogger.Object); var queryWithoutFilter = "SELECT * FROM Projects WHERE Name = 'Test'"; // Act var result = validator.ValidateQueryIncludesTenantFilter(queryWithoutFilter); var stats = validator.GetValidationStats(); // Assert result.Should().BeFalse(); stats.QueriesWithTenantFilter.Should().Be(0); stats.QueriesWithoutTenantFilter.Should().Be(1); stats.ViolatingQueries.Should().Contain(queryWithoutFilter); } [Fact] public void SecurityReport_IncludesFindings_ForCrossTenantAttempts() { // Arrange var mockLogger = new Mock>(); var auditLogger = new McpSecurityAuditLogger(mockLogger.Object); // Log a cross-tenant access attempt auditLogger.LogCrossTenantAccessAttempt(new McpSecurityAuditEvent { TenantId = Guid.NewGuid(), TargetTenantId = Guid.NewGuid() }); var reportGenerator = new MultiTenantSecurityReportGenerator(auditLogger); // Act var report = reportGenerator.GenerateReport(); // Assert report.Findings.Should().NotBeEmpty(); report.Findings.Should().Contain(f => f.Category.Contains("Cross-Tenant Access")); } [Fact] public void SecurityReport_IncludesFindings_ForUnfilteredQueries() { // Arrange var mockValidatorLogger = new Mock>(); var validator = new TenantContextValidator(mockValidatorLogger.Object); // Validate a query without tenant filter validator.ValidateQueryIncludesTenantFilter("SELECT * FROM Projects"); var reportGenerator = new MultiTenantSecurityReportGenerator(tenantValidator: validator); // Act var report = reportGenerator.GenerateReport(); // Assert report.Findings.Should().NotBeEmpty(); report.Findings.Should().Contain(f => f.Category.Contains("Queries Without TenantId Filter")); report.Findings.Should().Contain(f => f.Severity == "Critical"); } [Fact] public void SecurityReport_ShowsPerfectScore_WhenNoIssues() { // Arrange var reportGenerator = new MultiTenantSecurityReportGenerator(); // Act var report = reportGenerator.GenerateReport(); // Assert - With no issues, should have high score report.OverallScore.Score.Should().BeGreaterThanOrEqualTo(90); report.OverallScore.Status.Should().BeOneOf("Pass", "Warning"); } }