Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
293 lines
8.5 KiB
C#
293 lines
8.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace StellaOps.Cli.Services.Models;
|
|
|
|
// CLI-LNM-22-002: VEX observation models for CLI commands
|
|
|
|
/// <summary>
|
|
/// Query options for VEX observations.
|
|
/// </summary>
|
|
internal sealed class VexObservationQuery
|
|
{
|
|
[JsonPropertyName("tenant")]
|
|
public string Tenant { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("vulnerabilityIds")]
|
|
public IReadOnlyList<string> VulnerabilityIds { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("productKeys")]
|
|
public IReadOnlyList<string> ProductKeys { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("purls")]
|
|
public IReadOnlyList<string> Purls { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("cpes")]
|
|
public IReadOnlyList<string> Cpes { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("statuses")]
|
|
public IReadOnlyList<string> Statuses { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("providerIds")]
|
|
public IReadOnlyList<string> ProviderIds { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("limit")]
|
|
public int? Limit { get; init; }
|
|
|
|
[JsonPropertyName("cursor")]
|
|
public string? Cursor { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Response from VEX observation query.
|
|
/// </summary>
|
|
internal sealed class VexObservationResponse
|
|
{
|
|
[JsonPropertyName("observations")]
|
|
public IReadOnlyList<VexObservation> Observations { get; init; } = Array.Empty<VexObservation>();
|
|
|
|
[JsonPropertyName("aggregate")]
|
|
public VexObservationAggregate? Aggregate { get; init; }
|
|
|
|
[JsonPropertyName("nextCursor")]
|
|
public string? NextCursor { get; init; }
|
|
|
|
[JsonPropertyName("hasMore")]
|
|
public bool HasMore { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// VEX observation document.
|
|
/// </summary>
|
|
internal sealed class VexObservation
|
|
{
|
|
[JsonPropertyName("observationId")]
|
|
public string ObservationId { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("tenant")]
|
|
public string Tenant { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("vulnerabilityId")]
|
|
public string VulnerabilityId { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("providerId")]
|
|
public string ProviderId { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("product")]
|
|
public VexObservationProduct? Product { get; init; }
|
|
|
|
[JsonPropertyName("status")]
|
|
public string Status { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("justification")]
|
|
public string? Justification { get; init; }
|
|
|
|
[JsonPropertyName("detail")]
|
|
public string? Detail { get; init; }
|
|
|
|
[JsonPropertyName("document")]
|
|
public VexObservationDocument? Document { get; init; }
|
|
|
|
[JsonPropertyName("firstSeen")]
|
|
public DateTimeOffset FirstSeen { get; init; }
|
|
|
|
[JsonPropertyName("lastSeen")]
|
|
public DateTimeOffset LastSeen { get; init; }
|
|
|
|
[JsonPropertyName("confidence")]
|
|
public VexObservationConfidence? Confidence { get; init; }
|
|
|
|
[JsonPropertyName("createdAt")]
|
|
public DateTimeOffset CreatedAt { get; init; }
|
|
|
|
[JsonPropertyName("updatedAt")]
|
|
public DateTimeOffset? UpdatedAt { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Product information in VEX observation.
|
|
/// </summary>
|
|
internal sealed class VexObservationProduct
|
|
{
|
|
[JsonPropertyName("key")]
|
|
public string Key { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("name")]
|
|
public string? Name { get; init; }
|
|
|
|
[JsonPropertyName("version")]
|
|
public string? Version { get; init; }
|
|
|
|
[JsonPropertyName("purl")]
|
|
public string? Purl { get; init; }
|
|
|
|
[JsonPropertyName("cpe")]
|
|
public string? Cpe { get; init; }
|
|
|
|
[JsonPropertyName("componentIdentifiers")]
|
|
public IReadOnlyList<string> ComponentIdentifiers { get; init; } = Array.Empty<string>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Document reference in VEX observation.
|
|
/// </summary>
|
|
internal sealed class VexObservationDocument
|
|
{
|
|
[JsonPropertyName("format")]
|
|
public string Format { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("digest")]
|
|
public string Digest { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("sourceUri")]
|
|
public string SourceUri { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("revision")]
|
|
public string? Revision { get; init; }
|
|
|
|
[JsonPropertyName("signature")]
|
|
public VexObservationSignature? Signature { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Signature metadata for VEX document.
|
|
/// </summary>
|
|
internal sealed class VexObservationSignature
|
|
{
|
|
[JsonPropertyName("type")]
|
|
public string Type { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("subject")]
|
|
public string? Subject { get; init; }
|
|
|
|
[JsonPropertyName("issuer")]
|
|
public string? Issuer { get; init; }
|
|
|
|
[JsonPropertyName("keyId")]
|
|
public string? KeyId { get; init; }
|
|
|
|
[JsonPropertyName("verifiedAt")]
|
|
public DateTimeOffset? VerifiedAt { get; init; }
|
|
|
|
[JsonPropertyName("transparencyLogReference")]
|
|
public string? TransparencyLogReference { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Confidence level in VEX observation.
|
|
/// </summary>
|
|
internal sealed class VexObservationConfidence
|
|
{
|
|
[JsonPropertyName("level")]
|
|
public string Level { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("score")]
|
|
public double? Score { get; init; }
|
|
|
|
[JsonPropertyName("method")]
|
|
public string? Method { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggregate data from VEX observation query.
|
|
/// </summary>
|
|
internal sealed class VexObservationAggregate
|
|
{
|
|
[JsonPropertyName("vulnerabilityIds")]
|
|
public IReadOnlyList<string> VulnerabilityIds { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("productKeys")]
|
|
public IReadOnlyList<string> ProductKeys { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("purls")]
|
|
public IReadOnlyList<string> Purls { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("cpes")]
|
|
public IReadOnlyList<string> Cpes { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("providerIds")]
|
|
public IReadOnlyList<string> ProviderIds { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("statusCounts")]
|
|
public IReadOnlyDictionary<string, int> StatusCounts { get; init; } = new Dictionary<string, int>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// VEX linkset query options.
|
|
/// </summary>
|
|
internal sealed class VexLinksetQuery
|
|
{
|
|
[JsonPropertyName("tenant")]
|
|
public string Tenant { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("vulnerabilityId")]
|
|
public string VulnerabilityId { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("productKeys")]
|
|
public IReadOnlyList<string> ProductKeys { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("purls")]
|
|
public IReadOnlyList<string> Purls { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("statuses")]
|
|
public IReadOnlyList<string> Statuses { get; init; } = Array.Empty<string>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// VEX linkset response showing linked observations.
|
|
/// </summary>
|
|
internal sealed class VexLinksetResponse
|
|
{
|
|
[JsonPropertyName("vulnerabilityId")]
|
|
public string VulnerabilityId { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("observations")]
|
|
public IReadOnlyList<VexObservation> Observations { get; init; } = Array.Empty<VexObservation>();
|
|
|
|
[JsonPropertyName("summary")]
|
|
public VexLinksetSummary? Summary { get; init; }
|
|
|
|
[JsonPropertyName("conflicts")]
|
|
public IReadOnlyList<VexLinksetConflict> Conflicts { get; init; } = Array.Empty<VexLinksetConflict>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Summary of VEX linkset.
|
|
/// </summary>
|
|
internal sealed class VexLinksetSummary
|
|
{
|
|
[JsonPropertyName("totalObservations")]
|
|
public int TotalObservations { get; init; }
|
|
|
|
[JsonPropertyName("providers")]
|
|
public IReadOnlyList<string> Providers { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("products")]
|
|
public IReadOnlyList<string> Products { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("statusCounts")]
|
|
public IReadOnlyDictionary<string, int> StatusCounts { get; init; } = new Dictionary<string, int>();
|
|
|
|
[JsonPropertyName("hasConflicts")]
|
|
public bool HasConflicts { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Conflict between VEX observations.
|
|
/// </summary>
|
|
internal sealed class VexLinksetConflict
|
|
{
|
|
[JsonPropertyName("productKey")]
|
|
public string ProductKey { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("conflictingStatuses")]
|
|
public IReadOnlyList<string> ConflictingStatuses { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("observations")]
|
|
public IReadOnlyList<string> ObservationIds { get; init; } = Array.Empty<string>();
|
|
|
|
[JsonPropertyName("description")]
|
|
public string Description { get; init; } = string.Empty;
|
|
}
|