559e02f5c8
Owner decisions on #110: one signing key per environment; TrustedKeys stay hand-edited; Signing:ProductionBoundary (new, default off) logs a startup warning and reports a Degraded bundle-signing-policy /health/ready entry while RequireSignedBundles is off; the private key is read via ${secret:} (proved end to end, never logged); cluster pull decided not to be built; differential deletions stay deferred. Adds docs/operations/bundle-signing-runbook.md. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
44 lines
1.8 KiB
C#
44 lines
1.8 KiB
C#
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Microsoft.Extensions.Options;
|
|
using ZB.MOM.WW.ScadaBridge.Transport;
|
|
using ZB.MOM.WW.ScadaBridge.Transport.Signing;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.Host.Health;
|
|
|
|
/// <summary>
|
|
/// /health/ready entry (ScadaBridge#110): Degraded while a cluster marked
|
|
/// <c>Transport:Signing:ProductionBoundary</c> still accepts unsigned bundles. Degraded maps
|
|
/// to HTTP 200 in the shared health tier, so it is visible on the Overview dashboard without
|
|
/// taking the node out of rotation. Exposes only booleans — never key material.
|
|
/// </summary>
|
|
public sealed class BundleSigningPolicyHealthCheck : IHealthCheck
|
|
{
|
|
private readonly IOptionsMonitor<TransportOptions> _options;
|
|
|
|
/// <summary>Initializes the check.</summary>
|
|
/// <param name="options">Transport options.</param>
|
|
public BundleSigningPolicyHealthCheck(IOptionsMonitor<TransportOptions> options)
|
|
{
|
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task<HealthCheckResult> CheckHealthAsync(
|
|
HealthCheckContext context, CancellationToken cancellationToken = default)
|
|
{
|
|
var signing = _options.CurrentValue.Signing;
|
|
var data = new Dictionary<string, object>(StringComparer.Ordinal)
|
|
{
|
|
["productionBoundary"] = signing.ProductionBoundary,
|
|
["requireSignedBundles"] = signing.RequireSignedBundles,
|
|
["signingEnabled"] = signing.Enabled,
|
|
["trustedKeys"] = signing.TrustedKeys.Count,
|
|
};
|
|
|
|
var advisory = BundleSigningPolicyAdvisory.Evaluate(signing);
|
|
return Task.FromResult(advisory is null
|
|
? HealthCheckResult.Healthy("Bundle signing policy OK.", data)
|
|
: HealthCheckResult.Degraded(advisory, data: data));
|
|
}
|
|
}
|