Skip to main content

lean_ctx_patterns/
cosign.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Cosign (sigstore) output compression.
4//!
5//! `cosign verify` prints a human-readable verdict (`Verification for X --`
6//! plus the checks performed) followed by a large JSON signature payload. We
7//! keep the verdict/checks and any error, dropping the trailing JSON blob.
8
9use crate::ansi::strip_ansi;
10
11pub fn compress(_cmd: &str, output: &str) -> Option<String> {
12    let trimmed = output.trim();
13    if trimmed.is_empty() {
14        return Some("cosign: ok".to_string());
15    }
16
17    let mut kept: Vec<String> = Vec::new();
18    for raw in trimmed.lines() {
19        let line = strip_ansi(raw);
20        let line = line.trim();
21        if line.is_empty() {
22            continue;
23        }
24        // The JSON signature payload starts with '[' or '{' — stop there.
25        if line.starts_with('[') || line.starts_with('{') {
26            break;
27        }
28        kept.push(line.to_string());
29    }
30
31    if kept.is_empty() {
32        return Some("cosign: ok".to_string());
33    }
34    Some(kept.join("\n"))
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    const VERIFY: &str = "\nVerification for myimage:latest --\nThe following checks were performed on each of these signatures:\n  - The cosign claims were validated\n  - The signatures were verified against the specified public key\n[{\"critical\":{\"identity\":{\"docker-reference\":\"myimage\"},\"image\":{\"docker-manifest-digest\":\"sha256:deadbeef\"}}}]\n";
42
43    #[test]
44    fn keeps_verdict_drops_json() {
45        let r = compress("cosign verify myimage", VERIFY).unwrap();
46        assert!(r.contains("Verification for myimage:latest"), "{r}");
47        assert!(r.contains("claims were validated"), "{r}");
48        assert!(
49            !r.contains("docker-manifest-digest"),
50            "drops json payload: {r}"
51        );
52        assert!(!r.contains("sha256:deadbeef"), "{r}");
53    }
54
55    #[test]
56    fn keeps_errors() {
57        let out = "Error: no matching signatures:\nfailed to verify signature\n";
58        let r = compress("cosign verify x", out).unwrap();
59        assert!(r.contains("no matching signatures"), "{r}");
60    }
61
62    #[test]
63    fn empty_is_ok() {
64        assert_eq!(compress("cosign verify x", "").unwrap(), "cosign: ok");
65    }
66}