sprints and audit work
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Policy;
|
||||
using StellaOps.Policy.Determinization;
|
||||
using StellaOps.Policy.Determinization.Models;
|
||||
using StellaOps.Policy.Engine.Policies;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Tests.Policies;
|
||||
|
||||
public class DeterminizationPolicyTests
|
||||
{
|
||||
private readonly DeterminizationPolicy _policy;
|
||||
|
||||
public DeterminizationPolicyTests()
|
||||
{
|
||||
var options = Options.Create(new DeterminizationOptions());
|
||||
_policy = new DeterminizationPolicy(options, NullLogger<DeterminizationPolicy>.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_RuntimeEvidenceLoaded_ReturnsEscalated()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
runtime: new SignalState<RuntimeEvidence>
|
||||
{
|
||||
HasValue = true,
|
||||
Value = new RuntimeEvidence { ObservedLoaded = true }
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Escalated);
|
||||
result.MatchedRule.Should().Be("RuntimeEscalation");
|
||||
result.Reason.Should().Contain("Runtime evidence shows vulnerable code loaded");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_HighEpss_ReturnsQuarantined()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
epss: new SignalState<EpssEvidence>
|
||||
{
|
||||
HasValue = true,
|
||||
Value = new EpssEvidence { Score = 0.8 }
|
||||
},
|
||||
environment: DeploymentEnvironment.Production);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Blocked);
|
||||
result.MatchedRule.Should().Be("EpssQuarantine");
|
||||
result.Reason.Should().Contain("EPSS score");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_ReachableCode_ReturnsQuarantined()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
reachability: new SignalState<ReachabilityEvidence>
|
||||
{
|
||||
HasValue = true,
|
||||
Value = new ReachabilityEvidence { IsReachable = true, Confidence = 0.9 }
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Blocked);
|
||||
result.MatchedRule.Should().Be("ReachabilityQuarantine");
|
||||
result.Reason.Should().Contain("reachable");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_HighEntropyInProduction_ReturnsQuarantined()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
entropy: 0.5,
|
||||
environment: DeploymentEnvironment.Production);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Blocked);
|
||||
result.MatchedRule.Should().Be("ProductionEntropyBlock");
|
||||
result.Reason.Should().Contain("High uncertainty");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_StaleEvidence_ReturnsDeferred()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
isStale: true);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Deferred);
|
||||
result.MatchedRule.Should().Be("StaleEvidenceDefer");
|
||||
result.Reason.Should().Contain("stale");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_ModerateUncertaintyInDev_ReturnsGuardedPass()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
entropy: 0.5,
|
||||
trustScore: 0.3,
|
||||
environment: DeploymentEnvironment.Development);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.GuardedPass);
|
||||
result.MatchedRule.Should().Be("GuardedAllowNonProd");
|
||||
result.GuardRails.Should().NotBeNull();
|
||||
result.GuardRails!.EnableMonitoring.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_UnreachableWithHighConfidence_ReturnsAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
reachability: new SignalState<ReachabilityEvidence>
|
||||
{
|
||||
HasValue = true,
|
||||
Value = new ReachabilityEvidence { IsReachable = false, Confidence = 0.9 }
|
||||
},
|
||||
trustScore: 0.8);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Pass);
|
||||
result.MatchedRule.Should().Be("UnreachableAllow");
|
||||
result.Reason.Should().Contain("unreachable");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_VexNotAffected_ReturnsAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
vex: new SignalState<VexClaimSummary>
|
||||
{
|
||||
HasValue = true,
|
||||
Value = new VexClaimSummary { IsNotAffected = true, IssuerTrust = 0.9 }
|
||||
},
|
||||
trustScore: 0.8);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Pass);
|
||||
result.MatchedRule.Should().Be("VexNotAffectedAllow");
|
||||
result.Reason.Should().Contain("not_affected");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_SufficientEvidenceLowEntropy_ReturnsAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
entropy: 0.2,
|
||||
trustScore: 0.8,
|
||||
environment: DeploymentEnvironment.Production);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Pass);
|
||||
result.MatchedRule.Should().Be("SufficientEvidenceAllow");
|
||||
result.Reason.Should().Contain("Sufficient evidence");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_ModerateUncertaintyTier_ReturnsGuardedPass()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
tier: UncertaintyTier.Moderate,
|
||||
trustScore: 0.5,
|
||||
entropy: 0.5);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.GuardedPass);
|
||||
result.MatchedRule.Should().Be("GuardedAllowModerateUncertainty");
|
||||
result.GuardRails.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Evaluate_NoMatchingRule_ReturnsDeferred()
|
||||
{
|
||||
// Arrange
|
||||
var context = CreateContext(
|
||||
entropy: 0.9,
|
||||
trustScore: 0.1,
|
||||
environment: DeploymentEnvironment.Production);
|
||||
|
||||
// Act
|
||||
var result = _policy.Evaluate(context);
|
||||
|
||||
// Assert
|
||||
result.Status.Should().Be(PolicyVerdictStatus.Deferred);
|
||||
result.MatchedRule.Should().Be("DefaultDefer");
|
||||
result.Reason.Should().Contain("Insufficient evidence");
|
||||
}
|
||||
|
||||
private static DeterminizationContext CreateContext(
|
||||
SignalState<EpssEvidence>? epss = null,
|
||||
SignalState<VexClaimSummary>? vex = null,
|
||||
SignalState<ReachabilityEvidence>? reachability = null,
|
||||
SignalState<RuntimeEvidence>? runtime = null,
|
||||
double entropy = 0.0,
|
||||
double trustScore = 0.0,
|
||||
UncertaintyTier tier = UncertaintyTier.Minimal,
|
||||
DeploymentEnvironment environment = DeploymentEnvironment.Development,
|
||||
bool isStale = false)
|
||||
{
|
||||
var snapshot = new SignalSnapshot
|
||||
{
|
||||
Cve = "CVE-2024-0001",
|
||||
Purl = "pkg:npm/test@1.0.0",
|
||||
Epss = epss ?? SignalState<EpssEvidence>.NotQueried(),
|
||||
Vex = vex ?? SignalState<VexClaimSummary>.NotQueried(),
|
||||
Reachability = reachability ?? SignalState<ReachabilityEvidence>.NotQueried(),
|
||||
Runtime = runtime ?? SignalState<RuntimeEvidence>.NotQueried(),
|
||||
Backport = SignalState<BackportEvidence>.NotQueried(),
|
||||
Sbom = SignalState<SbomLineageEvidence>.NotQueried(),
|
||||
Cvss = SignalState<CvssEvidence>.NotQueried(),
|
||||
SnapshotAt = DateTimeOffset.UtcNow
|
||||
};
|
||||
|
||||
return new DeterminizationContext
|
||||
{
|
||||
SignalSnapshot = snapshot,
|
||||
UncertaintyScore = new UncertaintyScore
|
||||
{
|
||||
Entropy = entropy,
|
||||
Tier = tier,
|
||||
Completeness = 1.0 - entropy,
|
||||
MissingSignals = []
|
||||
},
|
||||
Decay = new ObservationDecay
|
||||
{
|
||||
LastSignalUpdate = DateTimeOffset.UtcNow.AddDays(-1),
|
||||
AgeDays = 1,
|
||||
DecayedMultiplier = isStale ? 0.3 : 0.9,
|
||||
IsStale = isStale
|
||||
},
|
||||
TrustScore = trustScore,
|
||||
Environment = environment
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user