feat: Initialize Zastava Webhook service with TLS and Authority authentication
- Added Program.cs to set up the web application with Serilog for logging, health check endpoints, and a placeholder admission endpoint. - Configured Kestrel server to use TLS 1.3 and handle client certificates appropriately. - Created StellaOps.Zastava.Webhook.csproj with necessary dependencies including Serilog and Polly. - Documented tasks in TASKS.md for the Zastava Webhook project, outlining current work and exit criteria for each task.
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Attestor.Core.Options;
|
||||
using StellaOps.Attestor.Core.Submission;
|
||||
using StellaOps.Attestor.Core.Observability;
|
||||
using StellaOps.Attestor.Infrastructure.Rekor;
|
||||
using StellaOps.Attestor.Infrastructure.Storage;
|
||||
using StellaOps.Attestor.Infrastructure.Submission;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Attestor.Tests;
|
||||
|
||||
public sealed class AttestorSubmissionServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task SubmitAsync_ReturnsDeterministicUuid_OnDuplicateBundle()
|
||||
{
|
||||
var options = Options.Create(new AttestorOptions
|
||||
{
|
||||
Redis = new AttestorOptions.RedisOptions
|
||||
{
|
||||
Url = string.Empty
|
||||
},
|
||||
Rekor = new AttestorOptions.RekorOptions
|
||||
{
|
||||
Primary = new AttestorOptions.RekorBackendOptions
|
||||
{
|
||||
Url = "https://rekor.stellaops.test",
|
||||
ProofTimeoutMs = 1000,
|
||||
PollIntervalMs = 50,
|
||||
MaxAttempts = 2
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var canonicalizer = new DefaultDsseCanonicalizer();
|
||||
var validator = new AttestorSubmissionValidator(canonicalizer);
|
||||
var repository = new InMemoryAttestorEntryRepository();
|
||||
var dedupeStore = new InMemoryAttestorDedupeStore();
|
||||
var rekorClient = new StubRekorClient(new NullLogger<StubRekorClient>());
|
||||
var archiveStore = new NullAttestorArchiveStore(new NullLogger<NullAttestorArchiveStore>());
|
||||
var auditSink = new InMemoryAttestorAuditSink();
|
||||
var logger = new NullLogger<AttestorSubmissionService>();
|
||||
using var metrics = new AttestorMetrics();
|
||||
var service = new AttestorSubmissionService(
|
||||
validator,
|
||||
repository,
|
||||
dedupeStore,
|
||||
rekorClient,
|
||||
archiveStore,
|
||||
auditSink,
|
||||
options,
|
||||
logger,
|
||||
TimeProvider.System,
|
||||
metrics);
|
||||
|
||||
var request = CreateValidRequest(canonicalizer);
|
||||
var context = new SubmissionContext
|
||||
{
|
||||
CallerSubject = "urn:stellaops:signer",
|
||||
CallerAudience = "attestor",
|
||||
CallerClientId = "signer-service",
|
||||
CallerTenant = "default",
|
||||
ClientCertificate = null,
|
||||
MtlsThumbprint = "00"
|
||||
};
|
||||
|
||||
var first = await service.SubmitAsync(request, context);
|
||||
var second = await service.SubmitAsync(request, context);
|
||||
|
||||
Assert.NotNull(first.Uuid);
|
||||
Assert.Equal(first.Uuid, second.Uuid);
|
||||
|
||||
var stored = await repository.GetByBundleShaAsync(request.Meta.BundleSha256);
|
||||
Assert.NotNull(stored);
|
||||
Assert.Equal(first.Uuid, stored!.RekorUuid);
|
||||
}
|
||||
|
||||
private static AttestorSubmissionRequest CreateValidRequest(DefaultDsseCanonicalizer canonicalizer)
|
||||
{
|
||||
var request = new AttestorSubmissionRequest
|
||||
{
|
||||
Bundle = new AttestorSubmissionRequest.SubmissionBundle
|
||||
{
|
||||
Mode = "keyless",
|
||||
Dsse = new AttestorSubmissionRequest.DsseEnvelope
|
||||
{
|
||||
PayloadType = "application/vnd.in-toto+json",
|
||||
PayloadBase64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("{}")),
|
||||
Signatures =
|
||||
{
|
||||
new AttestorSubmissionRequest.DsseSignature
|
||||
{
|
||||
KeyId = "test",
|
||||
Signature = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Meta = new AttestorSubmissionRequest.SubmissionMeta
|
||||
{
|
||||
Artifact = new AttestorSubmissionRequest.ArtifactInfo
|
||||
{
|
||||
Sha256 = new string('a', 64),
|
||||
Kind = "sbom"
|
||||
},
|
||||
LogPreference = "primary",
|
||||
Archive = false
|
||||
}
|
||||
};
|
||||
|
||||
var canonical = canonicalizer.CanonicalizeAsync(request).GetAwaiter().GetResult();
|
||||
request.Meta.BundleSha256 = Convert.ToHexString(SHA256.HashData(canonical)).ToLowerInvariant();
|
||||
return request;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user