save audit remarks applications progress
This commit is contained in:
@@ -67,6 +67,7 @@ public static class VerdictEndpoints
|
||||
private static async Task<IResult> StoreVerdictAsync(
|
||||
[FromBody] StoreVerdictRequest request,
|
||||
[FromServices] IVerdictRepository repository,
|
||||
[FromServices] TimeProvider timeProvider,
|
||||
[FromServices] ILogger<VerdictEndpointsLogger> logger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -105,7 +106,7 @@ public static class VerdictEndpoints
|
||||
PredicateDigest = request.PredicateDigest,
|
||||
DeterminismHash = request.DeterminismHash,
|
||||
RekorLogIndex = request.RekorLogIndex,
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
CreatedAt = timeProvider.GetUtcNow()
|
||||
};
|
||||
|
||||
// Store in repository
|
||||
@@ -253,6 +254,7 @@ public static class VerdictEndpoints
|
||||
private static async Task<IResult> VerifyVerdictAsync(
|
||||
string verdictId,
|
||||
[FromServices] IVerdictRepository repository,
|
||||
[FromServices] TimeProvider timeProvider,
|
||||
[FromServices] ILogger<VerdictEndpointsLogger> logger,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -270,11 +272,12 @@ public static class VerdictEndpoints
|
||||
|
||||
// TODO: Implement actual signature verification
|
||||
// For now, return a placeholder response
|
||||
var now = timeProvider.GetUtcNow();
|
||||
var response = new VerifyVerdictResponse
|
||||
{
|
||||
VerdictId = verdictId,
|
||||
SignatureValid = true, // TODO: Implement verification
|
||||
VerifiedAt = DateTimeOffset.UtcNow,
|
||||
VerifiedAt = now,
|
||||
Verifications = new[]
|
||||
{
|
||||
new SignatureVerification
|
||||
@@ -289,7 +292,7 @@ public static class VerdictEndpoints
|
||||
{
|
||||
LogIndex = record.RekorLogIndex.Value,
|
||||
InclusionProofValid = true, // TODO: Implement verification
|
||||
VerifiedAt = DateTimeOffset.UtcNow
|
||||
VerifiedAt = now
|
||||
}
|
||||
: null
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ using StellaOps.EvidenceLocker.Core.Signing;
|
||||
using StellaOps.EvidenceLocker.Core.Incident;
|
||||
using StellaOps.EvidenceLocker.Core.Timeline;
|
||||
using StellaOps.EvidenceLocker.Core.Storage;
|
||||
using StellaOps.Determinism;
|
||||
|
||||
namespace StellaOps.EvidenceLocker.Infrastructure.Services;
|
||||
|
||||
@@ -37,6 +38,7 @@ public sealed class EvidenceSnapshotService
|
||||
private readonly IIncidentModeState _incidentMode;
|
||||
private readonly IEvidenceObjectStore _objectStore;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
private readonly ILogger<EvidenceSnapshotService> _logger;
|
||||
private readonly QuotaOptions _quotas;
|
||||
|
||||
@@ -49,7 +51,8 @@ public sealed class EvidenceSnapshotService
|
||||
IEvidenceObjectStore objectStore,
|
||||
TimeProvider timeProvider,
|
||||
IOptions<EvidenceLockerOptions> options,
|
||||
ILogger<EvidenceSnapshotService> logger)
|
||||
ILogger<EvidenceSnapshotService> logger,
|
||||
IGuidProvider? guidProvider = null)
|
||||
{
|
||||
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
|
||||
_bundleBuilder = bundleBuilder ?? throw new ArgumentNullException(nameof(bundleBuilder));
|
||||
@@ -61,6 +64,7 @@ public sealed class EvidenceSnapshotService
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
_quotas = options.Value.Quotas ?? throw new InvalidOperationException("Quota options are required.");
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
public async Task<EvidenceSnapshotResult> CreateSnapshotAsync(
|
||||
@@ -76,7 +80,7 @@ public sealed class EvidenceSnapshotService
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
ValidateRequest(request);
|
||||
|
||||
var bundleId = EvidenceBundleId.FromGuid(Guid.NewGuid());
|
||||
var bundleId = EvidenceBundleId.FromGuid(_guidProvider.NewGuid());
|
||||
var createdAt = _timeProvider.GetUtcNow();
|
||||
var storageKey = $"tenants/{tenantId.Value:N}/bundles/{bundleId.Value:N}/bundle.tgz";
|
||||
var incidentSnapshot = _incidentMode.Current;
|
||||
@@ -245,7 +249,7 @@ public sealed class EvidenceSnapshotService
|
||||
}
|
||||
}
|
||||
|
||||
var holdId = EvidenceHoldId.FromGuid(Guid.NewGuid());
|
||||
var holdId = EvidenceHoldId.FromGuid(_guidProvider.NewGuid());
|
||||
var createdAt = _timeProvider.GetUtcNow();
|
||||
var hold = new EvidenceHold(
|
||||
holdId,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Cryptography\StellaOps.Cryptography.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Cryptography.DependencyInjection\StellaOps.Cryptography.DependencyInjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Cryptography.Plugin.BouncyCastle\StellaOps.Cryptography.Plugin.BouncyCastle.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Determinism.Abstractions\StellaOps.Determinism.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
|
||||
using StellaOps.EvidenceLocker.Core.Configuration;
|
||||
using StellaOps.EvidenceLocker.Core.Domain;
|
||||
using StellaOps.EvidenceLocker.Core.Storage;
|
||||
using StellaOps.Determinism;
|
||||
|
||||
namespace StellaOps.EvidenceLocker.Infrastructure.Storage;
|
||||
|
||||
@@ -11,11 +12,15 @@ internal sealed class FileSystemEvidenceObjectStore : IEvidenceObjectStore
|
||||
private readonly string _rootPath;
|
||||
private readonly bool _enforceWriteOnce;
|
||||
private readonly ILogger<FileSystemEvidenceObjectStore> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
|
||||
public FileSystemEvidenceObjectStore(
|
||||
FileSystemStoreOptions options,
|
||||
bool enforceWriteOnce,
|
||||
ILogger<FileSystemEvidenceObjectStore> logger)
|
||||
ILogger<FileSystemEvidenceObjectStore> logger,
|
||||
TimeProvider? timeProvider = null,
|
||||
IGuidProvider? guidProvider = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(options.RootPath);
|
||||
@@ -23,6 +28,8 @@ internal sealed class FileSystemEvidenceObjectStore : IEvidenceObjectStore
|
||||
_rootPath = Path.GetFullPath(options.RootPath);
|
||||
_enforceWriteOnce = enforceWriteOnce;
|
||||
_logger = logger;
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
|
||||
Directory.CreateDirectory(_rootPath);
|
||||
}
|
||||
@@ -33,8 +40,8 @@ internal sealed class FileSystemEvidenceObjectStore : IEvidenceObjectStore
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
var writeOnce = _enforceWriteOnce || options.EnforceWriteOnce;
|
||||
var utcNow = DateTimeOffset.UtcNow;
|
||||
var tempFilePath = Path.Combine(_rootPath, ".tmp", Guid.NewGuid().ToString("N"));
|
||||
var utcNow = _timeProvider.GetUtcNow();
|
||||
var tempFilePath = Path.Combine(_rootPath, ".tmp", _guidProvider.NewGuid().ToString("N"));
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath)!);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging;
|
||||
using StellaOps.EvidenceLocker.Core.Configuration;
|
||||
using StellaOps.EvidenceLocker.Core.Domain;
|
||||
using StellaOps.EvidenceLocker.Core.Storage;
|
||||
using StellaOps.Determinism;
|
||||
|
||||
namespace StellaOps.EvidenceLocker.Infrastructure.Storage;
|
||||
|
||||
@@ -15,17 +16,23 @@ internal sealed class S3EvidenceObjectStore : IEvidenceObjectStore, IDisposable
|
||||
private readonly AmazonS3StoreOptions _options;
|
||||
private readonly bool _enforceWriteOnce;
|
||||
private readonly ILogger<S3EvidenceObjectStore> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
|
||||
public S3EvidenceObjectStore(
|
||||
IAmazonS3 s3,
|
||||
AmazonS3StoreOptions options,
|
||||
bool enforceWriteOnce,
|
||||
ILogger<S3EvidenceObjectStore> logger)
|
||||
ILogger<S3EvidenceObjectStore> logger,
|
||||
TimeProvider? timeProvider = null,
|
||||
IGuidProvider? guidProvider = null)
|
||||
{
|
||||
_s3 = s3 ?? throw new ArgumentNullException(nameof(s3));
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_enforceWriteOnce = enforceWriteOnce;
|
||||
_logger = logger;
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
public async Task<EvidenceObjectMetadata> StoreAsync(
|
||||
@@ -37,7 +44,7 @@ internal sealed class S3EvidenceObjectStore : IEvidenceObjectStore, IDisposable
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
var writeOnce = _enforceWriteOnce || options.EnforceWriteOnce;
|
||||
var tempFilePath = Path.Combine(Path.GetTempPath(), $"evidence-{Guid.NewGuid():N}.tmp");
|
||||
var tempFilePath = Path.Combine(Path.GetTempPath(), $"evidence-{_guidProvider.NewGuid():N}.tmp");
|
||||
|
||||
using var sha = SHA256.Create();
|
||||
long totalBytes = 0;
|
||||
@@ -83,7 +90,7 @@ internal sealed class S3EvidenceObjectStore : IEvidenceObjectStore, IDisposable
|
||||
SizeBytes: totalBytes,
|
||||
Sha256: sha256,
|
||||
ETag: eTag,
|
||||
CreatedAt: DateTimeOffset.UtcNow);
|
||||
CreatedAt: _timeProvider.GetUtcNow());
|
||||
}
|
||||
|
||||
public async Task<Stream> OpenReadAsync(string storageKey, CancellationToken cancellationToken)
|
||||
|
||||
@@ -15,6 +15,7 @@ using StellaOps.EvidenceLocker.Core.Configuration;
|
||||
using StellaOps.EvidenceLocker.Core.Domain;
|
||||
using StellaOps.EvidenceLocker.Core.Incident;
|
||||
using StellaOps.EvidenceLocker.Core.Timeline;
|
||||
using StellaOps.Determinism;
|
||||
|
||||
namespace StellaOps.EvidenceLocker.Infrastructure.Timeline;
|
||||
|
||||
@@ -29,12 +30,14 @@ internal sealed class TimelineIndexerEvidenceTimelinePublisher : IEvidenceTimeli
|
||||
private readonly TimelineOptions _options;
|
||||
private readonly ILogger<TimelineIndexerEvidenceTimelinePublisher> _logger;
|
||||
private readonly Uri _endpoint;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
|
||||
public TimelineIndexerEvidenceTimelinePublisher(
|
||||
HttpClient httpClient,
|
||||
IOptions<EvidenceLockerOptions> options,
|
||||
TimeProvider timeProvider,
|
||||
ILogger<TimelineIndexerEvidenceTimelinePublisher> logger)
|
||||
ILogger<TimelineIndexerEvidenceTimelinePublisher> logger,
|
||||
IGuidProvider? guidProvider = null)
|
||||
{
|
||||
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
@@ -53,6 +56,7 @@ internal sealed class TimelineIndexerEvidenceTimelinePublisher : IEvidenceTimeli
|
||||
_endpoint = new Uri(_options.Endpoint, UriKind.Absolute);
|
||||
ArgumentNullException.ThrowIfNull(timeProvider);
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
public async Task PublishBundleSealedAsync(
|
||||
@@ -85,7 +89,7 @@ internal sealed class TimelineIndexerEvidenceTimelinePublisher : IEvidenceTimeli
|
||||
|
||||
private TimelineEventEnvelope BuildBundleEvent(EvidenceBundleSignature signature, EvidenceBundleManifest manifest, string rootHash)
|
||||
{
|
||||
var eventId = Guid.NewGuid();
|
||||
var eventId = _guidProvider.NewGuid();
|
||||
var occurredAt = signature.TimestampedAt ?? signature.SignedAt;
|
||||
var attributes = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||
{
|
||||
@@ -139,7 +143,7 @@ internal sealed class TimelineIndexerEvidenceTimelinePublisher : IEvidenceTimeli
|
||||
|
||||
private TimelineEventEnvelope BuildHoldEvent(EvidenceHold hold)
|
||||
{
|
||||
var eventId = Guid.NewGuid();
|
||||
var eventId = _guidProvider.NewGuid();
|
||||
var occurredAt = hold.CreatedAt;
|
||||
var attributes = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||
{
|
||||
@@ -175,7 +179,7 @@ internal sealed class TimelineIndexerEvidenceTimelinePublisher : IEvidenceTimeli
|
||||
|
||||
private TimelineEventEnvelope BuildIncidentEvent(IncidentModeChange change)
|
||||
{
|
||||
var eventId = Guid.NewGuid();
|
||||
var eventId = _guidProvider.NewGuid();
|
||||
var attributes = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||
{
|
||||
["state"] = change.IsActive ? "enabled" : "disabled",
|
||||
|
||||
@@ -63,7 +63,7 @@ public sealed record VerdictAttestationRecord
|
||||
public required string PredicateDigest { get; init; }
|
||||
public string? DeterminismHash { get; init; }
|
||||
public long? RekorLogIndex { get; init; }
|
||||
public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow;
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user