295 lines
7.9 KiB
C#
295 lines
7.9 KiB
C#
|
|
using StellaOps.Scanner.Contracts;
|
|
using System.Collections.Immutable;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace StellaOps.Scanner.ReachabilityDrift;
|
|
|
|
public sealed record CodeChangeFact
|
|
{
|
|
[JsonPropertyName("id")]
|
|
public required Guid Id { get; init; }
|
|
|
|
[JsonPropertyName("scanId")]
|
|
public required string ScanId { get; init; }
|
|
|
|
[JsonPropertyName("baseScanId")]
|
|
public required string BaseScanId { get; init; }
|
|
|
|
[JsonPropertyName("language")]
|
|
public required string Language { get; init; }
|
|
|
|
[JsonPropertyName("nodeId")]
|
|
public string? NodeId { get; init; }
|
|
|
|
[JsonPropertyName("file")]
|
|
public required string File { get; init; }
|
|
|
|
[JsonPropertyName("symbol")]
|
|
public required string Symbol { get; init; }
|
|
|
|
[JsonPropertyName("kind")]
|
|
public required CodeChangeKind Kind { get; init; }
|
|
|
|
[JsonPropertyName("details")]
|
|
public JsonElement? Details { get; init; }
|
|
|
|
[JsonPropertyName("detectedAt")]
|
|
public required DateTimeOffset DetectedAt { get; init; }
|
|
}
|
|
|
|
[JsonConverter(typeof(JsonStringEnumConverter<CodeChangeKind>))]
|
|
public enum CodeChangeKind
|
|
{
|
|
[JsonStringEnumMemberName("added")]
|
|
Added,
|
|
|
|
[JsonStringEnumMemberName("removed")]
|
|
Removed,
|
|
|
|
[JsonStringEnumMemberName("signature_changed")]
|
|
SignatureChanged,
|
|
|
|
[JsonStringEnumMemberName("guard_changed")]
|
|
GuardChanged,
|
|
|
|
[JsonStringEnumMemberName("dependency_changed")]
|
|
DependencyChanged,
|
|
|
|
[JsonStringEnumMemberName("visibility_changed")]
|
|
VisibilityChanged
|
|
}
|
|
|
|
public sealed record ReachabilityDriftResult
|
|
{
|
|
[JsonPropertyName("id")]
|
|
public required Guid Id { get; init; }
|
|
|
|
[JsonPropertyName("baseScanId")]
|
|
public required string BaseScanId { get; init; }
|
|
|
|
[JsonPropertyName("headScanId")]
|
|
public required string HeadScanId { get; init; }
|
|
|
|
[JsonPropertyName("language")]
|
|
public required string Language { get; init; }
|
|
|
|
[JsonPropertyName("detectedAt")]
|
|
public required DateTimeOffset DetectedAt { get; init; }
|
|
|
|
[JsonPropertyName("newlyReachable")]
|
|
public required ImmutableArray<DriftedSink> NewlyReachable { get; init; }
|
|
|
|
[JsonPropertyName("newlyUnreachable")]
|
|
public required ImmutableArray<DriftedSink> NewlyUnreachable { get; init; }
|
|
|
|
[JsonPropertyName("resultDigest")]
|
|
public required string ResultDigest { get; init; }
|
|
|
|
[JsonPropertyName("totalDriftCount")]
|
|
public int TotalDriftCount => NewlyReachable.Length + NewlyUnreachable.Length;
|
|
|
|
[JsonPropertyName("hasMaterialDrift")]
|
|
public bool HasMaterialDrift => NewlyReachable.Length > 0;
|
|
}
|
|
|
|
public sealed record DriftedSink
|
|
{
|
|
[JsonPropertyName("id")]
|
|
public required Guid Id { get; init; }
|
|
|
|
[JsonPropertyName("sinkNodeId")]
|
|
public required string SinkNodeId { get; init; }
|
|
|
|
[JsonPropertyName("symbol")]
|
|
public required string Symbol { get; init; }
|
|
|
|
[JsonPropertyName("sinkCategory")]
|
|
public required SinkCategory SinkCategory { get; init; }
|
|
|
|
[JsonPropertyName("direction")]
|
|
public required DriftDirection Direction { get; init; }
|
|
|
|
[JsonPropertyName("cause")]
|
|
public required DriftCause Cause { get; init; }
|
|
|
|
[JsonPropertyName("path")]
|
|
public required CompressedPath Path { get; init; }
|
|
|
|
[JsonPropertyName("associatedVulns")]
|
|
public ImmutableArray<AssociatedVuln> AssociatedVulns { get; init; } = ImmutableArray<AssociatedVuln>.Empty;
|
|
}
|
|
|
|
[JsonConverter(typeof(JsonStringEnumConverter<DriftDirection>))]
|
|
public enum DriftDirection
|
|
{
|
|
[JsonStringEnumMemberName("became_reachable")]
|
|
BecameReachable,
|
|
|
|
[JsonStringEnumMemberName("became_unreachable")]
|
|
BecameUnreachable
|
|
}
|
|
|
|
public sealed record DriftCause
|
|
{
|
|
[JsonPropertyName("kind")]
|
|
public required DriftCauseKind Kind { get; init; }
|
|
|
|
[JsonPropertyName("description")]
|
|
public required string Description { get; init; }
|
|
|
|
[JsonPropertyName("changedSymbol")]
|
|
public string? ChangedSymbol { get; init; }
|
|
|
|
[JsonPropertyName("changedFile")]
|
|
public string? ChangedFile { get; init; }
|
|
|
|
[JsonPropertyName("changedLine")]
|
|
public int? ChangedLine { get; init; }
|
|
|
|
[JsonPropertyName("codeChangeId")]
|
|
public Guid? CodeChangeId { get; init; }
|
|
|
|
public static DriftCause GuardRemoved(string symbol) =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.GuardRemoved,
|
|
Description = $"Guard condition removed in {symbol}",
|
|
ChangedSymbol = symbol
|
|
};
|
|
|
|
public static DriftCause NewPublicRoute(string symbol) =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.NewPublicRoute,
|
|
Description = $"New public entrypoint: {symbol}",
|
|
ChangedSymbol = symbol
|
|
};
|
|
|
|
public static DriftCause VisibilityEscalated(string symbol) =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.VisibilityEscalated,
|
|
Description = $"Visibility escalated to public: {symbol}",
|
|
ChangedSymbol = symbol
|
|
};
|
|
|
|
public static DriftCause DependencyUpgraded(string package, string? fromVersion, string? toVersion) =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.DependencyUpgraded,
|
|
Description = $"Dependency changed: {package} {fromVersion ?? "?"} -> {toVersion ?? "?"}",
|
|
ChangedSymbol = package
|
|
};
|
|
|
|
public static DriftCause GuardAdded(string symbol) =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.GuardAdded,
|
|
Description = $"Guard condition added in {symbol}",
|
|
ChangedSymbol = symbol
|
|
};
|
|
|
|
public static DriftCause SymbolRemoved(string symbol) =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.SymbolRemoved,
|
|
Description = $"Symbol removed: {symbol}",
|
|
ChangedSymbol = symbol
|
|
};
|
|
|
|
public static DriftCause Unknown() =>
|
|
new()
|
|
{
|
|
Kind = DriftCauseKind.Unknown,
|
|
Description = "Cause could not be determined"
|
|
};
|
|
}
|
|
|
|
[JsonConverter(typeof(JsonStringEnumConverter<DriftCauseKind>))]
|
|
public enum DriftCauseKind
|
|
{
|
|
[JsonStringEnumMemberName("guard_removed")]
|
|
GuardRemoved,
|
|
|
|
[JsonStringEnumMemberName("guard_added")]
|
|
GuardAdded,
|
|
|
|
[JsonStringEnumMemberName("new_public_route")]
|
|
NewPublicRoute,
|
|
|
|
[JsonStringEnumMemberName("visibility_escalated")]
|
|
VisibilityEscalated,
|
|
|
|
[JsonStringEnumMemberName("dependency_upgraded")]
|
|
DependencyUpgraded,
|
|
|
|
[JsonStringEnumMemberName("symbol_removed")]
|
|
SymbolRemoved,
|
|
|
|
[JsonStringEnumMemberName("unknown")]
|
|
Unknown
|
|
}
|
|
|
|
public sealed record CompressedPath
|
|
{
|
|
[JsonPropertyName("entrypoint")]
|
|
public required PathNode Entrypoint { get; init; }
|
|
|
|
[JsonPropertyName("sink")]
|
|
public required PathNode Sink { get; init; }
|
|
|
|
[JsonPropertyName("intermediateCount")]
|
|
public required int IntermediateCount { get; init; }
|
|
|
|
[JsonPropertyName("keyNodes")]
|
|
public required ImmutableArray<PathNode> KeyNodes { get; init; }
|
|
|
|
[JsonPropertyName("fullPath")]
|
|
public ImmutableArray<string>? FullPath { get; init; }
|
|
}
|
|
|
|
public sealed record PathNode
|
|
{
|
|
[JsonPropertyName("nodeId")]
|
|
public required string NodeId { get; init; }
|
|
|
|
[JsonPropertyName("symbol")]
|
|
public required string Symbol { get; init; }
|
|
|
|
[JsonPropertyName("file")]
|
|
public string? File { get; init; }
|
|
|
|
[JsonPropertyName("line")]
|
|
public int? Line { get; init; }
|
|
|
|
[JsonPropertyName("package")]
|
|
public string? Package { get; init; }
|
|
|
|
[JsonPropertyName("isChanged")]
|
|
public bool IsChanged { get; init; }
|
|
|
|
[JsonPropertyName("changeKind")]
|
|
public CodeChangeKind? ChangeKind { get; init; }
|
|
}
|
|
|
|
public sealed record AssociatedVuln
|
|
{
|
|
[JsonPropertyName("cveId")]
|
|
public required string CveId { get; init; }
|
|
|
|
[JsonPropertyName("epss")]
|
|
public double? Epss { get; init; }
|
|
|
|
[JsonPropertyName("cvss")]
|
|
public double? Cvss { get; init; }
|
|
|
|
[JsonPropertyName("vexStatus")]
|
|
public string? VexStatus { get; init; }
|
|
|
|
[JsonPropertyName("packagePurl")]
|
|
public string? PackagePurl { get; init; }
|
|
}
|
|
|