Add unit tests for SBOM ingestion and transformation
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implement `SbomIngestServiceCollectionExtensionsTests` to verify the SBOM ingestion pipeline exports snapshots correctly. - Create `SbomIngestTransformerTests` to ensure the transformation produces expected nodes and edges, including deduplication of license nodes and normalization of timestamps. - Add `SbomSnapshotExporterTests` to test the export functionality for manifest, adjacency, nodes, and edges. - Introduce `VexOverlayTransformerTests` to validate the transformation of VEX nodes and edges. - Set up project file for the test project with necessary dependencies and configurations. - Include JSON fixture files for testing purposes.
This commit is contained in:
@@ -39,6 +39,9 @@ internal sealed class IssuerDirectoryClient : IIssuerDirectoryClient
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(issuerId);
|
||||
|
||||
tenantId = tenantId.Trim();
|
||||
issuerId = issuerId.Trim();
|
||||
|
||||
var cacheKey = CacheKey("keys", tenantId, issuerId, includeGlobal.ToString(CultureInfo.InvariantCulture));
|
||||
if (_cache.TryGetValue(cacheKey, out IReadOnlyList<IssuerKeyModel>? cached) && cached is not null)
|
||||
{
|
||||
@@ -77,6 +80,9 @@ internal sealed class IssuerDirectoryClient : IIssuerDirectoryClient
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(issuerId);
|
||||
|
||||
tenantId = tenantId.Trim();
|
||||
issuerId = issuerId.Trim();
|
||||
|
||||
var cacheKey = CacheKey("trust", tenantId, issuerId, includeGlobal.ToString(CultureInfo.InvariantCulture));
|
||||
if (_cache.TryGetValue(cacheKey, out IssuerTrustResponseModel? cached) && cached is not null)
|
||||
{
|
||||
@@ -105,6 +111,84 @@ internal sealed class IssuerDirectoryClient : IIssuerDirectoryClient
|
||||
return payload;
|
||||
}
|
||||
|
||||
public async ValueTask<IssuerTrustResponseModel> SetIssuerTrustAsync(
|
||||
string tenantId,
|
||||
string issuerId,
|
||||
decimal weight,
|
||||
string? reason,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(issuerId);
|
||||
|
||||
var normalizedTenant = tenantId.Trim();
|
||||
var normalizedReason = string.IsNullOrWhiteSpace(reason) ? null : reason.Trim();
|
||||
var requestUri = $"issuer-directory/issuers/{Uri.EscapeDataString(issuerId)}/trust";
|
||||
|
||||
using var request = new HttpRequestMessage(HttpMethod.Put, requestUri)
|
||||
{
|
||||
Content = JsonContent.Create(new IssuerTrustSetRequestModel(weight, normalizedReason))
|
||||
};
|
||||
|
||||
request.Headers.TryAddWithoutValidation(_options.TenantHeader, normalizedTenant);
|
||||
if (!string.IsNullOrWhiteSpace(normalizedReason))
|
||||
{
|
||||
request.Headers.TryAddWithoutValidation(_options.AuditReasonHeader, normalizedReason);
|
||||
}
|
||||
|
||||
using var response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Issuer Directory trust update failed for {IssuerId} (tenant={TenantId}) {StatusCode}",
|
||||
issuerId,
|
||||
normalizedTenant,
|
||||
response.StatusCode);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
InvalidateTrustCache(normalizedTenant, issuerId);
|
||||
|
||||
var payload = await response.Content.ReadFromJsonAsync<IssuerTrustResponseModel>(cancellationToken: cancellationToken)
|
||||
.ConfigureAwait(false) ?? new IssuerTrustResponseModel(null, null, 0m);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
public async ValueTask DeleteIssuerTrustAsync(
|
||||
string tenantId,
|
||||
string issuerId,
|
||||
string? reason,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(issuerId);
|
||||
|
||||
var normalizedTenant = tenantId.Trim();
|
||||
var normalizedReason = string.IsNullOrWhiteSpace(reason) ? null : reason.Trim();
|
||||
var requestUri = $"issuer-directory/issuers/{Uri.EscapeDataString(issuerId)}/trust";
|
||||
|
||||
using var request = new HttpRequestMessage(HttpMethod.Delete, requestUri);
|
||||
request.Headers.TryAddWithoutValidation(_options.TenantHeader, normalizedTenant);
|
||||
if (!string.IsNullOrWhiteSpace(normalizedReason))
|
||||
{
|
||||
request.Headers.TryAddWithoutValidation(_options.AuditReasonHeader, normalizedReason);
|
||||
}
|
||||
|
||||
using var response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Issuer Directory trust delete failed for {IssuerId} (tenant={TenantId}) {StatusCode}",
|
||||
issuerId,
|
||||
normalizedTenant,
|
||||
response.StatusCode);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
InvalidateTrustCache(normalizedTenant, issuerId);
|
||||
}
|
||||
|
||||
private static string CacheKey(string prefix, params string[] parts)
|
||||
{
|
||||
if (parts is null || parts.Length == 0)
|
||||
@@ -117,4 +201,11 @@ internal sealed class IssuerDirectoryClient : IIssuerDirectoryClient
|
||||
Array.Copy(parts, 0, segments, 1, parts.Length);
|
||||
return string.Join('|', segments);
|
||||
}
|
||||
|
||||
private void InvalidateTrustCache(string tenantId, string issuerId)
|
||||
{
|
||||
_cache.Remove(CacheKey("trust", tenantId, issuerId, bool.FalseString));
|
||||
_cache.Remove(CacheKey("trust", tenantId, issuerId, bool.TrueString));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user