server/lib/tests/oci_evidence/keyless.rs
//! Keyless signing as `cosign sign` writes it, against a Sigstore minted in the test
//! (`provenance/tests/common`), and the signed trust bundle that pins it (HOL-OCI-EVIDENCE).
#![allow(dead_code)]
#[path = "../../../../provenance/tests/common/mod.rs"]
pub mod sigstore;
use rcgen::SigningKey as _;
use sigstore::{MiniSigstore, SIGNED_AT};
use super::*;
/// The signed trust bundle that pins `ms`, and the bundle trust policy that verifies it.
pub struct Trust {
pub _dir: tempfile::TempDir,
pub bundle: String,
pub policy: String,
}
pub fn trust(ms: &MiniSigstore) -> Trust {
use holger_provenance::trust::{build_trust_bundle, BundleSigner, TrustBundleOptions};
use update_bundle::policy::{
ApprovedSigner, CertificateValidity, ExpiredPosture, TrustMode, TrustPolicy,
};
use update_bundle::schema::POLICY_SCHEMA;
let mint = |cn: &str| {
let key = rcgen::KeyPair::generate_for(&rcgen::PKCS_ED25519).unwrap();
let mut p = rcgen::CertificateParams::new(vec![]).unwrap();
p.distinguished_name.push(rcgen::DnType::CommonName, cn);
let der = p.self_signed(&key).unwrap().der().to_vec();
(
holger_provenance::crypto::sha256_hex(&der),
BundleSigner {
cert_der: der,
key_pkcs8: key.serialize_der(),
},
)
};
let (fr, reviewer) = mint("trust-reviewer");
let (fo, owner) = mint("trust-owner");
let (fl, release) = mint("trust-release");
let policy = TrustPolicy {
schema_version: POLICY_SCHEMA.to_string(),
trust_mode: Some(TrustMode::PinnedSigners),
trusted_roots: vec![],
certificate_validity: CertificateValidity::Enforce,
approved_signers: vec![
ApprovedSigner {
fingerprint: fr,
subject: None,
roles: vec!["security-reviewer".into()],
},
ApprovedSigner {
fingerprint: fo,
subject: None,
roles: vec!["system-owner".into()],
},
],
required_approval_roles: vec!["security-reviewer".into(), "system-owner".into()],
minimum_distinct_approvers: 2,
trusted_release_signers: vec![fl],
release_signer_must_be_distinct: true,
maximum_bundle_age_secs: None,
require_expiry: true,
on_expired_metadata: Some(ExpiredPosture::Refuse),
require_sbom: false,
require_vex: false,
require_scan: false,
allowed_products: vec![holger_provenance::TRUST_PRODUCT.into()],
allowed_models: vec![],
};
let dir = tempfile::tempdir().unwrap();
let now = chrono::Utc::now();
let bundle = build_trust_bundle(
&ms.trusted_root_json(),
TrustBundleOptions {
sequence: 1,
created_at: now - chrono::Duration::minutes(5),
expires_at: Some(now + chrono::Duration::days(90)),
supplier: "holger-sigstore-trust".into(),
producer: "test".into(),
source_uri: Some("https://tuf.example.test".into()),
policy: policy.clone(),
approvals: vec![
("security-reviewer".into(), reviewer),
("system-owner".into(), owner),
],
release,
out: dir.path().join("sigstore-trust.holger.znippy"),
apk_keys: vec![],
pgp_keys: vec![],
},
)
.expect("the trust bundle is signed");
let policy_path = dir.path().join("bundle-trust.ron");
std::fs::write(&policy_path, policy.to_ron().unwrap()).unwrap();
Trust {
bundle: bundle.display().to_string(),
policy: policy_path.display().to_string(),
_dir: dir,
}
}
/// **A keyless cosign `.sig` manifest** for `digest`, signed as (`issuer`, `subject`): the
/// simple-signing payload `cosign sign` writes, its signature, the Fulcio-like leaf and the
/// chain, and the Rekor bundle (a `hashedrekord` 0.0.1 body, its SET) as layer annotations.
pub fn keyless_sig(
ms: &MiniSigstore,
reference: &str,
digest: &str,
issuer: &str,
subject: &str,
) -> (Vec<u8>, Vec<Vec<u8>>) {
use holger_provenance::{crypto, tlog};
let payload = serde_json::to_vec(&serde_json::json!({
"critical": {
"identity": {"docker-reference": reference},
"image": {"docker-manifest-digest": digest},
"type": "cosign container image signature",
},
"optional": null,
}))
.unwrap();
let (key, cert) = ms.leaf(issuer, subject, (2026, 10, 23));
let sig = key.sign(&payload).unwrap();
let cert_pem = sigstore::pem_of_der("CERTIFICATE", &cert);
let body = serde_json::to_vec(&serde_json::json!({
"apiVersion": "0.0.1", "kind": "hashedrekord",
"spec": {
"data": {"hash": {"algorithm": "sha256", "value": crypto::sha256_hex(&payload)}},
"signature": {"content": b64(&sig), "publicKey": {"content": b64(cert_pem.as_bytes())}},
},
}))
.unwrap();
let entry = holger_provenance::material::TlogEntry {
log_index: 4242,
log_id: ms.rekor_id(),
integrated_time: SIGNED_AT,
kind: "hashedrekord".into(),
version: "0.0.1".into(),
body: body.clone(),
set: None,
proof: None,
};
let set = ms.rekor.sign(&tlog::set_payload(&entry)).unwrap();
let bundle = serde_json::json!({
"SignedEntryTimestamp": b64(&set),
"Payload": {"body": b64(&body), "integratedTime": SIGNED_AT, "logIndex": 4242, "logID": hex::encode(ms.rekor_id())},
});
let config = br#"{"architecture":"","created":"0001-01-01T00:00:00Z","history":[{"created":"0001-01-01T00:00:00Z"}],"os":"","rootfs":{"type":"layers","diff_ids":[]},"config":{}}"#.to_vec();
let manifest = serde_json::to_vec(&serde_json::json!({
"schemaVersion": 2, "mediaType": MANIFEST,
"config": {"mediaType": CONFIG, "digest": super::digest(&config), "size": config.len()},
"layers": [{
"mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
"digest": super::digest(&payload), "size": payload.len(),
"annotations": {
"dev.cosignproject.cosign/signature": b64(&sig),
"dev.sigstore.cosign/certificate": cert_pem,
"dev.sigstore.cosign/chain": sigstore::pem_of_der("CERTIFICATE", &ms.root_der),
"dev.sigstore.cosign/bundle": bundle.to_string(),
},
}],
}))
.unwrap();
(manifest, vec![config, payload])
}
/// Push `img` by digest, its `.sig` (when given), then the tag that takes it in.
pub fn push_signed(
r: &Running,
name: &str,
img: &Img,
sig: Option<(Vec<u8>, Vec<Vec<u8>>)>,
) -> (u16, String, Vec<u8>) {
push_blobs(r, "ida", name, &img.blobs());
assert_eq!(
push_manifest(r, "ida", name, &img.digest, &img.manifest).0,
201
);
if let Some((m, blobs)) = sig {
push_blobs(r, "ida", name, &blobs);
let tag = format!("sha256-{}.sig", img.digest.trim_start_matches("sha256:"));
assert_eq!(push_manifest(r, "ida", name, &tag, &m).0, 201);
}
push_manifest(r, "ida", name, "v1", &img.manifest)
}