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

- 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:
StellaOps Bot
2025-12-03 07:51:50 +02:00
parent 37cba83708
commit e923880694
171 changed files with 6567 additions and 2952 deletions

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env bash
set -euo pipefail
# Offline verifier for policy-sim inputs lock (PS1PS10 remediation).
# Usage: verify-policy-sim-lock.sh lock.json --policy path --graph path --sbom path --time-anchor path --dataset path [--max-age-hours 24]
usage() {
echo "Usage: $0 lock.json --policy <file> --graph <file> --sbom <file> --time-anchor <file> --dataset <file> [--max-age-hours <n>]" >&2
exit 2
}
[[ $# -lt 11 ]] && usage
lock=""
policy=""
graph=""
sbom=""
time_anchor=""
dataset=""
max_age_hours=0
while [[ $# -gt 0 ]]; do
case "$1" in
--policy) policy=${2:-}; shift ;;
--graph) graph=${2:-}; shift ;;
--sbom) sbom=${2:-}; shift ;;
--time-anchor) time_anchor=${2:-}; shift ;;
--dataset) dataset=${2:-}; shift ;;
--max-age-hours) max_age_hours=${2:-0}; shift ;;
*) if [[ -z "$lock" ]]; then lock=$1; else usage; fi ;;
esac
shift
done
[[ -z "$lock" || -z "$policy" || -z "$graph" || -z "$sbom" || -z "$time_anchor" || -z "$dataset" ]] && usage
require() { command -v "$1" >/dev/null || { echo "$1 is required" >&2; exit 2; }; }
require jq
require sha256sum
calc_sha() { sha256sum "$1" | awk '{print $1}'; }
lock_policy=$(jq -r '.policyBundleSha256' "$lock")
lock_graph=$(jq -r '.graphSha256' "$lock")
lock_sbom=$(jq -r '.sbomSha256' "$lock")
lock_anchor=$(jq -r '.timeAnchorSha256' "$lock")
lock_dataset=$(jq -r '.datasetSha256' "$lock")
lock_shadow=$(jq -r '.shadowIsolation' "$lock")
lock_scopes=$(jq -r '.requiredScopes[]?' "$lock" | tr '\n' ' ')
lock_generated=$(jq -r '.generatedAt' "$lock")
sha_ok() {
[[ $1 =~ ^[A-Fa-f0-9]{64}$ ]]
}
for h in "$lock_policy" "$lock_graph" "$lock_sbom" "$lock_anchor" "$lock_dataset"; do
sha_ok "$h" || { echo "invalid digest format: $h" >&2; exit 3; }
done
[[ "$lock_shadow" == "true" ]] || { echo "shadowIsolation must be true" >&2; exit 5; }
if ! grep -qi "policy:simulate:shadow" <<< "$lock_scopes"; then
echo "requiredScopes missing policy:simulate:shadow" >&2; exit 5;
fi
[[ "$lock_policy" == "$(calc_sha "$policy")" ]] || { echo "policy digest mismatch" >&2; exit 3; }
[[ "$lock_graph" == "$(calc_sha "$graph")" ]] || { echo "graph digest mismatch" >&2; exit 3; }
[[ "$lock_sbom" == "$(calc_sha "$sbom")" ]] || { echo "sbom digest mismatch" >&2; exit 3; }
[[ "$lock_anchor" == "$(calc_sha "$time_anchor")" ]] || { echo "time anchor digest mismatch" >&2; exit 3; }
[[ "$lock_dataset" == "$(calc_sha "$dataset")" ]] || { echo "dataset digest mismatch" >&2; exit 3; }
if [[ $max_age_hours -gt 0 ]]; then
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
age_hours=$(python3 - <<'PY'
import sys,datetime
lock=sys.argv[1].replace('Z','+00:00')
now=sys.argv[2].replace('Z','+00:00')
l=datetime.datetime.fromisoformat(lock)
n=datetime.datetime.fromisoformat(now)
print((n-l).total_seconds()/3600)
PY
"$lock_generated" "$now")
if (( $(printf '%.0f' "$age_hours") > max_age_hours )); then
echo "lock stale: ${age_hours}h > ${max_age_hours}h" >&2
exit 4
fi
fi
echo "policy-sim lock verified (shadow mode enforced)."