sigstore_verification/verifiers/
github.rs1use crate::Result;
2use crate::bundle::ParsedBundle;
3use crate::verifiers::{Policy, VerificationResult, Verifier};
4use async_trait::async_trait;
5use log::debug;
6use std::path::Path;
7
8pub struct GitHubVerifier {
11 pub repository: Option<String>,
13 pub workflow: Option<String>,
15}
16
17impl GitHubVerifier {
18 pub fn new() -> Self {
19 Self {
20 repository: None,
21 workflow: None,
22 }
23 }
24
25 pub fn with_repository(mut self, repo: impl Into<String>) -> Self {
26 self.repository = Some(repo.into());
27 self
28 }
29
30 pub fn with_workflow(mut self, workflow: impl Into<String>) -> Self {
31 self.workflow = Some(workflow.into());
32 self
33 }
34}
35
36impl Default for GitHubVerifier {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42#[async_trait]
43impl Verifier for GitHubVerifier {
44 async fn verify(
45 &self,
46 bundle: &ParsedBundle,
47 artifact_path: &Path,
48 policy: &Policy,
49 ) -> Result<VerificationResult> {
50 debug!(
51 "Starting GitHub attestation verification for {:?}",
52 artifact_path
53 );
54
55 let expected_workflow = policy
57 .signer_workflow
58 .as_deref()
59 .or(self.workflow.as_deref());
60
61 let attestations = vec![crate::api::Attestation {
63 bundle: Some(serde_json::from_slice(&bundle.payload)?),
64 bundle_url: None,
65 }];
66
67 crate::verify::verify_attestations(&attestations, artifact_path, expected_workflow).await?;
68
69 let cert_info = if let Some(cert) = &bundle.certificate {
71 Some(crate::verify::verify_certificate(cert)?)
72 } else {
73 None
74 };
75
76 Ok(VerificationResult {
77 success: true,
78 slsa_level: Some(3), certificate_identity: cert_info.as_ref().and_then(|ci| ci.repository.clone()),
80 builder_identity: cert_info.as_ref().and_then(|ci| ci.workflow_ref.clone()),
81 messages: vec![
82 "GitHub attestation verification successful".to_string(),
83 format!("Workflow: {}", expected_workflow.unwrap_or("any")),
84 ],
85 })
86 }
87
88 fn verifier_type(&self) -> &'static str {
89 "GitHub"
90 }
91}