Add sample proof bundle configurations and verification script
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
Console CI / console-ci (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
VEX Proof Bundles / verify-bundles (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
Console CI / console-ci (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
VEX Proof Bundles / verify-bundles (push) Has been cancelled
- Introduced sample proof bundle configuration files for testing, including `sample-proof-bundle-config.dsse.json`, `sample-proof-bundle.dsse.json`, and `sample-proof-bundle.json`. - Implemented a verification script `test_verify_sample.sh` to validate proof bundles against specified schemas and catalogs. - Updated existing proof bundle configurations with new metadata, including versioning, created timestamps, and justification details. - Enhanced evidence entries with expiration dates and hashes for better integrity checks. - Ensured all new configurations adhere to the defined schema for consistency and reliability in testing.
This commit is contained in:
99
docs/modules/export-center/operations/verify-export-kit.sh
Normal file
99
docs/modules/export-center/operations/verify-export-kit.sh
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Offline verifier for Export Center bundles (EC10)
|
||||
# Usage: VERIFY_FIXTURE=1 ./verify-export-kit.sh [kit_dir]
|
||||
|
||||
kit_dir="${1:-src/ExportCenter/__fixtures/export-kit}"
|
||||
|
||||
for f in manifest.json manifest.sha256 provenance.json manifest.dsse; do
|
||||
if [[ ! -f "${kit_dir}/${f}" ]]; then
|
||||
echo "missing ${kit_dir}/${f}" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
manifest_sha="$(sha256sum "${kit_dir}/manifest.json" | awk '{print $1}')"
|
||||
expected_sha="$(awk '{print $1}' "${kit_dir}/manifest.sha256")"
|
||||
|
||||
if [[ "${manifest_sha}" != "${expected_sha}" ]]; then
|
||||
echo "manifest hash mismatch: expected ${expected_sha} got ${manifest_sha}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
python - <<'PY' "${kit_dir}" "${manifest_sha}"
|
||||
import base64, hashlib, json, sys, pathlib
|
||||
|
||||
kit = pathlib.Path(sys.argv[1])
|
||||
manifest_sha = sys.argv[2]
|
||||
manifest = json.loads(kit.joinpath("manifest.json").read_text())
|
||||
|
||||
errors = []
|
||||
selectors = manifest.get("selectors", {})
|
||||
tenants = selectors.get("tenants", [])
|
||||
tenant = manifest.get("tenant")
|
||||
|
||||
if tenant and tenants and tenant not in tenants and "*" not in tenants[0]:
|
||||
errors.append(f"tenant {tenant} not included in selectors.tenants {tenants}")
|
||||
|
||||
digests = []
|
||||
for item in manifest.get("contents", []):
|
||||
digest = item.get("digest", "")
|
||||
if not digest.startswith("sha256:"):
|
||||
errors.append(f"invalid digest format for {item.get('path')}")
|
||||
continue
|
||||
digests.append(digest.split("sha256:")[1])
|
||||
|
||||
rerun_calc = hashlib.sha256("\n".join(sorted(digests)).encode()).hexdigest()
|
||||
rerun_expected = manifest.get("rerunHash")
|
||||
if rerun_expected != f"sha256:{rerun_calc}":
|
||||
errors.append(f"rerunHash mismatch: expected sha256:{rerun_calc} got {rerun_expected}")
|
||||
|
||||
annotations = manifest["integrity"]["oci"]["annotations"]
|
||||
manifest_digest_hex = annotations["io.stellaops.export.manifest-digest"].split("sha256:")[1]
|
||||
digest_hdr = manifest["integrity"]["httpHeaders"]["Digest"]
|
||||
expected_hdr = "sha-256=" + base64.b64encode(bytes.fromhex(manifest_digest_hex)).decode()
|
||||
if digest_hdr != expected_hdr:
|
||||
errors.append("Digest header does not match manifest digest annotation")
|
||||
|
||||
log_meta = manifest.get("attestations", {}).get("log")
|
||||
if not log_meta:
|
||||
errors.append("attestation log metadata missing")
|
||||
|
||||
if not manifest.get("quotas"):
|
||||
errors.append("quotas/backpressure block missing")
|
||||
|
||||
if len(set(tenants)) > 1 and not manifest.get("approval", {}).get("required"):
|
||||
errors.append("cross-tenant approval required but not present")
|
||||
|
||||
if errors:
|
||||
for err in errors:
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
print("manifest checks ok")
|
||||
PY
|
||||
|
||||
python - <<'PY' "${kit_dir}" "${manifest_sha}"
|
||||
import json, sys, pathlib
|
||||
|
||||
kit = pathlib.Path(sys.argv[1])
|
||||
manifest_sha = sys.argv[2]
|
||||
prov = json.loads(kit.joinpath("provenance.json").read_text())
|
||||
|
||||
manifest_subject = prov["subject"][0]["digest"]["sha256"]
|
||||
if manifest_subject != manifest_sha:
|
||||
print(f"provenance manifest digest mismatch: {manifest_subject} vs {manifest_sha}")
|
||||
sys.exit(1)
|
||||
|
||||
log = prov["predicate"]["environment"]["logs"]
|
||||
required = ["kind", "logId", "logIndex", "entryDigest", "timestamp"]
|
||||
missing = [k for k in required if k not in log]
|
||||
if missing:
|
||||
print(f"provenance log metadata missing keys: {missing}")
|
||||
sys.exit(1)
|
||||
|
||||
print("provenance checks ok")
|
||||
PY
|
||||
|
||||
echo "verify-export-kit: PASS"
|
||||
Reference in New Issue
Block a user