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

nordisk/holger

server/cli/src/sigstore_cli.rs

//! **`holger sigstore-trust`** (lane HOL-OCI-EVIDENCE): the estate's Sigstore trust root
//! (`server_lib::sigstore_trust`).
//!
//! * `make` (the release build; `cargo xtask sigstore-trust stage` runs it): Sigstore's
//!   `trusted_root.json` (held to the pinned digest unless `--unpinned`, a test's own root)
//!   signed into a `holger.sigstore-trust/v1` bundle by the three identities under
//!   `--signer-dir` (minted on first use, keys 0600), and the bundle trust policy that pins them.
//! * `status --config C`: what the box has installed under `<data_root>/holger-trust`.
//!
//! A refresh is carried in like any bundle: `holger bundle import`, the inbox, the import doors.

use std::path::PathBuf;

use anyhow::{Context, Result};
use clap::{Args, Subcommand};

#[derive(Args)]
pub struct SigstoreTrustArgs {
    #[command(subcommand)]
    pub op: SigstoreTrustOp,
}

#[derive(Subcommand)]
pub enum SigstoreTrustOp {
    /// Sign a trusted_root.json into a trust bundle (the release build).
    Make {
        /// Sigstore's trusted_root.json (the pinned TUF target).
        #[arg(long)]
        root: PathBuf,
        /// The release trust identities, minted here on first use.
        #[arg(long)]
        signer_dir: PathBuf,
        /// The trust bundle to write.
        #[arg(long)]
        out: PathBuf,
        /// Write the bundle trust policy that pins the identities.
        #[arg(long)]
        policy_out: Option<PathBuf>,
        /// The bundle's sequence (each refresh higher). Default: this machine's clock, seconds.
        #[arg(long)]
        sequence: Option<u64>,
        #[arg(long, default_value_t = 730)]
        valid_days: i64,
        /// Take a root that is not the pinned public-good one (a test's own Sigstore).
        #[arg(long)]
        unpinned: bool,
    },
    /// What the box has installed.
    Status {
        #[arg(short, long)]
        config: PathBuf,
    },
}

pub fn run(a: SigstoreTrustArgs) -> Result<()> {
    match a.op {
        SigstoreTrustOp::Make {
            root,
            signer_dir,
            out,
            policy_out,
            sequence,
            valid_days,
            unpinned,
        } => {
            let json = std::fs::read(&root).with_context(|| format!("read {}", root.display()))?;
            if !unpinned {
                server_lib::sigstore_trust::check_pinned(&json).map_err(|e| anyhow::anyhow!(e))?;
            }
            let sequence = sequence.unwrap_or_else(|| chrono::Utc::now().timestamp().max(1) as u64);
            make(&json, &signer_dir, &out, sequence, valid_days, policy_out)
        }
        SigstoreTrustOp::Status { config } => {
            let holger = server_lib::read_ron_config(&config)
                .with_context(|| format!("load config {}", config.display()))?;
            match server_lib::sigstore_trust::installed(&holger.data_root()) {
                Some(i) => println!(
                    "SIGSTORE TRUST ROOT seq {} ({}) from {} at {}: trusted_root sha256:{} at {}",
                    i.sequence, i.bundle_id, i.from, i.at, i.trusted_root_sha256, i.path
                ),
                None => println!(
                    "SIGSTORE TRUST ROOT none installed under {}",
                    server_lib::sigstore_trust::dir(&holger.data_root()).display()
                ),
            }
            Ok(())
        }
    }
}

#[cfg(feature = "export-push")]
fn make(
    json: &[u8],
    signer_dir: &std::path::Path,
    out: &std::path::Path,
    sequence: u64,
    valid_days: i64,
    policy_out: Option<PathBuf>,
) -> Result<()> {
    let policy = server_lib::sigstore_trust::make(
        json,
        signer_dir,
        out,
        sequence,
        valid_days,
        Some(server_lib::sigstore_trust::pinned_url()),
    )?;
    println!(
        "SIGSTORE TRUST BUNDLE {} seq {sequence} (valid {valid_days} d)",
        out.display()
    );
    if let Some(p) = policy_out {
        std::fs::write(
            &p,
            policy
                .to_ron()
                .map_err(|e| anyhow::anyhow!("the trust policy: {e}"))?,
        )
        .with_context(|| format!("write {}", p.display()))?;
        println!(
            "TRUST POLICY {} (the pinned release trust identities)",
            p.display()
        );
    }
    Ok(())
}

#[cfg(not(feature = "export-push"))]
fn make(
    _: &[u8],
    _: &std::path::Path,
    _: &std::path::Path,
    _: u64,
    _: i64,
    _: Option<PathBuf>,
) -> Result<()> {
    anyhow::bail!("this build signs no trust root (the release build's, with `export-push`, does)")
}