work
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using System.Security.Cryptography;
|
||||
using StellaOps.Policy.Engine.Streaming;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Services;
|
||||
|
||||
public sealed partial class PolicyEvaluationService
|
||||
{
|
||||
public Task<JsonObject> EvaluatePathScopeAsync(
|
||||
PathScopeSimulationRequest request,
|
||||
PathScopeTarget target,
|
||||
CancellationToken ct)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
var stableKey = string.Create(CultureInfo.InvariantCulture, $"{request.BasePolicyRef}|{request.CandidatePolicyRef}|{target.FilePath}|{target.Pattern}");
|
||||
var verdictDelta = ComputeDelta(stableKey);
|
||||
|
||||
var finding = new JsonObject
|
||||
{
|
||||
["id"] = target.EvidenceHash ?? "stub-ghsa",
|
||||
["ruleId"] = "policy.rules.path-scope.stub",
|
||||
["severity"] = "info",
|
||||
["verdict"] = new JsonObject
|
||||
{
|
||||
["base"] = verdictDelta.baseVerdict,
|
||||
["candidate"] = verdictDelta.candidateVerdict,
|
||||
["delta"] = verdictDelta.delta
|
||||
},
|
||||
["evidence"] = new JsonObject
|
||||
{
|
||||
["locator"] = new JsonObject
|
||||
{
|
||||
["filePath"] = target.FilePath,
|
||||
["digest"] = target.Digest
|
||||
},
|
||||
["provenance"] = new JsonObject
|
||||
{
|
||||
["ingestedAt"] = target.IngestedAt?.ToString("O", CultureInfo.InvariantCulture),
|
||||
["connectorId"] = target.ConnectorId
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var envelope = new JsonObject
|
||||
{
|
||||
["tenant"] = request.Tenant,
|
||||
["subject"] = JsonSerializer.SerializeToNode(request.Subject, SerializerOptions),
|
||||
["target"] = new JsonObject
|
||||
{
|
||||
["filePath"] = target.FilePath,
|
||||
["pattern"] = target.Pattern,
|
||||
["pathMatch"] = target.PathMatch,
|
||||
["confidence"] = target.Confidence,
|
||||
["evidenceHash"] = target.EvidenceHash
|
||||
},
|
||||
["finding"] = finding,
|
||||
["trace"] = new JsonArray
|
||||
{
|
||||
new JsonObject { ["step"] = "match", ["path"] = target.FilePath },
|
||||
new JsonObject { ["step"] = "decision", ["effect"] = verdictDelta.candidateVerdict }
|
||||
},
|
||||
["metrics"] = new JsonObject
|
||||
{
|
||||
["evalTicks"] = stableKey.Length,
|
||||
["rulesEvaluated"] = 1,
|
||||
["bindings"] = 1
|
||||
}
|
||||
};
|
||||
|
||||
return Task.FromResult(envelope);
|
||||
}
|
||||
|
||||
private static (string baseVerdict, string candidateVerdict, string delta) ComputeDelta(string stableKey)
|
||||
{
|
||||
// Deterministic pseudo verdict using SHA-256 over the stable key.
|
||||
Span<byte> hashBytes = stackalloc byte[32];
|
||||
SHA256.HashData(Encoding.UTF8.GetBytes(stableKey), hashBytes);
|
||||
|
||||
// Use lowest byte to determine delta.
|
||||
var flag = hashBytes[0];
|
||||
var baseVerdict = "deny";
|
||||
var candidateVerdict = (flag & 1) == 0 ? "warn" : "deny";
|
||||
var delta = baseVerdict == candidateVerdict ? "unchanged" : "softened";
|
||||
return (baseVerdict, candidateVerdict, delta);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,27 @@
|
||||
using System.Collections.Immutable;
|
||||
using StellaOps.Policy.Engine.Compilation;
|
||||
using StellaOps.Policy.Engine.Evaluation;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Services;
|
||||
|
||||
internal sealed class PolicyEvaluationService
|
||||
{
|
||||
private readonly PolicyEvaluator evaluator = new();
|
||||
|
||||
public PolicyEvaluationResult Evaluate(PolicyIrDocument document, PolicyEvaluationContext context)
|
||||
{
|
||||
if (document is null)
|
||||
{
|
||||
using System.Collections.Immutable;
|
||||
using StellaOps.Policy.Engine.Compilation;
|
||||
using StellaOps.Policy.Engine.Evaluation;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Services;
|
||||
|
||||
internal sealed class PolicyEvaluationService
|
||||
{
|
||||
private readonly PolicyEvaluator evaluator = new();
|
||||
private readonly PathScopeMetrics _pathMetrics;
|
||||
|
||||
public PolicyEvaluationService() : this(new PathScopeMetrics())
|
||||
{
|
||||
}
|
||||
|
||||
public PolicyEvaluationService(PathScopeMetrics pathMetrics)
|
||||
{
|
||||
_pathMetrics = pathMetrics ?? throw new ArgumentNullException(nameof(pathMetrics));
|
||||
}
|
||||
|
||||
public PolicyEvaluationResult Evaluate(PolicyIrDocument document, PolicyEvaluationContext context)
|
||||
{
|
||||
if (document is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
@@ -19,8 +29,10 @@ internal sealed class PolicyEvaluationService
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var request = new PolicyEvaluationRequest(document, context);
|
||||
return evaluator.Evaluate(request);
|
||||
}
|
||||
}
|
||||
|
||||
var request = new PolicyEvaluationRequest(document, context);
|
||||
return evaluator.Evaluate(request);
|
||||
}
|
||||
|
||||
// PathScopeSimulationService partial class relies on _pathMetrics.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user