diff --git a/.github/workflows/rust-compile.yml b/.github/workflows/rust-compile.yml index c139c5511..cab5d4054 100644 --- a/.github/workflows/rust-compile.yml +++ b/.github/workflows/rust-compile.yml @@ -141,6 +141,8 @@ jobs: - name: Run tests if: ${{ !matrix.skip-tests }} + env: + GOOGLE_CLOUD_TEST_KEY_JSON: ${{ secrets.GOOGLE_CLOUD_TEST_KEY_JSON }} run: > cargo nextest run --workspace diff --git a/crates/rattler_networking/src/gcs_middleware.rs b/crates/rattler_networking/src/gcs_middleware.rs index 9cb9649ac..e07083b91 100644 --- a/crates/rattler_networking/src/gcs_middleware.rs +++ b/crates/rattler_networking/src/gcs_middleware.rs @@ -36,20 +36,14 @@ impl Middleware for GCSMiddleware { /// Auth to GCS async fn authenticate_with_google_cloud(mut req: Request) -> MiddlewareResult { - let audience = "https://storage.googleapis.com/"; - let scopes = [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/devstorage.read_only", - ]; - let config = Config::default() - .with_audience(audience) - .with_scopes(&scopes); + let scopes = ["https://www.googleapis.com/auth/devstorage.read_only"]; + + let config = Config::default().with_scopes(&scopes); match DefaultTokenSourceProvider::new(config).await { Ok(provider) => match provider.token_source().token().await { Ok(token) => { - let bearer_auth = format!("Bearer {token}"); - let header_value = reqwest::header::HeaderValue::from_str(&bearer_auth) + let header_value = reqwest::header::HeaderValue::from_str(&token) .map_err(reqwest_middleware::Error::middleware)?; req.headers_mut() .insert(reqwest::header::AUTHORIZATION, header_value); @@ -63,3 +57,47 @@ async fn authenticate_with_google_cloud(mut req: Request) -> MiddlewareResult Err(reqwest_middleware::Error::Middleware(anyhow::Error::new(e))), } } + +#[cfg(test)] +mod tests { + use super::*; + use reqwest::Client; + use tempfile; + + #[tokio::test] + async fn test_gcs_middleware() { + let credentials = match std::env::var("GOOGLE_CLOUD_TEST_KEY_JSON") { + Ok(credentials) if !credentials.is_empty() => credentials, + Err(_) | Ok(_) => { + eprintln!("Skipping test as GOOGLE_CLOUD_TEST_KEY_JSON is not set"); + return; + } + }; + println!("Running GCS Test"); + + // We have to set GOOGLE_APPLICATION_CREDENTIALS to the path of the JSON key file + let key_file = tempfile::NamedTempFile::with_suffix(".json").unwrap(); + std::fs::write(&key_file, credentials).unwrap(); + + let prev_value = std::env::var("GOOGLE_APPLICATION_CREDENTIALS").ok(); + std::env::set_var("GOOGLE_APPLICATION_CREDENTIALS", key_file.path()); + + let client = reqwest_middleware::ClientBuilder::new(Client::new()) + .with(GCSMiddleware) + .build(); + + let url = "gcs://test-channel/noarch/repodata.json"; + let response = client.get(url).send().await.unwrap(); + assert!(response.status().is_success()); + + let url = "gcs://test-channel-nonexist/noarch/repodata.json"; + let response = client.get(url).send().await.unwrap(); + assert!(response.status().is_client_error()); + + if let Some(value) = prev_value { + std::env::set_var("GOOGLE_APPLICATION_CREDENTIALS", value); + } else { + std::env::remove_var("GOOGLE_APPLICATION_CREDENTIALS"); + } + } +}