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.
89 lines
2.9 KiB
Bash
89 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# Offline verifier for policy-sim inputs lock (PS1–PS10 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)."
|