audit, advisories and doctors/setup work
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Moq.Protected;
|
||||
using StellaOps.SbomService.Models;
|
||||
using StellaOps.SbomService.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.SbomService.Tests;
|
||||
|
||||
public sealed class ScanJobEmitterServiceTests
|
||||
{
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public async Task SubmitScanAsync_RejectsDisallowedScannerHost()
|
||||
{
|
||||
// Arrange
|
||||
var configuration = BuildConfiguration("http://blocked.example.com");
|
||||
var httpClientFactory = new Mock<IHttpClientFactory>();
|
||||
httpClientFactory
|
||||
.Setup(f => f.CreateClient(It.IsAny<string>()))
|
||||
.Returns(new HttpClient(new Mock<HttpMessageHandler>().Object));
|
||||
|
||||
var service = new ScanJobEmitterService(
|
||||
httpClientFactory.Object,
|
||||
configuration,
|
||||
NullLogger<ScanJobEmitterService>.Instance,
|
||||
Options.Create(new ScannerHttpOptions
|
||||
{
|
||||
AllowedHosts = new List<string> { "scanner.local" }
|
||||
}),
|
||||
new QueueGuidProvider(new[] { Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa") }));
|
||||
|
||||
var request = new ScanJobRequest(
|
||||
ImageReference: "library/nginx:latest",
|
||||
Digest: "sha256:deadbeef",
|
||||
Platform: "linux/amd64",
|
||||
Force: false,
|
||||
ClientRequestId: null,
|
||||
SourceId: "source-1",
|
||||
TriggerType: "manual");
|
||||
|
||||
// Act
|
||||
var result = await service.SubmitScanAsync(request);
|
||||
|
||||
// Assert
|
||||
result.Success.Should().BeFalse();
|
||||
result.Error.Should().Contain("allowlisted");
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
[Fact]
|
||||
public async Task SubmitBatchScanAsync_UsesDeterministicRequestId()
|
||||
{
|
||||
// Arrange
|
||||
var configuration = BuildConfiguration("http://scanner.local");
|
||||
var handler = new Mock<HttpMessageHandler>();
|
||||
HttpRequestMessage? captured = null;
|
||||
|
||||
handler
|
||||
.Protected()
|
||||
.Setup<Task<HttpResponseMessage>>(
|
||||
"SendAsync",
|
||||
ItExpr.IsAny<HttpRequestMessage>(),
|
||||
ItExpr.IsAny<CancellationToken>())
|
||||
.Callback<HttpRequestMessage, CancellationToken>((request, _) => captured = request)
|
||||
.ReturnsAsync(new HttpResponseMessage
|
||||
{
|
||||
StatusCode = HttpStatusCode.OK,
|
||||
Content = new StringContent("{\"snapshot\":{\"id\":\"job-123\",\"status\":\"queued\"},\"created\":true}")
|
||||
});
|
||||
|
||||
var httpClientFactory = new Mock<IHttpClientFactory>();
|
||||
httpClientFactory
|
||||
.Setup(f => f.CreateClient(It.IsAny<string>()))
|
||||
.Returns(new HttpClient(handler.Object));
|
||||
|
||||
var service = new ScanJobEmitterService(
|
||||
httpClientFactory.Object,
|
||||
configuration,
|
||||
NullLogger<ScanJobEmitterService>.Instance,
|
||||
Options.Create(new ScannerHttpOptions
|
||||
{
|
||||
AllowedHosts = new List<string> { "scanner.local" }
|
||||
}),
|
||||
new QueueGuidProvider(new[] { Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb") }));
|
||||
|
||||
var images = new[]
|
||||
{
|
||||
new DiscoveredImage("library/nginx", "latest", "sha256:deadbeef")
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await service.SubmitBatchScanAsync("source-1", images);
|
||||
|
||||
// Assert
|
||||
result.Submitted.Should().Be(1);
|
||||
captured.Should().NotBeNull();
|
||||
|
||||
var payload = await captured!.Content!.ReadAsStringAsync();
|
||||
using var doc = JsonDocument.Parse(payload);
|
||||
var clientRequestId = doc.RootElement.GetProperty("clientRequestId").GetString();
|
||||
clientRequestId.Should().Be("registry-source-1-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
|
||||
}
|
||||
|
||||
private static IConfiguration BuildConfiguration(string scannerUrl)
|
||||
{
|
||||
return new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["SbomService:ScannerUrl"] = scannerUrl,
|
||||
["SbomService:BatchScanSize"] = "1",
|
||||
["SbomService:BatchScanDelayMs"] = "0"
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user