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

@@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
namespace StellaOps.Configuration;
/// <summary>
/// Options controlling vulnerability explorer specific features exposed by Authority.
/// </summary>
public sealed class AuthorityVulnerabilityExplorerOptions
{
/// <summary>
/// Workflow-oriented configuration (anti-forgery tokens, CSRF enforcement helpers).
/// </summary>
public AuthorityVulnWorkflowOptions Workflow { get; } = new();
/// <summary>
/// Attachment handling configuration (signed access tokens).
/// </summary>
public AuthorityVulnAttachmentOptions Attachments { get; } = new();
internal void Validate()
{
Workflow.Validate();
Attachments.Validate();
}
}
/// <summary>
/// Workflow specific configuration for Vuln Explorer clients.
/// </summary>
public sealed class AuthorityVulnWorkflowOptions
{
/// <summary>
/// Anti-forgery token configuration.
/// </summary>
public AuthorityVulnAntiForgeryOptions AntiForgery { get; } = new();
internal void Validate()
{
AntiForgery.Validate();
}
}
/// <summary>
/// Anti-forgery token configuration used to protect workflow submissions.
/// </summary>
public sealed class AuthorityVulnAntiForgeryOptions
{
/// <summary>
/// Determines whether anti-forgery token issuance/verification is enabled.
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// Audience claim value embedded in issued tokens.
/// </summary>
public string Audience { get; set; } = "stellaops:vuln-workflow";
/// <summary>
/// Default lifetime applied when callers omit an explicit expiration.
/// </summary>
public TimeSpan DefaultLifetime { get; set; } = TimeSpan.FromMinutes(10);
/// <summary>
/// Maximum lifetime permitted for anti-forgery tokens.
/// </summary>
public TimeSpan MaxLifetime { get; set; } = TimeSpan.FromMinutes(30);
/// <summary>
/// Optional maximum size for the context dictionary payload.
/// </summary>
public int MaxContextEntries { get; set; } = 16;
/// <summary>
/// Maximum length permitted per context value entry.
/// </summary>
public int MaxContextValueLength { get; set; } = 256;
internal void Validate()
{
if (!Enabled)
{
return;
}
if (string.IsNullOrWhiteSpace(Audience))
{
throw new InvalidOperationException("vulnerabilityExplorer.workflow.antiForgery.audience must be specified when anti-forgery tokens are enabled.");
}
if (DefaultLifetime <= TimeSpan.Zero)
{
throw new InvalidOperationException("vulnerabilityExplorer.workflow.antiForgery.defaultLifetime must be greater than zero.");
}
if (MaxLifetime <= TimeSpan.Zero || MaxLifetime < DefaultLifetime)
{
throw new InvalidOperationException("vulnerabilityExplorer.workflow.antiForgery.maxLifetime must be greater than zero and greater than or equal to defaultLifetime.");
}
if (MaxContextEntries < 0)
{
throw new InvalidOperationException("vulnerabilityExplorer.workflow.antiForgery.maxContextEntries must be non-negative.");
}
if (MaxContextValueLength <= 0)
{
throw new InvalidOperationException("vulnerabilityExplorer.workflow.antiForgery.maxContextValueLength must be greater than zero.");
}
}
}
/// <summary>
/// Attachment token configuration used to protect ledger attachments.
/// </summary>
public sealed class AuthorityVulnAttachmentOptions
{
/// <summary>
/// Determines whether attachment token issuance/verification is enabled.
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// Default lifetime for attachment access tokens.
/// </summary>
public TimeSpan DefaultLifetime { get; set; } = TimeSpan.FromMinutes(30);
/// <summary>
/// Maximum lifetime permitted for attachment access tokens.
/// </summary>
public TimeSpan MaxLifetime { get; set; } = TimeSpan.FromHours(4);
/// <summary>
/// Payload type identifier emitted in audit and downstream validation.
/// </summary>
public string PayloadType { get; set; } = "application/vnd.stellaops.vuln-attachment-token+json";
/// <summary>
/// Optional limit on attachment metadata entries.
/// </summary>
public int MaxMetadataEntries { get; set; } = 16;
/// <summary>
/// Optional maximum length for metadata values.
/// </summary>
public int MaxMetadataValueLength { get; set; } = 512;
internal void Validate()
{
if (!Enabled)
{
return;
}
if (DefaultLifetime <= TimeSpan.Zero)
{
throw new InvalidOperationException("vulnerabilityExplorer.attachments.defaultLifetime must be greater than zero when attachment tokens are enabled.");
}
if (MaxLifetime <= TimeSpan.Zero || MaxLifetime < DefaultLifetime)
{
throw new InvalidOperationException("vulnerabilityExplorer.attachments.maxLifetime must be greater than zero and greater than or equal to defaultLifetime.");
}
if (string.IsNullOrWhiteSpace(PayloadType))
{
throw new InvalidOperationException("vulnerabilityExplorer.attachments.payloadType must be specified when attachment tokens are enabled.");
}
if (MaxMetadataEntries < 0)
{
throw new InvalidOperationException("vulnerabilityExplorer.attachments.maxMetadataEntries must be non-negative.");
}
if (MaxMetadataValueLength <= 0)
{
throw new InvalidOperationException("vulnerabilityExplorer.attachments.maxMetadataValueLength must be greater than zero.");
}
}
}