Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

provenance/tests/slsa_dwarf_release.rs

//! Holger's provenance scanner verifies a release bundle from dwarves, the build server,
//! in its SLSA Build L3 release-build mode (dwarves-slsa): a DSSE envelope, key-signed (ECDSA P-256, as the
//! owner's YubiKey signs), over one in-toto v1 / SLSA Provenance v1 statement for a
//! whole release. The policy is the one docs/SLSA.md gives operators.

use holger_provenance::{effective, verify_artifact, ProvenanceFloor, ProvenanceGate, Verdict};

const DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/slsa-dwarf");
const BUILDER: &str = "https://git.gunnar.rs/nordisk/dwarves/slsa/builders/dwarves-server/v1";
const KEYID: &str = "b7238cc7bd98598c053314a119a98e670bc3ab1243cf3f7bf35817a7e3f4b6a5";

fn read(name: &str) -> Vec<u8> {
    std::fs::read(format!("{DIR}/{name}")).unwrap()
}

/// The operator's RON (docs/SLSA.md): the release key on the floor, the dwarves builder at
/// SLSA build level 3 and the key on the source's gate.
fn policy(level: u8, slsa_min: u8) -> holger_provenance::EffectivePolicy {
    let pem = String::from_utf8(read("release-test-key.pub")).unwrap();
    let floor: ProvenanceFloor = ron::from_str(&format!(
        r#"(keys: [(id: "{KEYID}", alg: ecdsa_p256, public_key: "{}")])"#,
        pem.replace('\n', "\\n")
    ))
    .unwrap();
    let gate: ProvenanceGate =
        ron::from_str(&format!(r#"require(builders: [(id: "{BUILDER}", level: {level})], keys: ["{KEYID}"], slsa_min: {slsa_min})"#)).unwrap();
    effective(&floor, &gate)
}

fn bundle() -> Vec<(String, Vec<u8>)> {
    vec![(
        "holger-2.0.0-rebuild.intoto.jsonl".to_string(),
        read("holger-2.0.0-rebuild.intoto.jsonl"),
    )]
}

#[test]
fn a_crate_of_a_dwarves_release_passes_at_slsa_build_level_3() {
    let r = verify_artifact(
        &read("holger-errcode-2.0.0.crate"),
        &bundle(),
        &policy(3, 3),
        None,
    );
    assert_eq!(r.verdict, Verdict::Pass, "{}", r.detail);
    let c = r
        .verified_provenance()
        .next()
        .expect("a verified provenance candidate");
    assert_eq!(c.builder_id.as_deref(), Some(BUILDER));
    assert_eq!(c.slsa_level, Some(3));
    let slsa = c.slsa.as_ref().unwrap();
    assert_eq!(
        slsa.build_type,
        "https://git.gunnar.rs/nordisk/dwarves/slsa/buildtypes/cargo-release/v1"
    );
    assert_eq!(slsa.external_parameters["release"], "holger-2.0.0-rebuild");
    assert!(slsa
        .resolved_dependencies
        .iter()
        .any(|d| d["digest"]["gitCommit"] == "87e5ada50ab5745464e4b46305bfd62d0460f52c"));
}

#[test]
fn a_changed_crate_is_refused() {
    let mut bytes = read("holger-errcode-2.0.0.crate");
    let n = bytes.len();
    bytes[n - 1] ^= 1;
    let r = verify_artifact(&bytes, &bundle(), &policy(3, 3), None);
    assert_eq!(r.verdict, Verdict::Block, "{}", r.detail);
}

#[test]
fn without_the_builder_at_level_3_the_minimum_refuses_it() {
    // A builder the policy names without a level counts as a signed builder (L2).
    let pem = String::from_utf8(read("release-test-key.pub")).unwrap();
    let floor: ProvenanceFloor = ron::from_str(&format!(
        r#"(keys: [(id: "{KEYID}", alg: ecdsa_p256, public_key: "{}")])"#,
        pem.replace('\n', "\\n")
    ))
    .unwrap();
    let gate: ProvenanceGate = ron::from_str(&format!(
        r#"require(builders: ["{BUILDER}"], keys: ["{KEYID}"], slsa_min: 3)"#
    ))
    .unwrap();
    let r = verify_artifact(
        &read("holger-errcode-2.0.0.crate"),
        &bundle(),
        &effective(&floor, &gate),
        None,
    );
    assert_eq!(r.verdict, Verdict::Block, "{}", r.detail);
    assert_eq!(
        r.code.as_deref(),
        Some("holger-provenance-7"),
        "{}",
        r.detail
    );
}

#[test]
fn another_key_is_refused() {
    let other = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYMc989J2nOEa5vxSMSfKIxhMSv6hulsvWVx8o36/jGzQtXVXeopc2v+lPihUGW/PhKT+BpLPxM7EP4Ayo/6NRw==\n-----END PUBLIC KEY-----\n";
    let floor: ProvenanceFloor = ron::from_str(&format!(
        r#"(keys: [(id: "{KEYID}", alg: ecdsa_p256, public_key: "{}")])"#,
        other.replace('\n', "\\n")
    ))
    .unwrap();
    let gate: ProvenanceGate = ron::from_str(&format!(
        r#"require(builders: [(id: "{BUILDER}", level: 3)], keys: ["{KEYID}"], slsa_min: 3)"#
    ))
    .unwrap();
    let r = verify_artifact(
        &read("holger-errcode-2.0.0.crate"),
        &bundle(),
        &effective(&floor, &gate),
        None,
    );
    assert_eq!(r.verdict, Verdict::Block, "{}", r.detail);
    // Refused for the signature, not for an unreadable key.
    assert_eq!(
        r.code.as_deref(),
        Some("holger-provenance-3"),
        "{}",
        r.detail
    );
}