summaryrefslogtreecommitdiff
path: root/cli/tools/registry/provenance.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/registry/provenance.rs')
-rw-r--r--cli/tools/registry/provenance.rs87
1 files changed, 48 insertions, 39 deletions
diff --git a/cli/tools/registry/provenance.rs b/cli/tools/registry/provenance.rs
index 69926372e..7fa2be381 100644
--- a/cli/tools/registry/provenance.rs
+++ b/cli/tools/registry/provenance.rs
@@ -1,5 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+use crate::http_util::HttpClient;
+
use super::api::OidcTokenResponse;
use super::auth::gha_oidc_token;
use super::auth::is_gha;
@@ -13,7 +15,6 @@ use deno_core::serde_json;
use once_cell::sync::Lazy;
use p256::elliptic_curve;
use p256::pkcs8::AssociatedOid;
-use reqwest::Client;
use ring::rand::SystemRandom;
use ring::signature::EcdsaKeyPair;
use ring::signature::KeyPair;
@@ -291,6 +292,7 @@ pub struct ProvenanceBundle {
}
pub async fn generate_provenance(
+ http_client: &HttpClient,
subject: Subject,
) -> Result<ProvenanceBundle, AnyError> {
if !is_gha() {
@@ -306,19 +308,20 @@ pub async fn generate_provenance(
let slsa = ProvenanceAttestation::new_github_actions(subject);
let attestation = serde_json::to_string(&slsa)?;
- let bundle = attest(&attestation, INTOTO_PAYLOAD_TYPE).await?;
+ let bundle = attest(http_client, &attestation, INTOTO_PAYLOAD_TYPE).await?;
Ok(bundle)
}
pub async fn attest(
+ http_client: &HttpClient,
data: &str,
type_: &str,
) -> Result<ProvenanceBundle, AnyError> {
// DSSE Pre-Auth Encoding (PAE) payload
let pae = pre_auth_encoding(type_, data);
- let signer = FulcioSigner::new()?;
+ let signer = FulcioSigner::new(http_client)?;
let (signature, key_material) = signer.sign(&pae).await?;
let content = SignatureBundle {
@@ -332,7 +335,8 @@ pub async fn attest(
}],
},
};
- let transparency_logs = testify(&content, &key_material.certificate).await?;
+ let transparency_logs =
+ testify(http_client, &content, &key_material.certificate).await?;
// First log entry is the one we're interested in
let (_, log_entry) = transparency_logs.iter().next().unwrap();
@@ -363,13 +367,6 @@ static DEFAULT_FULCIO_URL: Lazy<String> = Lazy::new(|| {
.unwrap_or_else(|_| "https://fulcio.sigstore.dev".to_string())
});
-struct FulcioSigner {
- // The ephemeral key pair used to sign.
- ephemeral_signer: EcdsaKeyPair,
- rng: SystemRandom,
- client: Client,
-}
-
static ALGORITHM: &ring::signature::EcdsaSigningAlgorithm =
&ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING;
@@ -424,8 +421,15 @@ struct SigningCertificateResponse {
signed_certificate_detached_sct: Option<SignedCertificate>,
}
-impl FulcioSigner {
- pub fn new() -> Result<Self, AnyError> {
+struct FulcioSigner<'a> {
+ // The ephemeral key pair used to sign.
+ ephemeral_signer: EcdsaKeyPair,
+ rng: SystemRandom,
+ http_client: &'a HttpClient,
+}
+
+impl<'a> FulcioSigner<'a> {
+ pub fn new(http_client: &'a HttpClient) -> Result<Self, AnyError> {
let rng = SystemRandom::new();
let document = EcdsaKeyPair::generate_pkcs8(ALGORITHM, &rng)?;
let ephemeral_signer =
@@ -434,7 +438,7 @@ impl FulcioSigner {
Ok(Self {
ephemeral_signer,
rng,
- client: Client::new(),
+ http_client,
})
}
@@ -443,7 +447,7 @@ impl FulcioSigner {
data: &[u8],
) -> Result<(ring::signature::Signature, KeyMaterial), AnyError> {
// Request token from GitHub Actions for audience "sigstore"
- let token = gha_request_token("sigstore").await?;
+ let token = self.gha_request_token("sigstore").await?;
// Extract the subject from the token
let subject = extract_jwt_subject(&token)?;
@@ -498,7 +502,12 @@ impl FulcioSigner {
},
};
- let response = self.client.post(url).json(&request_body).send().await?;
+ let response = self
+ .http_client
+ .post(url)
+ .json(&request_body)
+ .send()
+ .await?;
let body: SigningCertificateResponse = response.json().await?;
@@ -508,6 +517,27 @@ impl FulcioSigner {
.ok_or_else(|| anyhow::anyhow!("No certificate chain returned"))?;
Ok(key.chain.certificates)
}
+
+ async fn gha_request_token(&self, aud: &str) -> Result<String, AnyError> {
+ let Ok(req_url) = env::var("ACTIONS_ID_TOKEN_REQUEST_URL") else {
+ bail!("Not running in GitHub Actions");
+ };
+
+ let Some(token) = gha_oidc_token() else {
+ bail!("No OIDC token available");
+ };
+
+ let res = self
+ .http_client
+ .get(&req_url)
+ .bearer_auth(token)
+ .query(&[("audience", aud)])
+ .send()
+ .await?
+ .json::<OidcTokenResponse>()
+ .await?;
+ Ok(res.value)
+ }
}
#[derive(Deserialize)]
@@ -532,27 +562,6 @@ fn extract_jwt_subject(token: &str) -> Result<String, AnyError> {
}
}
-async fn gha_request_token(aud: &str) -> Result<String, AnyError> {
- let Ok(req_url) = env::var("ACTIONS_ID_TOKEN_REQUEST_URL") else {
- bail!("Not running in GitHub Actions");
- };
-
- let Some(token) = gha_oidc_token() else {
- bail!("No OIDC token available");
- };
-
- let client = Client::new();
- let res = client
- .get(&req_url)
- .bearer_auth(token)
- .query(&[("audience", aud)])
- .send()
- .await?
- .json::<OidcTokenResponse>()
- .await?;
- Ok(res.value)
-}
-
static DEFAULT_REKOR_URL: Lazy<String> = Lazy::new(|| {
env::var("REKOR_URL")
.unwrap_or_else(|_| "https://rekor.sigstore.dev".to_string())
@@ -616,6 +625,7 @@ struct ProposedIntotoEntryHash {
// Rekor witness
async fn testify(
+ http_client: &HttpClient,
content: &SignatureBundle,
public_key: &str,
) -> Result<RekorEntry, AnyError> {
@@ -672,9 +682,8 @@ async fn testify(
},
};
- let client = Client::new();
let url = format!("{}/api/v1/log/entries", *DEFAULT_REKOR_URL);
- let res = client
+ let res = http_client
.post(&url)
.json(&proposed_intoto_entry)
.send()