use std::path::Path;
use std::process::{Command, Stdio};
use anyhow::{Context, Result};
fn cosign_bin() -> String {
std::env::var("MNEMO_COSIGN_BIN").unwrap_or_else(|_| "cosign".to_string())
}
pub fn expected_identity() -> String {
std::env::var("MNEMO_SIGN_IDENTITY").unwrap_or_else(|_| {
"https://github.com/Vesperis-group/mnemo/.github/workflows/release.yml@refs/heads/main"
.to_string()
})
}
pub fn expected_oidc_issuer() -> String {
std::env::var("MNEMO_SIGN_OIDC_ISSUER")
.unwrap_or_else(|_| "https://token.actions.githubusercontent.com".to_string())
}
pub fn signature_asset_name(asset_name: &str) -> String {
format!("{asset_name}.sigstore.json")
}
pub fn cosign_available() -> bool {
Command::new(cosign_bin())
.arg("version")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.map(|s| s.success())
.unwrap_or(false)
}
pub fn verify_sigstore_bundle(asset: &Path, bundle: &Path) -> Result<()> {
let status = Command::new(cosign_bin())
.arg("verify-blob")
.arg("--bundle")
.arg(bundle)
.arg("--certificate-identity")
.arg(expected_identity())
.arg("--certificate-oidc-issuer")
.arg(expected_oidc_issuer())
.arg(asset)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.context("exécution de `cosign verify-blob` impossible")?;
if !status.success() {
anyhow::bail!("`cosign verify-blob` a échoué (signature invalide ou non conforme)");
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn nom_bundle_signature_construit() {
assert_eq!(
signature_asset_name("mnemo-v0.8.0-x86_64-unknown-linux-musl.tar.gz"),
"mnemo-v0.8.0-x86_64-unknown-linux-musl.tar.gz.sigstore.json"
);
assert_eq!(
signature_asset_name("mnemo-v0.8.0-aarch64-unknown-linux-musl.tar.gz"),
"mnemo-v0.8.0-aarch64-unknown-linux-musl.tar.gz.sigstore.json"
);
}
#[test]
fn identite_et_issuer_par_defaut() {
std::env::remove_var("MNEMO_SIGN_IDENTITY");
std::env::remove_var("MNEMO_SIGN_OIDC_ISSUER");
assert_eq!(
expected_identity(),
"https://github.com/Vesperis-group/mnemo/.github/workflows/release.yml@refs/heads/main"
);
assert_eq!(
expected_oidc_issuer(),
"https://token.actions.githubusercontent.com"
);
}
#[test]
fn cosign_absent_renvoie_faux() {
std::env::set_var("MNEMO_COSIGN_BIN", "/nonexistent/cosign-mnemo-test");
assert!(!cosign_available());
std::env::remove_var("MNEMO_COSIGN_BIN");
}
}