new two advisories and sprints work on them
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
using StellaOps.Doctor.Models;
|
||||
using StellaOps.Doctor.Plugins;
|
||||
using StellaOps.Doctor.Plugins.Builders;
|
||||
using StellaOps.Doctor.Plugins.Verification.Configuration;
|
||||
|
||||
namespace StellaOps.Doctor.Plugins.Verification.Checks;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for verification checks providing common functionality.
|
||||
/// </summary>
|
||||
public abstract class VerificationCheckBase : IDoctorCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Plugin identifier for verification checks.
|
||||
/// </summary>
|
||||
protected const string PluginId = "stellaops.doctor.verification";
|
||||
|
||||
/// <summary>
|
||||
/// Category name for verification checks.
|
||||
/// </summary>
|
||||
protected const string CategoryName = "Security";
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string CheckId { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string Description { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DoctorSeverity DefaultSeverity => DoctorSeverity.Fail;
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract IReadOnlyList<string> Tags { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual TimeSpan EstimatedDuration => TimeSpan.FromSeconds(10);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool CanRun(DoctorPluginContext context)
|
||||
{
|
||||
var options = VerificationPlugin.GetOptions(context);
|
||||
return options.Enabled;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DoctorCheckResult> RunAsync(DoctorPluginContext context, CancellationToken ct)
|
||||
{
|
||||
var result = context.CreateResult(CheckId, PluginId, CategoryName);
|
||||
var options = VerificationPlugin.GetOptions(context);
|
||||
|
||||
if (!options.Enabled)
|
||||
{
|
||||
return result
|
||||
.Skip("Verification plugin is disabled")
|
||||
.WithEvidence("Configuration", e => e
|
||||
.Add("Enabled", "false"))
|
||||
.Build();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return await ExecuteCheckAsync(context, options, result, ct);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
return result
|
||||
.Fail($"Network error: {ex.Message}")
|
||||
.WithEvidence("Error details", e => e
|
||||
.Add("ExceptionType", ex.GetType().Name)
|
||||
.Add("Message", ex.Message)
|
||||
.Add("StatusCode", ex.StatusCode?.ToString() ?? "(none)"))
|
||||
.WithCauses(
|
||||
"Network connectivity issue",
|
||||
"Registry or endpoint unreachable",
|
||||
"Authentication failure")
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Check network connectivity", "Verify the endpoint is reachable")
|
||||
.AddManualStep(2, "Check credentials", "Verify authentication is configured correctly"))
|
||||
.WithVerification($"stella doctor --check {CheckId}")
|
||||
.Build();
|
||||
}
|
||||
catch (TaskCanceledException ex) when (ex.CancellationToken != ct)
|
||||
{
|
||||
return result
|
||||
.Fail("Request timed out")
|
||||
.WithEvidence("Error details", e => e
|
||||
.Add("ExceptionType", "TimeoutException")
|
||||
.Add("Message", "The request timed out before completing"))
|
||||
.WithCauses(
|
||||
"Endpoint is slow to respond",
|
||||
"Network latency is high",
|
||||
"Large artifact size")
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Increase timeout", "Set Doctor:Plugins:Verification:HttpTimeoutSeconds to a higher value"))
|
||||
.WithVerification($"stella doctor --check {CheckId}")
|
||||
.Build();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return result
|
||||
.Fail($"Unexpected error: {ex.Message}")
|
||||
.WithEvidence("Error details", e => e
|
||||
.Add("ExceptionType", ex.GetType().Name)
|
||||
.Add("Message", ex.Message))
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specific check logic.
|
||||
/// </summary>
|
||||
protected abstract Task<DoctorCheckResult> ExecuteCheckAsync(
|
||||
DoctorPluginContext context,
|
||||
VerificationPluginOptions options,
|
||||
CheckResultBuilder result,
|
||||
CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an HttpClient with configured timeout.
|
||||
/// </summary>
|
||||
protected static HttpClient CreateHttpClient(VerificationPluginOptions options)
|
||||
{
|
||||
return new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(options.HttpTimeoutSeconds)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a test artifact is configured.
|
||||
/// </summary>
|
||||
protected static bool HasTestArtifactConfigured(VerificationPluginOptions options)
|
||||
{
|
||||
return !string.IsNullOrEmpty(options.TestArtifact.Reference)
|
||||
|| !string.IsNullOrEmpty(options.TestArtifact.OfflineBundlePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a skip result for when test artifact is not configured.
|
||||
/// </summary>
|
||||
protected static DoctorCheckResult GetNoTestArtifactConfiguredResult(CheckResultBuilder result, string checkId)
|
||||
{
|
||||
return result
|
||||
.Skip("Test artifact not configured")
|
||||
.WithEvidence("Configuration", e => e
|
||||
.Add("TestArtifactReference", "(not set)")
|
||||
.Add("OfflineBundlePath", "(not set)")
|
||||
.Add("Note", "Configure a test artifact to enable verification pipeline checks"))
|
||||
.WithRemediation(r => r
|
||||
.AddManualStep(1, "Configure test artifact", "Set Doctor:Plugins:Verification:TestArtifact:Reference to an OCI reference")
|
||||
.AddManualStep(2, "Or use offline bundle", "Set Doctor:Plugins:Verification:TestArtifact:OfflineBundlePath for air-gap environments"))
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user