greentic_dev/
pack_verify.rs1use std::path::Path;
2
3use anyhow::Result;
4use greentic_pack::reader::{PackVerifyResult, SigningPolicy, open_pack};
5use serde_json::json;
6
7#[derive(Debug, Clone, Copy)]
8pub enum VerifyPolicy {
9 Strict,
10 DevOk,
11}
12
13impl From<VerifyPolicy> for SigningPolicy {
14 fn from(policy: VerifyPolicy) -> Self {
15 match policy {
16 VerifyPolicy::Strict => SigningPolicy::Strict,
17 VerifyPolicy::DevOk => SigningPolicy::DevOk,
18 }
19 }
20}
21
22pub fn run(pack_path: &Path, policy: VerifyPolicy, emit_json: bool) -> Result<()> {
23 let load = open_pack(pack_path, policy.into()).map_err(|err: PackVerifyResult| {
24 anyhow::anyhow!("pack verification failed: {}", err.message)
25 })?;
26
27 if emit_json {
28 let doc = json!({
29 "manifest": load.manifest,
30 "report": {
31 "signature_ok": load.report.signature_ok,
32 "sbom_ok": load.report.sbom_ok,
33 "warnings": load.report.warnings,
34 },
35 "sbom": load.sbom,
36 });
37 println!("{}", serde_json::to_string_pretty(&doc)?);
38 } else {
39 println!("✓ Pack verified: {}", pack_path.display());
40 if !load.report.warnings.is_empty() {
41 println!("Warnings:");
42 for warning in &load.report.warnings {
43 println!("- {warning}");
44 }
45 }
46 }
47
48 Ok(())
49}
50
51#[cfg(test)]
52mod tests {
53 use super::{VerifyPolicy, run};
54 use crate::pack_build::{self, PackSigning};
55
56 #[test]
57 fn verify_can_emit_json_report() {
58 let root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
59 let flow_path = root.join("tests/fixtures/hello-pack/hello-flow.ygtc");
60 let component_dir = root.join("fixtures/components");
61
62 let temp = tempfile::tempdir().unwrap();
63 let pack_path = temp.path().join("verify-json.gtpack");
64 pack_build::run(
65 &flow_path,
66 &pack_path,
67 PackSigning::Dev,
68 None,
69 Some(component_dir.as_path()),
70 )
71 .unwrap();
72
73 run(&pack_path, VerifyPolicy::DevOk, true).unwrap();
74 }
75}