Implement VEX document verification system with issuer management and signature verification
- Added IIssuerDirectory interface for managing VEX document issuers, including methods for registration, revocation, and trust validation. - Created InMemoryIssuerDirectory class as an in-memory implementation of IIssuerDirectory for testing and single-instance deployments. - Introduced ISignatureVerifier interface for verifying signatures on VEX documents, with support for multiple signature formats. - Developed SignatureVerifier class as the default implementation of ISignatureVerifier, allowing extensibility for different signature formats. - Implemented handlers for DSSE and JWS signature formats, including methods for verification and signature extraction. - Defined various records and enums for issuer and signature metadata, enhancing the structure and clarity of the verification process.
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Policy.RiskProfile.Scope;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Audit log interface for effective:write operations per CONTRACT-AUTHORITY-EFFECTIVE-WRITE-008.
|
||||
/// </summary>
|
||||
internal interface IEffectivePolicyAuditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Records an effective policy creation event.
|
||||
/// </summary>
|
||||
void RecordCreated(EffectivePolicy policy, string? actorId);
|
||||
|
||||
/// <summary>
|
||||
/// Records an effective policy update event.
|
||||
/// </summary>
|
||||
void RecordUpdated(EffectivePolicy policy, string? actorId, object? changes);
|
||||
|
||||
/// <summary>
|
||||
/// Records an effective policy deletion event.
|
||||
/// </summary>
|
||||
void RecordDeleted(string effectivePolicyId, string? actorId);
|
||||
|
||||
/// <summary>
|
||||
/// Records a scope attachment event.
|
||||
/// </summary>
|
||||
void RecordScopeAttached(AuthorityScopeAttachment attachment, string? actorId);
|
||||
|
||||
/// <summary>
|
||||
/// Records a scope detachment event.
|
||||
/// </summary>
|
||||
void RecordScopeDetached(string attachmentId, string? actorId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default implementation of effective policy auditor.
|
||||
/// Emits structured logs for all effective:write operations per CONTRACT-AUTHORITY-EFFECTIVE-WRITE-008.
|
||||
/// </summary>
|
||||
internal sealed class EffectivePolicyAuditor : IEffectivePolicyAuditor
|
||||
{
|
||||
private readonly ILogger<EffectivePolicyAuditor> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public EffectivePolicyAuditor(
|
||||
ILogger<EffectivePolicyAuditor> logger,
|
||||
TimeProvider timeProvider)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
|
||||
}
|
||||
|
||||
public void RecordCreated(EffectivePolicy policy, string? actorId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(policy);
|
||||
|
||||
var scope = CreateBaseScope("effective_policy.created", actorId);
|
||||
scope["effective_policy_id"] = policy.EffectivePolicyId;
|
||||
scope["tenant_id"] = policy.TenantId;
|
||||
scope["policy_id"] = policy.PolicyId;
|
||||
scope["subject_pattern"] = policy.SubjectPattern;
|
||||
scope["priority"] = policy.Priority;
|
||||
|
||||
if (policy.Scopes is { Count: > 0 })
|
||||
{
|
||||
scope["scopes"] = policy.Scopes;
|
||||
}
|
||||
|
||||
using (_logger.BeginScope(scope))
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Effective policy created: {EffectivePolicyId} for pattern {SubjectPattern}",
|
||||
policy.EffectivePolicyId,
|
||||
policy.SubjectPattern);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecordUpdated(EffectivePolicy policy, string? actorId, object? changes)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(policy);
|
||||
|
||||
var scope = CreateBaseScope("effective_policy.updated", actorId);
|
||||
scope["effective_policy_id"] = policy.EffectivePolicyId;
|
||||
scope["tenant_id"] = policy.TenantId;
|
||||
|
||||
if (changes is not null)
|
||||
{
|
||||
scope["changes"] = changes;
|
||||
}
|
||||
|
||||
using (_logger.BeginScope(scope))
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Effective policy updated: {EffectivePolicyId}",
|
||||
policy.EffectivePolicyId);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecordDeleted(string effectivePolicyId, string? actorId)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(effectivePolicyId);
|
||||
|
||||
var scope = CreateBaseScope("effective_policy.deleted", actorId);
|
||||
scope["effective_policy_id"] = effectivePolicyId;
|
||||
|
||||
using (_logger.BeginScope(scope))
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Effective policy deleted: {EffectivePolicyId}",
|
||||
effectivePolicyId);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecordScopeAttached(AuthorityScopeAttachment attachment, string? actorId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(attachment);
|
||||
|
||||
var scope = CreateBaseScope("scope_attachment.created", actorId);
|
||||
scope["attachment_id"] = attachment.AttachmentId;
|
||||
scope["effective_policy_id"] = attachment.EffectivePolicyId;
|
||||
scope["scope"] = attachment.Scope;
|
||||
|
||||
if (attachment.Conditions is { Count: > 0 })
|
||||
{
|
||||
scope["conditions"] = attachment.Conditions;
|
||||
}
|
||||
|
||||
using (_logger.BeginScope(scope))
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Scope attached: {Scope} to policy {EffectivePolicyId}",
|
||||
attachment.Scope,
|
||||
attachment.EffectivePolicyId);
|
||||
}
|
||||
}
|
||||
|
||||
public void RecordScopeDetached(string attachmentId, string? actorId)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(attachmentId);
|
||||
|
||||
var scope = CreateBaseScope("scope_attachment.deleted", actorId);
|
||||
scope["attachment_id"] = attachmentId;
|
||||
|
||||
using (_logger.BeginScope(scope))
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Scope detached: {AttachmentId}",
|
||||
attachmentId);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, object?> CreateBaseScope(string eventType, string? actorId)
|
||||
{
|
||||
var scope = new Dictionary<string, object?>
|
||||
{
|
||||
["event"] = eventType,
|
||||
["timestamp"] = _timeProvider.GetUtcNow().ToString("O")
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(actorId))
|
||||
{
|
||||
scope["actor"] = actorId;
|
||||
}
|
||||
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user