Files
git.stella-ops.org/src/Concelier/StellaOps.Excititor.WebService/Services/AirgapSignerTrustService.cs

84 lines
2.8 KiB
C#

using Microsoft.Extensions.Logging;
using StellaOps.Excititor.Connectors.Abstractions.Trust;
using StellaOps.Excititor.WebService.Contracts;
using System;
using System.IO;
using System.Linq;
namespace StellaOps.Excititor.WebService.Services;
internal sealed class AirgapSignerTrustService
{
private readonly ILogger<AirgapSignerTrustService> _logger;
private readonly string? _metadataPath;
private ConnectorSignerMetadataSet? _metadata;
public AirgapSignerTrustService(ILogger<AirgapSignerTrustService> logger)
{
_logger = logger;
_metadataPath = Environment.GetEnvironmentVariable("STELLAOPS_CONNECTOR_SIGNER_METADATA_PATH");
}
public bool Validate(AirgapImportRequest request, out string? errorCode, out string? message)
{
errorCode = null;
message = null;
if (string.IsNullOrWhiteSpace(_metadataPath) || !File.Exists(_metadataPath))
{
_logger.LogDebug("Airgap signer metadata not configured; skipping trust enforcement.");
return true;
}
_metadata ??= ConnectorSignerMetadataLoader.TryLoad(_metadataPath);
if (_metadata is null)
{
_logger.LogWarning("Failed to load airgap signer metadata from {Path}; allowing import.", _metadataPath);
return true;
}
if (string.IsNullOrWhiteSpace(request.Publisher))
{
errorCode = "AIRGAP_SOURCE_UNTRUSTED";
message = "publisher is required for trust enforcement.";
return false;
}
if (!_metadata.TryGet(request.Publisher, out var connector))
{
errorCode = "AIRGAP_SOURCE_UNTRUSTED";
message = $"Publisher '{request.Publisher}' is not present in trusted signer metadata.";
return false;
}
if (connector.Revoked)
{
errorCode = "AIRGAP_SOURCE_UNTRUSTED";
message = $"Publisher '{request.Publisher}' is revoked.";
return false;
}
if (connector.Bundle?.Digest is { } digest && !string.IsNullOrWhiteSpace(digest))
{
if (!string.Equals(digest.Trim(), request.PayloadHash?.Trim(), StringComparison.OrdinalIgnoreCase))
{
errorCode = "AIRGAP_PAYLOAD_MISMATCH";
message = "Payload hash does not match trusted bundle digest.";
return false;
}
}
// Basic sanity: ensure at least one signer entry exists.
if (connector.Signers.IsDefaultOrEmpty || connector.Signers.Sum(s => s.Fingerprints.Length) == 0)
{
errorCode = "AIRGAP_SOURCE_UNTRUSTED";
message = $"Publisher '{request.Publisher}' has no trusted signers configured.";
return false;
}
return true;
}
}