using System; using System.Net.Http; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; using StellaOps.Scanner.Sbomer.BuildXPlugin.Descriptor; namespace StellaOps.Scanner.Sbomer.BuildXPlugin.Attestation; /// /// Sends provenance placeholders to the Attestor service for asynchronous DSSE signing. /// public sealed class AttestorClient { private readonly HttpClient httpClient; public AttestorClient(HttpClient httpClient) { this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); } public async Task SendPlaceholderAsync(Uri attestorUri, DescriptorDocument document, CancellationToken cancellationToken) { if (attestorUri is null) { throw new ArgumentNullException(nameof(attestorUri)); } if (document is null) { throw new ArgumentNullException(nameof(document)); } var payload = new AttestorProvenanceRequest( ImageDigest: document.Subject.Digest, SbomDigest: document.Artifact.Digest, ExpectedDsseSha256: document.Provenance.ExpectedDsseSha256, Nonce: document.Provenance.Nonce, PredicateType: document.Provenance.PredicateType, Schema: document.Schema); using var response = await httpClient.PostAsJsonAsync(attestorUri, payload, cancellationToken).ConfigureAwait(false); if (!response.IsSuccessStatusCode) { var body = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false); throw new BuildxPluginException($"Attestor rejected provenance placeholder ({(int)response.StatusCode}): {body}"); } } }