feat: Add DigestUpsertRequest and LockEntity models
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
- Introduced DigestUpsertRequest for handling digest upsert requests with properties like ChannelId, Recipient, DigestKey, Events, and CollectUntil. - Created LockEntity to represent a lightweight distributed lock entry with properties such as Id, TenantId, Resource, Owner, ExpiresAt, and CreatedAt. feat: Implement ILockRepository interface and LockRepository class - Defined ILockRepository interface with methods for acquiring and releasing locks. - Implemented LockRepository class with methods to try acquiring a lock and releasing it, using SQL for upsert operations. feat: Add SurfaceManifestPointer record for manifest pointers - Introduced SurfaceManifestPointer to represent a minimal pointer to a Surface.FS manifest associated with an image digest. feat: Create PolicySimulationInputLock and related validation logic - Added PolicySimulationInputLock record to describe policy simulation inputs and expected digests. - Implemented validation logic for policy simulation inputs, including checks for digest drift and shadow mode requirements. test: Add unit tests for ReplayVerificationService and ReplayVerifier - Created ReplayVerificationServiceTests to validate the behavior of the ReplayVerificationService under various scenarios. - Developed ReplayVerifierTests to ensure the correctness of the ReplayVerifier logic. test: Implement PolicySimulationInputLockValidatorTests - Added tests for PolicySimulationInputLockValidator to verify the validation logic against expected inputs and conditions. chore: Add cosign key example and signing scripts - Included a placeholder cosign key example for development purposes. - Added a script for signing Signals artifacts using cosign with support for both v2 and v3. chore: Create script for uploading evidence to the evidence locker - Developed a script to upload evidence to the evidence locker, ensuring required environment variables are set.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.AirGap.Importer.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Replay enforcement depth for offline kit verification.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum ReplayDepth
|
||||
{
|
||||
HashOnly,
|
||||
FullRecompute,
|
||||
PolicyFreeze
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace StellaOps.AirGap.Importer.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Inputs required to enforce replay depth for an offline kit.
|
||||
/// </summary>
|
||||
public sealed record ReplayVerificationRequest(
|
||||
string ExpectedManifestSha256,
|
||||
string ExpectedBundleSha256,
|
||||
string ComputedManifestSha256,
|
||||
string ComputedBundleSha256,
|
||||
DateTimeOffset ManifestCreatedAt,
|
||||
int StalenessWindowHours,
|
||||
string? BundlePolicyHash,
|
||||
string? SealedPolicyHash,
|
||||
ReplayDepth Depth);
|
||||
|
||||
public sealed record ReplayVerificationResult(bool IsValid, string Reason)
|
||||
{
|
||||
public static ReplayVerificationResult Success(string reason = "ok") => new(true, reason);
|
||||
public static ReplayVerificationResult Failure(string reason) => new(false, reason);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using StellaOps.AirGap.Importer.Contracts;
|
||||
|
||||
namespace StellaOps.AirGap.Importer.Validation;
|
||||
|
||||
/// <summary>
|
||||
/// Enforces replay depth semantics for offline kit validation.
|
||||
/// </summary>
|
||||
public sealed class ReplayVerifier
|
||||
{
|
||||
public ReplayVerificationResult Verify(ReplayVerificationRequest request, DateTimeOffset nowUtc)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.ExpectedManifestSha256) ||
|
||||
string.IsNullOrWhiteSpace(request.ExpectedBundleSha256) ||
|
||||
string.IsNullOrWhiteSpace(request.ComputedManifestSha256) ||
|
||||
string.IsNullOrWhiteSpace(request.ComputedBundleSha256))
|
||||
{
|
||||
return ReplayVerificationResult.Failure("hash-missing");
|
||||
}
|
||||
|
||||
if (!string.Equals(request.ExpectedManifestSha256, request.ComputedManifestSha256, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ReplayVerificationResult.Failure("manifest-hash-drift");
|
||||
}
|
||||
|
||||
if (!string.Equals(request.ExpectedBundleSha256, request.ComputedBundleSha256, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ReplayVerificationResult.Failure("bundle-hash-drift");
|
||||
}
|
||||
|
||||
if (request.StalenessWindowHours >= 0)
|
||||
{
|
||||
var age = nowUtc - request.ManifestCreatedAt;
|
||||
if (age > TimeSpan.FromHours(request.StalenessWindowHours))
|
||||
{
|
||||
return ReplayVerificationResult.Failure("manifest-stale");
|
||||
}
|
||||
}
|
||||
|
||||
if (request.Depth == ReplayDepth.PolicyFreeze)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.SealedPolicyHash) || string.IsNullOrWhiteSpace(request.BundlePolicyHash))
|
||||
{
|
||||
return ReplayVerificationResult.Failure("policy-hash-missing");
|
||||
}
|
||||
|
||||
if (!string.Equals(request.BundlePolicyHash, request.SealedPolicyHash, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ReplayVerificationResult.Failure("policy-hash-drift");
|
||||
}
|
||||
}
|
||||
|
||||
return request.Depth switch
|
||||
{
|
||||
ReplayDepth.HashOnly => ReplayVerificationResult.Success("hash-only-passed"),
|
||||
ReplayDepth.FullRecompute => ReplayVerificationResult.Success("full-recompute-passed"),
|
||||
ReplayDepth.PolicyFreeze => ReplayVerificationResult.Success("policy-freeze-passed"),
|
||||
_ => ReplayVerificationResult.Failure("unknown-depth")
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user