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.
106 lines
4.0 KiB
Python
106 lines
4.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Sign mirror-thin-v1 artefacts using an Ed25519 key and emit DSSE + TUF signatures.
|
|
|
|
Usage:
|
|
python scripts/mirror/sign_thin_bundle.py \
|
|
--key out/mirror/thin/tuf/keys/mirror-ed25519-test-1.pem \
|
|
--manifest out/mirror/thin/mirror-thin-v1.manifest.json \
|
|
--tar out/mirror/thin/mirror-thin-v1.tar.gz \
|
|
--tuf-dir out/mirror/thin/tuf \
|
|
--time-anchor out/mirror/thin/stage-v1/layers/time-anchor.json
|
|
|
|
Writes:
|
|
- mirror-thin-v1.manifest.dsse.json
|
|
- mirror-thin-v1.bundle.dsse.json (optional, when --bundle is provided)
|
|
- updates signatures in root.json, targets.json, snapshot.json, timestamp.json
|
|
"""
|
|
import argparse, base64, json, pathlib, hashlib
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
|
|
def b64url(data: bytes) -> str:
|
|
return base64.urlsafe_b64encode(data).rstrip(b"=").decode()
|
|
|
|
def load_key(path: pathlib.Path) -> Ed25519PrivateKey:
|
|
return serialization.load_pem_private_key(path.read_bytes(), password=None)
|
|
|
|
def keyid_from_pub(pub_path: pathlib.Path) -> str:
|
|
raw = pub_path.read_bytes()
|
|
return hashlib.sha256(raw).hexdigest()
|
|
|
|
def sign_bytes(key: Ed25519PrivateKey, data: bytes) -> bytes:
|
|
return key.sign(data)
|
|
|
|
def write_json(path: pathlib.Path, obj):
|
|
path.write_text(json.dumps(obj, indent=2, sort_keys=True) + "\n")
|
|
|
|
def sign_tuf(path: pathlib.Path, keyid: str, key: Ed25519PrivateKey):
|
|
data = path.read_bytes()
|
|
sig = sign_bytes(key, data)
|
|
obj = json.loads(data)
|
|
obj["signatures"] = [{"keyid": keyid, "sig": b64url(sig)}]
|
|
write_json(path, obj)
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--key", required=True, type=pathlib.Path)
|
|
ap.add_argument("--manifest", required=True, type=pathlib.Path)
|
|
ap.add_argument("--tar", required=True, type=pathlib.Path)
|
|
ap.add_argument("--tuf-dir", required=True, type=pathlib.Path)
|
|
ap.add_argument("--bundle", required=False, type=pathlib.Path)
|
|
ap.add_argument("--time-anchor", required=False, type=pathlib.Path)
|
|
args = ap.parse_args()
|
|
|
|
key = load_key(args.key)
|
|
pub_path = args.key.with_suffix(".pub")
|
|
keyid = keyid_from_pub(pub_path)
|
|
|
|
manifest_bytes = args.manifest.read_bytes()
|
|
sig = sign_bytes(key, manifest_bytes)
|
|
dsse = {
|
|
"payloadType": "application/vnd.stellaops.mirror.manifest+json",
|
|
"payload": b64url(manifest_bytes),
|
|
"signatures": [{"keyid": keyid, "sig": b64url(sig)}],
|
|
}
|
|
dsse_path = args.manifest.with_suffix(".dsse.json")
|
|
write_json(dsse_path, dsse)
|
|
|
|
if args.bundle:
|
|
bundle_bytes = args.bundle.read_bytes()
|
|
bundle_sig = sign_bytes(key, bundle_bytes)
|
|
bundle_dsse = {
|
|
"payloadType": "application/vnd.stellaops.mirror.bundle+json",
|
|
"payload": b64url(bundle_bytes),
|
|
"signatures": [{"keyid": keyid, "sig": b64url(bundle_sig)}],
|
|
}
|
|
bundle_dsse_path = args.bundle.with_suffix(".dsse.json")
|
|
write_json(bundle_dsse_path, bundle_dsse)
|
|
|
|
anchor_dsse_path = None
|
|
if args.time_anchor:
|
|
anchor_bytes = args.time_anchor.read_bytes()
|
|
anchor_sig = sign_bytes(key, anchor_bytes)
|
|
anchor_dsse = {
|
|
"payloadType": "application/vnd.stellaops.time-anchor+json",
|
|
"payload": b64url(anchor_bytes),
|
|
"signatures": [{"keyid": keyid, "sig": b64url(anchor_sig)}],
|
|
}
|
|
anchor_dsse_path = args.time_anchor.with_suffix(".dsse.json")
|
|
write_json(anchor_dsse_path, anchor_dsse)
|
|
|
|
# update TUF metadata
|
|
for name in ["root.json", "targets.json", "snapshot.json", "timestamp.json"]:
|
|
sign_tuf(args.tuf_dir / name, keyid, key)
|
|
|
|
parts = [f"manifest DSSE -> {dsse_path}"]
|
|
if args.bundle:
|
|
parts.append(f"bundle DSSE -> {bundle_dsse_path}")
|
|
if anchor_dsse_path:
|
|
parts.append(f"time anchor DSSE -> {anchor_dsse_path}")
|
|
parts.append("TUF metadata updated")
|
|
print(f"Signed DSSE + TUF using keyid {keyid}; " + ", ".join(parts))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|