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

@@ -4,6 +4,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
@@ -12,6 +13,7 @@ using Microsoft.Extensions.Options;
using Microsoft.Extensions.Time.Testing;
using Microsoft.IdentityModel.Tokens;
using StellaOps.Auth.Client;
using StellaOps.AirGap.Policy;
using Xunit;
namespace StellaOps.Auth.Client.Tests;
@@ -73,6 +75,39 @@ public class ServiceCollectionExtensionsTests
Assert.Contains(recordedHandlers, handler => handler.GetType().Name.Contains("PolicyHttpMessageHandler", StringComparison.Ordinal));
}
[Fact]
public void EnsureEgressAllowed_InvokesPolicyWhenAuthorityProvided()
{
var services = new ServiceCollection();
var recordingPolicy = new RecordingPolicy();
services.AddSingleton<IEgressPolicy>(recordingPolicy);
using var provider = services.BuildServiceProvider();
var options = new StellaOpsAuthClientOptions
{
Authority = "https://authority.test",
DiscoveryCacheLifetime = TimeSpan.FromMinutes(1),
JwksCacheLifetime = TimeSpan.FromMinutes(1),
AllowOfflineCacheFallback = false,
};
options.Validate();
var method = typeof(ServiceCollectionExtensions)
.GetMethod("EnsureEgressAllowed", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(method);
method!.Invoke(null, new object?[] { provider, options, "authority-discovery" });
Assert.Single(recordingPolicy.Requests);
var request = recordingPolicy.Requests[0];
Assert.Equal("StellaOpsAuthClient", request.Component);
Assert.Equal(new Uri("https://authority.test"), request.Destination);
Assert.Equal("authority-discovery", request.Intent);
}
private static HttpResponseMessage CreateResponse(HttpStatusCode statusCode, string jsonContent)
{
return new HttpResponseMessage(statusCode)
@@ -224,6 +259,37 @@ public class ServiceCollectionExtensionsTests
}
}
private sealed class RecordingPolicy : IEgressPolicy
{
private readonly List<EgressRequest> requests = new();
public bool IsSealed => true;
public EgressPolicyMode Mode => EgressPolicyMode.Sealed;
public IReadOnlyList<EgressRequest> Requests => requests;
public EgressDecision Evaluate(EgressRequest request)
{
requests.Add(request);
return EgressDecision.Allowed;
}
public ValueTask<EgressDecision> EvaluateAsync(EgressRequest request, CancellationToken cancellationToken = default)
=> new(Evaluate(request));
public void EnsureAllowed(EgressRequest request)
{
requests.Add(request);
}
public ValueTask EnsureAllowedAsync(EgressRequest request, CancellationToken cancellationToken = default)
{
EnsureAllowed(request);
return ValueTask.CompletedTask;
}
}
private sealed class ThrowingTokenClient : IStellaOpsTokenClient
{
public int RequestCount { get; private set; }
@@ -278,11 +344,11 @@ public class ServiceCollectionExtensionsTests
null,
"{}");
return Task.FromResult(result);
}
return Task.FromResult(result);
}
public Task<StellaOpsTokenResult> RequestPasswordTokenAsync(string username, string password, string? scope = null, IReadOnlyDictionary<string, string>? additionalParameters = null, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public Task<StellaOpsTokenResult> RequestPasswordTokenAsync(string username, string password, string? scope = null, IReadOnlyDictionary<string, string>? additionalParameters = null, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public Task<JsonWebKeySet> GetJsonWebKeySetAsync(CancellationToken cancellationToken = default)
=> Task.FromResult(new JsonWebKeySet());