up
Some checks failed
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
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
Some checks failed
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
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
This commit is contained in:
@@ -55,6 +55,10 @@ internal sealed record RuntimePolicyImageResult
|
||||
[JsonPropertyName("rekor")]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public RuntimePolicyRekorResult? Rekor { get; init; }
|
||||
|
||||
[JsonPropertyName("manifestDigest")]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? ManifestDigest { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record RuntimePolicyRekorResult
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Metrics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -10,13 +11,20 @@ using StellaOps.Zastava.Core.Contracts;
|
||||
using StellaOps.Zastava.Observer.Backend;
|
||||
using StellaOps.Zastava.Observer.Configuration;
|
||||
using StellaOps.Zastava.Observer.ContainerRuntime.Cri;
|
||||
using StellaOps.Zastava.Observer.Surface;
|
||||
|
||||
namespace StellaOps.Zastava.Observer.Posture;
|
||||
|
||||
internal sealed class RuntimePostureEvaluator : IRuntimePostureEvaluator
|
||||
{
|
||||
private static readonly Meter Meter = new("StellaOps.Zastava.Observer", "1.0.0");
|
||||
private static readonly Counter<long> ManifestFailuresCounter = Meter.CreateCounter<long>(
|
||||
"zastava_surface_manifest_failures_total",
|
||||
description: "Count of Surface manifest fetch failures");
|
||||
|
||||
private readonly IRuntimePolicyClient policyClient;
|
||||
private readonly IRuntimePostureCache cache;
|
||||
private readonly IRuntimeSurfaceFsClient surfaceFsClient;
|
||||
private readonly IOptionsMonitor<ZastavaObserverOptions> optionsMonitor;
|
||||
private readonly TimeProvider timeProvider;
|
||||
private readonly ILogger<RuntimePostureEvaluator> logger;
|
||||
@@ -24,12 +32,14 @@ internal sealed class RuntimePostureEvaluator : IRuntimePostureEvaluator
|
||||
public RuntimePostureEvaluator(
|
||||
IRuntimePolicyClient policyClient,
|
||||
IRuntimePostureCache cache,
|
||||
IRuntimeSurfaceFsClient surfaceFsClient,
|
||||
IOptionsMonitor<ZastavaObserverOptions> optionsMonitor,
|
||||
TimeProvider timeProvider,
|
||||
ILogger<RuntimePostureEvaluator> logger)
|
||||
{
|
||||
this.policyClient = policyClient ?? throw new ArgumentNullException(nameof(policyClient));
|
||||
this.cache = cache ?? throw new ArgumentNullException(nameof(cache));
|
||||
this.surfaceFsClient = surfaceFsClient ?? throw new ArgumentNullException(nameof(surfaceFsClient));
|
||||
this.optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor));
|
||||
this.timeProvider = timeProvider ?? TimeProvider.System;
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
@@ -100,6 +110,8 @@ internal sealed class RuntimePostureEvaluator : IRuntimePostureEvaluator
|
||||
Value = expiresAt.ToString("O", CultureInfo.InvariantCulture)
|
||||
});
|
||||
|
||||
await EnrichWithManifestAsync(imageResult.ManifestDigest, evidence, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new RuntimePostureEvaluationResult(posture, evidence);
|
||||
}
|
||||
catch (Exception ex) when (!cancellationToken.IsCancellationRequested)
|
||||
@@ -185,4 +197,86 @@ internal sealed class RuntimePostureEvaluator : IRuntimePostureEvaluator
|
||||
|
||||
return posture;
|
||||
}
|
||||
|
||||
private async Task EnrichWithManifestAsync(string? manifestDigest, List<RuntimeEvidence> evidence, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(manifestDigest))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var manifest = await surfaceFsClient.TryGetManifestAsync(manifestDigest, cancellationToken).ConfigureAwait(false);
|
||||
if (manifest is null)
|
||||
{
|
||||
ManifestFailuresCounter.Add(1, new KeyValuePair<string, object?>("reason", "not_found"));
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = "runtime.surface.manifest",
|
||||
Value = "not_found"
|
||||
});
|
||||
logger.LogDebug("Surface manifest {ManifestDigest} not found in local cache.", manifestDigest);
|
||||
return;
|
||||
}
|
||||
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = "runtime.surface.manifest",
|
||||
Value = "resolved"
|
||||
});
|
||||
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = "runtime.surface.manifestDigest",
|
||||
Value = manifestDigest
|
||||
});
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(manifest.ImageDigest))
|
||||
{
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = "runtime.surface.imageDigest",
|
||||
Value = manifest.ImageDigest
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var artifact in manifest.Artifacts)
|
||||
{
|
||||
var artifactKind = artifact.Kind;
|
||||
if (string.IsNullOrWhiteSpace(artifactKind))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = $"runtime.surface.artifact.{artifactKind}",
|
||||
Value = artifact.Digest
|
||||
});
|
||||
|
||||
if (artifact.Metadata is not null && artifact.Metadata.Count > 0)
|
||||
{
|
||||
foreach (var kvp in artifact.Metadata.Take(5))
|
||||
{
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = $"runtime.surface.artifact.{artifactKind}.{kvp.Key}",
|
||||
Value = kvp.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
ManifestFailuresCounter.Add(1, new KeyValuePair<string, object?>("reason", "fetch_error"));
|
||||
evidence.Add(new RuntimeEvidence
|
||||
{
|
||||
Signal = "runtime.surface.manifest",
|
||||
Value = "fetch_error"
|
||||
});
|
||||
logger.LogWarning(ex, "Failed to fetch Surface manifest {ManifestDigest}.", manifestDigest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user