feat: Implement vulnerability token signing and verification utilities
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added VulnTokenSigner for signing JWT tokens with specified algorithms and keys.
- Introduced VulnTokenUtilities for resolving tenant and subject claims, and sanitizing context dictionaries.
- Created VulnTokenVerificationUtilities for parsing tokens, verifying signatures, and deserializing payloads.
- Developed VulnWorkflowAntiForgeryTokenIssuer for issuing anti-forgery tokens with configurable options.
- Implemented VulnWorkflowAntiForgeryTokenVerifier for verifying anti-forgery tokens and validating payloads.
- Added AuthorityVulnerabilityExplorerOptions to manage configuration for vulnerability explorer features.
- Included tests for FilesystemPackRunDispatcher to ensure proper job handling under egress policy restrictions.
This commit is contained in:
master
2025-11-03 10:02:29 +02:00
parent bf2bf4b395
commit b1e78fe412
215 changed files with 19441 additions and 12185 deletions

View File

@@ -1,110 +1,110 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using FluentAssertions;
using StellaOps.Scheduler.Models;
using Xunit;
namespace StellaOps.Scheduler.Queue.Tests;
public sealed class PlannerAndRunnerMessageTests
{
[Fact]
public void PlannerMessage_CanonicalSerialization_RoundTrips()
{
var schedule = new Schedule(
id: "sch-tenant-nightly",
tenantId: "tenant-alpha",
name: "Nightly Deltas",
enabled: true,
cronExpression: "0 2 * * *",
timezone: "UTC",
mode: ScheduleMode.AnalysisOnly,
selection: new Selector(SelectorScope.AllImages, tenantId: "tenant-alpha"),
onlyIf: new ScheduleOnlyIf(lastReportOlderThanDays: 3),
notify: new ScheduleNotify(onNewFindings: true, SeverityRank.High, includeKev: true),
limits: new ScheduleLimits(maxJobs: 10, ratePerSecond: 5, parallelism: 3),
createdAt: DateTimeOffset.Parse("2025-10-01T02:00:00Z"),
createdBy: "system",
updatedAt: DateTimeOffset.Parse("2025-10-02T02:00:00Z"),
updatedBy: "system",
subscribers: ImmutableArray<string>.Empty,
schemaVersion: "1.0.0");
var run = new Run(
id: "run-123",
tenantId: "tenant-alpha",
trigger: RunTrigger.Cron,
state: RunState.Planning,
stats: new RunStats(candidates: 5, deduped: 4, queued: 0, completed: 0, deltas: 0),
createdAt: DateTimeOffset.Parse("2025-10-02T02:05:00Z"),
reason: new RunReason(manualReason: null, feedserExportId: null, vexerExportId: null, cursor: null)
with { ImpactWindowFrom = "2025-10-01T00:00:00Z", ImpactWindowTo = "2025-10-02T00:00:00Z" },
scheduleId: "sch-tenant-nightly");
var impactSet = new ImpactSet(
selector: new Selector(SelectorScope.AllImages, tenantId: "tenant-alpha"),
images: new[]
{
new ImpactImage(
imageDigest: "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
registry: "registry",
repository: "repo",
namespaces: new[] { "prod" },
tags: new[] { "latest" },
usedByEntrypoint: true,
labels: new[] { KeyValuePair.Create("team", "appsec") })
},
usageOnly: true,
generatedAt: DateTimeOffset.Parse("2025-10-02T02:06:00Z"),
total: 1,
snapshotId: "snap-001");
var message = new PlannerQueueMessage(run, impactSet, schedule, correlationId: "corr-1");
var json = CanonicalJsonSerializer.Serialize(message);
var roundTrip = CanonicalJsonSerializer.Deserialize<PlannerQueueMessage>(json);
roundTrip.Should().BeEquivalentTo(message, options => options.WithStrictOrdering());
}
[Fact]
public void RunnerSegmentMessage_RequiresAtLeastOneDigest()
{
var act = () => new RunnerSegmentQueueMessage(
segmentId: "segment-empty",
runId: "run-123",
tenantId: "tenant-alpha",
imageDigests: Array.Empty<string>());
act.Should().Throw<ArgumentException>();
}
[Fact]
public void RunnerSegmentMessage_CanonicalSerialization_RoundTrips()
{
var message = new RunnerSegmentQueueMessage(
segmentId: "segment-01",
runId: "run-123",
tenantId: "tenant-alpha",
imageDigests: new[]
{
"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
scheduleId: "sch-tenant-nightly",
ratePerSecond: 25,
usageOnly: true,
attributes: new Dictionary<string, string>
{
["plannerShard"] = "0",
["priority"] = "kev"
},
correlationId: "corr-2");
var json = CanonicalJsonSerializer.Serialize(message);
var roundTrip = CanonicalJsonSerializer.Deserialize<RunnerSegmentQueueMessage>(json);
roundTrip.Should().BeEquivalentTo(message, options => options.WithStrictOrdering());
}
}
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using FluentAssertions;
using StellaOps.Scheduler.Models;
using Xunit;
namespace StellaOps.Scheduler.Queue.Tests;
public sealed class PlannerAndRunnerMessageTests
{
[Fact]
public void PlannerMessage_CanonicalSerialization_RoundTrips()
{
var schedule = new Schedule(
id: "sch-tenant-nightly",
tenantId: "tenant-alpha",
name: "Nightly Deltas",
enabled: true,
cronExpression: "0 2 * * *",
timezone: "UTC",
mode: ScheduleMode.AnalysisOnly,
selection: new Selector(SelectorScope.AllImages, tenantId: "tenant-alpha"),
onlyIf: new ScheduleOnlyIf(lastReportOlderThanDays: 3),
notify: new ScheduleNotify(onNewFindings: true, SeverityRank.High, includeKev: true),
limits: new ScheduleLimits(maxJobs: 10, ratePerSecond: 5, parallelism: 3),
createdAt: DateTimeOffset.Parse("2025-10-01T02:00:00Z"),
createdBy: "system",
updatedAt: DateTimeOffset.Parse("2025-10-02T02:00:00Z"),
updatedBy: "system",
subscribers: ImmutableArray<string>.Empty,
schemaVersion: "1.0.0");
var run = new Run(
id: "run-123",
tenantId: "tenant-alpha",
trigger: RunTrigger.Cron,
state: RunState.Planning,
stats: new RunStats(candidates: 5, deduped: 4, queued: 0, completed: 0, deltas: 0),
createdAt: DateTimeOffset.Parse("2025-10-02T02:05:00Z"),
reason: new RunReason(manualReason: null, conselierExportId: null, excitorExportId: null, cursor: null)
with { ImpactWindowFrom = "2025-10-01T00:00:00Z", ImpactWindowTo = "2025-10-02T00:00:00Z" },
scheduleId: "sch-tenant-nightly");
var impactSet = new ImpactSet(
selector: new Selector(SelectorScope.AllImages, tenantId: "tenant-alpha"),
images: new[]
{
new ImpactImage(
imageDigest: "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
registry: "registry",
repository: "repo",
namespaces: new[] { "prod" },
tags: new[] { "latest" },
usedByEntrypoint: true,
labels: new[] { KeyValuePair.Create("team", "appsec") })
},
usageOnly: true,
generatedAt: DateTimeOffset.Parse("2025-10-02T02:06:00Z"),
total: 1,
snapshotId: "snap-001");
var message = new PlannerQueueMessage(run, impactSet, schedule, correlationId: "corr-1");
var json = CanonicalJsonSerializer.Serialize(message);
var roundTrip = CanonicalJsonSerializer.Deserialize<PlannerQueueMessage>(json);
roundTrip.Should().BeEquivalentTo(message, options => options.WithStrictOrdering());
}
[Fact]
public void RunnerSegmentMessage_RequiresAtLeastOneDigest()
{
var act = () => new RunnerSegmentQueueMessage(
segmentId: "segment-empty",
runId: "run-123",
tenantId: "tenant-alpha",
imageDigests: Array.Empty<string>());
act.Should().Throw<ArgumentException>();
}
[Fact]
public void RunnerSegmentMessage_CanonicalSerialization_RoundTrips()
{
var message = new RunnerSegmentQueueMessage(
segmentId: "segment-01",
runId: "run-123",
tenantId: "tenant-alpha",
imageDigests: new[]
{
"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
scheduleId: "sch-tenant-nightly",
ratePerSecond: 25,
usageOnly: true,
attributes: new Dictionary<string, string>
{
["plannerShard"] = "0",
["priority"] = "kev"
},
correlationId: "corr-2");
var json = CanonicalJsonSerializer.Serialize(message);
var roundTrip = CanonicalJsonSerializer.Deserialize<RunnerSegmentQueueMessage>(json);
roundTrip.Should().BeEquivalentTo(message, options => options.WithStrictOrdering());
}
}