tests fixes and sprints work
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
using System.Collections.Immutable;
|
||||
using FluentAssertions;
|
||||
using StellaOps.Concelier.SbomIntegration.Models;
|
||||
using StellaOps.Scanner.Reachability.Dependencies;
|
||||
using StellaOps.Scanner.Reachability.Dependencies.Reporting;
|
||||
using StellaOps.Scanner.Sarif;
|
||||
using StellaOps.Scanner.Sarif.Fingerprints;
|
||||
using StellaOps.Scanner.Sarif.Rules;
|
||||
using StellaOps.TestKit;
|
||||
using Xunit;
|
||||
using static StellaOps.Scanner.Reachability.Tests.DependencyTestData;
|
||||
using ReachabilityStatus = StellaOps.Scanner.Reachability.Dependencies.ReachabilityStatus;
|
||||
|
||||
namespace StellaOps.Scanner.Reachability.Tests;
|
||||
|
||||
public sealed class DependencyReachabilityReporterTests
|
||||
{
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task BuildReport_EmitsFilteredFindingsAndSarif()
|
||||
{
|
||||
var sbom = BuildSbom(
|
||||
components:
|
||||
[
|
||||
Component("app", type: "application", purl: "pkg:npm/app@1.0.0"),
|
||||
Component("lib-a", purl: "pkg:npm/lib-a@1.0.0"),
|
||||
Component("lib-b", purl: "pkg:npm/lib-b@1.0.0")
|
||||
],
|
||||
dependencies:
|
||||
[
|
||||
Dependency("app", ["lib-a"], DependencyScope.Runtime),
|
||||
Dependency("lib-a", ["lib-b"], DependencyScope.Runtime)
|
||||
],
|
||||
rootRef: "app");
|
||||
|
||||
var policy = new ReachabilityPolicy
|
||||
{
|
||||
Reporting = new ReachabilityReportingPolicy
|
||||
{
|
||||
ShowFilteredVulnerabilities = true,
|
||||
IncludeReachabilityPaths = true
|
||||
}
|
||||
};
|
||||
|
||||
var combiner = new ReachGraphReachabilityCombiner();
|
||||
var reachabilityReport = combiner.Analyze(sbom, callGraph: null, policy);
|
||||
|
||||
var matchedAt = new DateTimeOffset(2025, 1, 2, 3, 4, 5, TimeSpan.Zero);
|
||||
var matches = new[]
|
||||
{
|
||||
new SbomAdvisoryMatch
|
||||
{
|
||||
Id = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
|
||||
SbomId = Guid.Empty,
|
||||
SbomDigest = "sha256:deadbeef",
|
||||
CanonicalId = Guid.Parse("11111111-1111-1111-1111-111111111111"),
|
||||
Purl = "pkg:npm/lib-a@1.0.0",
|
||||
Method = MatchMethod.ExactPurl,
|
||||
IsReachable = true,
|
||||
IsDeployed = false,
|
||||
MatchedAt = matchedAt
|
||||
},
|
||||
new SbomAdvisoryMatch
|
||||
{
|
||||
Id = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"),
|
||||
SbomId = Guid.Empty,
|
||||
SbomDigest = "sha256:deadbeef",
|
||||
CanonicalId = Guid.Parse("22222222-2222-2222-2222-222222222222"),
|
||||
Purl = "pkg:npm/lib-b@1.0.0",
|
||||
Method = MatchMethod.ExactPurl,
|
||||
IsReachable = false,
|
||||
IsDeployed = false,
|
||||
MatchedAt = matchedAt
|
||||
}
|
||||
};
|
||||
|
||||
var reachabilityMap = new Dictionary<string, ReachabilityStatus>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["pkg:npm/lib-a@1.0.0"] = ReachabilityStatus.Reachable,
|
||||
["pkg:npm/lib-b@1.0.0"] = ReachabilityStatus.Unreachable
|
||||
};
|
||||
|
||||
var severityMap = new Dictionary<Guid, string?>
|
||||
{
|
||||
[Guid.Parse("11111111-1111-1111-1111-111111111111")] = "high",
|
||||
[Guid.Parse("22222222-2222-2222-2222-222222222222")] = "medium"
|
||||
};
|
||||
|
||||
var filter = new VulnerabilityReachabilityFilter();
|
||||
var filterResult = filter.Apply(matches, reachabilityMap, policy, severityMap);
|
||||
|
||||
var advisorySummaries = new Dictionary<Guid, DependencyReachabilityAdvisorySummary>
|
||||
{
|
||||
[Guid.Parse("11111111-1111-1111-1111-111111111111")] = new DependencyReachabilityAdvisorySummary
|
||||
{
|
||||
CanonicalId = Guid.Parse("11111111-1111-1111-1111-111111111111"),
|
||||
VulnerabilityId = "CVE-2025-0001",
|
||||
Severity = "high",
|
||||
Title = "lib-a issue"
|
||||
},
|
||||
[Guid.Parse("22222222-2222-2222-2222-222222222222")] = new DependencyReachabilityAdvisorySummary
|
||||
{
|
||||
CanonicalId = Guid.Parse("22222222-2222-2222-2222-222222222222"),
|
||||
VulnerabilityId = "CVE-2025-0002",
|
||||
Severity = "medium",
|
||||
Title = "lib-b issue"
|
||||
}
|
||||
};
|
||||
|
||||
var ruleRegistry = new SarifRuleRegistry();
|
||||
var fingerprintGenerator = new FingerprintGenerator(ruleRegistry);
|
||||
var reporter = new DependencyReachabilityReporter(new SarifExportService(
|
||||
ruleRegistry,
|
||||
fingerprintGenerator));
|
||||
var report = reporter.BuildReport(sbom, reachabilityReport, filterResult, advisorySummaries, policy);
|
||||
|
||||
report.Vulnerabilities.Should().ContainSingle();
|
||||
report.FilteredVulnerabilities.Should().ContainSingle();
|
||||
report.Summary.VulnerabilityStatistics.FilteredVulnerabilities.Should().Be(1);
|
||||
|
||||
var purlLookup = sbom.Components
|
||||
.Where(component => !string.IsNullOrWhiteSpace(component.BomRef))
|
||||
.ToDictionary(component => component.BomRef!, component => component.Purl, StringComparer.Ordinal);
|
||||
var dot = reporter.ExportGraphViz(
|
||||
reachabilityReport.Graph,
|
||||
reachabilityReport.ComponentReachability,
|
||||
purlLookup);
|
||||
dot.Should().Contain("digraph");
|
||||
dot.Should().Contain("\"app\"");
|
||||
|
||||
var sarif = await reporter.ExportSarifAsync(report, "1.2.3", includeFiltered: true);
|
||||
sarif.Runs.Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user