From 5f009c1111a377e6a62e888b27cca5aae5d2076a Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 00:01:15 +0900 Subject: [PATCH 01/10] feat(core): add aws external account token retrieval --- gcloud-sdk/Cargo.toml | 6 +- gcloud-sdk/src/error.rs | 2 +- .../src/token_source/ext_creds_source/mod.rs | 224 +++++++++++++++++- 3 files changed, 228 insertions(+), 4 deletions(-) diff --git a/gcloud-sdk/Cargo.toml b/gcloud-sdk/Cargo.toml index 1cd112685..16875b334 100644 --- a/gcloud-sdk/Cargo.toml +++ b/gcloud-sdk/Cargo.toml @@ -20,6 +20,7 @@ default = ["tls-roots"] tls-roots = ["tonic/tls-roots", "reqwest/rustls-tls-native-roots"] tls-webpki-roots = ["tonic/tls-webpki-roots", "reqwest/rustls-tls-webpki-roots"] rest = ["serde_with"] +external-account-aws = ["aws-config", "aws-sigv4", "aws-credential-types", "percent-encoding"] # Google API features ccc-hosted-marketplace-v2 = [] @@ -451,7 +452,10 @@ once_cell = "1.19" reqwest = { version=">=0.12.7", features=["multipart", "json", "gzip", "stream"], default-features = false } bytes = { version = "1"} serde_with = { version = "3", optional = true } - +aws-config = { version = "1.1", features = ["behavior-version-latest"], optional = true } +aws-sigv4 = { version = "1.2" , optional = true } +aws-credential-types = { version = "1.2.1", optional = true } +percent-encoding = { version = "2.3", optional = true } [dev-dependencies] cargo-audit = "0.21" diff --git a/gcloud-sdk/src/error.rs b/gcloud-sdk/src/error.rs index 713033555..809b39233 100644 --- a/gcloud-sdk/src/error.rs +++ b/gcloud-sdk/src/error.rs @@ -18,7 +18,7 @@ pub enum ErrorKind { CredentialsJson(serde_json::Error), /// An error reading credentials file. CredentialsFile(std::io::Error), - /// An error parsing data from token response. + /// An error from json serialization and deserialization. TokenJson(serde_json::Error), /// Invalid token error. TokenData, diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 341426876..7c438174e 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -9,7 +9,8 @@ use tracing::*; pub enum ExternalCredentialSource { UrlBased(ExternalCredentialUrl), FileBased(ExternalCredentialFile), - // AWS external source implementation example https://github.com/googleapis/google-auth-library-nodejs/blob/4bbd13fbf9081e004209d0ffc336648cff0c529e/src/auth/awsclient.ts + #[cfg(feature = "external-account-aws")] + Aws(Aws), } #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] @@ -25,6 +26,26 @@ pub struct ExternalCredentialFile { format: Option, } +/// https://google.aip.dev/auth/4117#determining-the-subject-token-in-aws +#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct Aws { + /// This defines the regional AWS GetCallerIdentity action URL. This URL should be used + /// to determine the AWS account ID and its roles. + pub regional_cred_verification_url: String, + /// This is the environment identifier, of format `aws{version}`. + pub environment_id: String, + /// This URL should be used to determine the current AWS region needed for the signed + /// request construction when the region environment variables are not present. + pub region_url: Option, + /// This AWS metadata server URL should be used to retrieve the access key, secret key + /// and security token needed to sign the GetCallerIdentity request. + pub url: Option, + /// Presence of this URL enforces the auth libraries to fetch a Session Token from AWS. + /// This field is required for EC2 instances using IMDSv2. This Session Token would + /// later be used while making calls to the metadata endpoint. + pub imdsv2_session_token_url: Option, +} + #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[serde(tag = "type")] #[serde(rename_all = "camelCase")] @@ -42,11 +63,26 @@ pub async fn subject_token( client: &reqwest::Client, external_account: &ExternalAccount, ) -> crate::error::Result { - match external_account.credential_source { + match &external_account.credential_source { ExternalCredentialSource::UrlBased(ref url_creds) => { subject_token_url(client, url_creds).await } ExternalCredentialSource::FileBased(ref url_creds) => subject_token_file(url_creds).await, + #[cfg(feature = "external-account-aws")] + ExternalCredentialSource::Aws(Aws { + regional_cred_verification_url, + .. + }) => { + let (credentials, region) = aws::get_aws_props().await?; + aws::subject_token_aws( + regional_cred_verification_url.as_str(), + credentials, + region, + std::time::SystemTime::now(), + &external_account.audience, + ) + .await + } } } @@ -139,3 +175,187 @@ fn subject_token_from_json( .into() }) } + +#[cfg(feature = "external-account-aws")] +mod aws { + use crate::error::Error; + use crate::error::ErrorKind; + use aws_config::Region; + use aws_credential_types::provider::ProvideCredentials; + use aws_credential_types::Credentials; + use aws_sigv4::http_request::{ + SignableBody, SignatureLocation, SigningParams, SigningSettings, + }; + use aws_sigv4::sign::v4::SigningParams as V4SigningParams; + use hyper::http::{Method, Request}; + use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; + use secret_vault_value::SecretValue; + use serde::Serialize; + use std::time::SystemTime; + + pub async fn subject_token_aws( + regional_cred_verification_url: &str, + credentials: Credentials, + region: Region, + sign_at: SystemTime, + audience: &str, + ) -> crate::error::Result { + let identity = credentials.into(); + let signature_time = sign_at; + + let mut signing_settings = SigningSettings::default(); + signing_settings.signature_location = SignatureLocation::Headers; + let v4_signing_params = V4SigningParams::builder() + .name("sts") + .identity(&identity) + .region(region.as_ref()) + .time(signature_time) + .settings(signing_settings) + .build() + .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))?; + let params = SigningParams::V4(v4_signing_params); + + let regional_cred_verification_url = + regional_cred_verification_url.replace("{region}", region.as_ref()); + let subject_token_url = regional_cred_verification_url; + let url = url::Url::parse(&subject_token_url).unwrap(); + let method = Method::POST; + let mut headers = vec![("x-goog-cloud-target-resource", audience)]; + if let Some(host) = url.host_str() { + headers.push(("Host", host)) + } + let mut req = Request::builder().uri(url.to_string()).method(&method); + for header in &headers { + req = req.header(header.0, header.1); + } + let mut request = req.body(()).unwrap(); + + let signable_request = aws_sigv4::http_request::SignableRequest::new( + "POST", + &subject_token_url, + headers.into_iter(), + SignableBody::empty(), + ) + .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))?; + let (instruction, _) = aws_sigv4::http_request::sign(signable_request, ¶ms) + .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))? + .into_parts(); + instruction.apply_to_request_http1x(&mut request); + let payload = AWSRequest { + url: subject_token_url.to_string(), + method: method.to_string(), + headers: request + .headers() + .into_iter() + .flat_map(|(k, v)| { + v.to_str() + .ok() + .map(|v| AWSRequestHeader::new(k.to_string(), v.to_string())) + }) + .collect(), + }; + let payload = + serde_json::to_string(&payload).map_err(|e| Error::from(ErrorKind::TokenJson(e)))?; + let sts_token = utf8_percent_encode(&payload, NON_ALPHANUMERIC).to_string(); + + Ok(sts_token.into()) + } + + pub async fn get_aws_props() -> crate::error::Result<(Credentials, Region)> { + let imds_client = aws_config::imds::Client::builder().build(); + let imds_credentials_provider = + aws_config::imds::credentials::ImdsCredentialsProvider::builder() + .imds_client(imds_client.clone()) + .build(); + let imds_region_provider = aws_config::imds::region::Builder::default() + .imds_client(imds_client) + .build(); + + let config = aws_config::load_from_env().await; + let region = match config.region() { + Some(region) => Some(region.to_owned()), + None => imds_region_provider.region().await, + } + .ok_or_else(|| { + Error::from(ErrorKind::ExternalCredsSourceError( + "region not found".to_string(), + )) + })?; + let provide_credentials = { + match config.credentials_provider() { + Some(provider) => provider.provide_credentials().await, + None => imds_credentials_provider.provide_credentials().await, + } + }; + let credentials: Credentials = provide_credentials + .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))? + .into(); + Ok((credentials, region)) + } + + #[derive(Debug, Serialize)] + struct AWSRequest { + url: String, + method: String, + headers: Vec, + } + + #[derive(Debug, Serialize, Clone)] + struct AWSRequestHeader { + key: String, + value: String, + } + + impl AWSRequestHeader { + pub fn new(key: impl Into, value: impl Into) -> Self { + Self { + key: key.into(), + value: value.into(), + } + } + } + + #[cfg(test)] + mod tests { + use std::time::SystemTime; + + use aws_config::Region; + use aws_credential_types::Credentials; + use chrono::NaiveDateTime; + + use super::subject_token_aws; + #[tokio::test] + async fn sanity_check_subject_token() { + // This test uses the following implementation for reference + // https://github.com/yoshidan/google-cloud-rust/blob/8d09d6156dfb29965cd20539375896f16b3f739d/foundation/auth/src/token_source/external_account_source/aws_subject_token_source.rs#L381 + let credentials = Credentials::new( + "AccessKeyId", + "SecretAccessKey", + Some("SecurityToken".to_string()), + None, + "test", + ); + let sign_at: SystemTime = + NaiveDateTime::parse_from_str("2022-12-31 00:00:00", "%Y-%m-%d %H:%M:%S") + .unwrap() + .and_utc() + .into(); + let region = Region::from_static("ap-northeast-1b"); + let audience = "//iam.googleapis.com/projects/myprojectnumber/locations/global/workloadIdentityPools/aws-test/providers/aws-test"; + let regional_cred_verification_url = + "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15"; + let result = subject_token_aws( + regional_cred_verification_url, + credentials, + region.clone(), + sign_at, + audience, + ) + .await; + assert_eq!( + result.unwrap().sensitive_value_to_str().unwrap(), + "%7B%22url%22%3A%22https%3A%2F%2Fsts%2Eap%2Dnortheast%2D1b%2Eamazonaws%2Ecom%3FAction%3DGetCallerIdentity%26Version%3D2011%2D06%2D15%22%2C%22method%22%3A%22POST%22%2C%22headers%22%3A%5B%7B%22key%22%3A%22x%2Dgoog%2Dcloud%2Dtarget%2Dresource%22%2C%22value%22%3A%22%2F%2Fiam%2Egoogleapis%2Ecom%2Fprojects%2Fmyprojectnumber%2Flocations%2Fglobal%2FworkloadIdentityPools%2Faws%2Dtest%2Fproviders%2Faws%2Dtest%22%7D%2C%7B%22key%22%3A%22host%22%2C%22value%22%3A%22sts%2Eap%2Dnortheast%2D1b%2Eamazonaws%2Ecom%22%7D%2C%7B%22key%22%3A%22x%2Damz%2Ddate%22%2C%22value%22%3A%2220221231T000000Z%22%7D%2C%7B%22key%22%3A%22authorization%22%2C%22value%22%3A%22AWS4%2DHMAC%2DSHA256%20Credential%3DAccessKeyId%2F20221231%2Fap%2Dnortheast%2D1b%2Fsts%2Faws4%5Frequest%2C%20SignedHeaders%3Dhost%3Bx%2Damz%2Ddate%3Bx%2Damz%2Dsecurity%2Dtoken%3Bx%2Dgoog%2Dcloud%2Dtarget%2Dresource%2C%20Signature%3D168a40df8b7c11fb0588a13cada1443e31e4736de702232f9a2177b26edda21c%22%7D%2C%7B%22key%22%3A%22x%2Damz%2Dsecurity%2Dtoken%22%2C%22value%22%3A%22SecurityToken%22%7D%5D%7D" + ); + } + } +} From 81c65ca81f3ba42d0d4777a16456d4ea5f8fb180 Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 00:19:02 +0900 Subject: [PATCH 02/10] tidy: use simpler API --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 7c438174e..9dd87aea5 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -181,6 +181,8 @@ mod aws { use crate::error::Error; use crate::error::ErrorKind; use aws_config::Region; + use aws_config::imds::credentials::ImdsCredentialsProvider; + use aws_config::imds::region::ImdsRegionProvider; use aws_credential_types::provider::ProvideCredentials; use aws_credential_types::Credentials; use aws_sigv4::http_request::{ @@ -262,14 +264,8 @@ mod aws { } pub async fn get_aws_props() -> crate::error::Result<(Credentials, Region)> { - let imds_client = aws_config::imds::Client::builder().build(); - let imds_credentials_provider = - aws_config::imds::credentials::ImdsCredentialsProvider::builder() - .imds_client(imds_client.clone()) - .build(); - let imds_region_provider = aws_config::imds::region::Builder::default() - .imds_client(imds_client) - .build(); + let imds_region_provider = ImdsRegionProvider::builder().build(); + let imds_credentials_provider = ImdsCredentialsProvider::builder().build(); let config = aws_config::load_from_env().await; let region = match config.region() { From c74bf6d8dcd053f8d8b42aff05d900e0243db131 Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 00:28:16 +0900 Subject: [PATCH 03/10] improve: use imds as a fallback --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 9dd87aea5..051bf0c03 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -180,9 +180,9 @@ fn subject_token_from_json( mod aws { use crate::error::Error; use crate::error::ErrorKind; - use aws_config::Region; use aws_config::imds::credentials::ImdsCredentialsProvider; use aws_config::imds::region::ImdsRegionProvider; + use aws_config::Region; use aws_credential_types::provider::ProvideCredentials; use aws_credential_types::Credentials; use aws_sigv4::http_request::{ @@ -279,7 +279,10 @@ mod aws { })?; let provide_credentials = { match config.credentials_provider() { - Some(provider) => provider.provide_credentials().await, + Some(provider) => provider + .provide_credentials() + .await + .or(imds_credentials_provider.provide_credentials().await), None => imds_credentials_provider.provide_credentials().await, } }; From 954f60aa56ee4fec9648abd1f06e24a09a4fd22d Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 00:49:29 +0900 Subject: [PATCH 04/10] chore: colocate to use-site --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 051bf0c03..4ff2684dc 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -265,7 +265,6 @@ mod aws { pub async fn get_aws_props() -> crate::error::Result<(Credentials, Region)> { let imds_region_provider = ImdsRegionProvider::builder().build(); - let imds_credentials_provider = ImdsCredentialsProvider::builder().build(); let config = aws_config::load_from_env().await; let region = match config.region() { @@ -277,6 +276,7 @@ mod aws { "region not found".to_string(), )) })?; + let imds_credentials_provider = ImdsCredentialsProvider::builder().build(); let provide_credentials = { match config.credentials_provider() { Some(provider) => provider From 24a6c069005a9cf99ef821800f410915c92653b7 Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 00:53:06 +0900 Subject: [PATCH 05/10] chore: use the same value --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 4ff2684dc..a614bf6b9 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -233,7 +233,7 @@ mod aws { let mut request = req.body(()).unwrap(); let signable_request = aws_sigv4::http_request::SignableRequest::new( - "POST", + method.as_str(), &subject_token_url, headers.into_iter(), SignableBody::empty(), From 5857ddeb8f40bee2f55906fb97567ac14e5b9db9 Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 01:43:17 +0900 Subject: [PATCH 06/10] improve: validate environment id --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index a614bf6b9..5d3f21dec 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -71,8 +71,16 @@ pub async fn subject_token( #[cfg(feature = "external-account-aws")] ExternalCredentialSource::Aws(Aws { regional_cred_verification_url, + environment_id, .. }) => { + if environment_id.starts_with("aws") { + if environment_id != "aws1" { + return Err(crate::error::ErrorKind::ExternalCredsSourceError( + "unsupported aws version".to_string(), + ).into()); + } + }; let (credentials, region) = aws::get_aws_props().await?; aws::subject_token_aws( regional_cred_verification_url.as_str(), From 068900959ca11042cab906b138edc3082f335766 Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 02:07:25 +0900 Subject: [PATCH 07/10] improve: use default credentials provider chain default credentials chain includes all the common credential sources. --- .../src/token_source/ext_creds_source/mod.rs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 5d3f21dec..7a37b7436 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -78,7 +78,8 @@ pub async fn subject_token( if environment_id != "aws1" { return Err(crate::error::ErrorKind::ExternalCredsSourceError( "unsupported aws version".to_string(), - ).into()); + ) + .into()); } }; let (credentials, region) = aws::get_aws_props().await?; @@ -284,17 +285,13 @@ mod aws { "region not found".to_string(), )) })?; - let imds_credentials_provider = ImdsCredentialsProvider::builder().build(); - let provide_credentials = { - match config.credentials_provider() { - Some(provider) => provider - .provide_credentials() - .await - .or(imds_credentials_provider.provide_credentials().await), - None => imds_credentials_provider.provide_credentials().await, - } - }; - let credentials: Credentials = provide_credentials + let credentials_provider = + aws_config::default_provider::credentials::DefaultCredentialsChain::builder() + .build() + .await; + let credentials: Credentials = credentials_provider + .provide_credentials() + .await .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))? .into(); Ok((credentials, region)) From 063563a56af5443b0bf7cc85f7df8336f22684e7 Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 02:25:38 +0900 Subject: [PATCH 08/10] fix: region should be obtained from default as well --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 7a37b7436..43cfe61df 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -189,8 +189,6 @@ fn subject_token_from_json( mod aws { use crate::error::Error; use crate::error::ErrorKind; - use aws_config::imds::credentials::ImdsCredentialsProvider; - use aws_config::imds::region::ImdsRegionProvider; use aws_config::Region; use aws_credential_types::provider::ProvideCredentials; use aws_credential_types::Credentials; @@ -273,7 +271,8 @@ mod aws { } pub async fn get_aws_props() -> crate::error::Result<(Credentials, Region)> { - let imds_region_provider = ImdsRegionProvider::builder().build(); + let imds_region_provider = + aws_config::default_provider::region::DefaultRegionChain::builder().build(); let config = aws_config::load_from_env().await; let region = match config.region() { From cd5dbecd76e8ab52130bba5264818ffb7db60d5a Mon Sep 17 00:00:00 2001 From: i10416 Date: Thu, 28 Nov 2024 02:30:39 +0900 Subject: [PATCH 09/10] tidy: simplify aws props lookup --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index 43cfe61df..aef8d0af3 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -271,15 +271,9 @@ mod aws { } pub async fn get_aws_props() -> crate::error::Result<(Credentials, Region)> { - let imds_region_provider = + let region_provider = aws_config::default_provider::region::DefaultRegionChain::builder().build(); - - let config = aws_config::load_from_env().await; - let region = match config.region() { - Some(region) => Some(region.to_owned()), - None => imds_region_provider.region().await, - } - .ok_or_else(|| { + let region = region_provider.region().await.ok_or_else(|| { Error::from(ErrorKind::ExternalCredsSourceError( "region not found".to_string(), )) From fa3979a8d1a376dd85968330d48e7580eb547d81 Mon Sep 17 00:00:00 2001 From: i10416 Date: Tue, 3 Dec 2024 01:37:41 +0900 Subject: [PATCH 10/10] tidy: address code review --- gcloud-sdk/src/token_source/ext_creds_source/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs index aef8d0af3..3f89f29d8 100644 --- a/gcloud-sdk/src/token_source/ext_creds_source/mod.rs +++ b/gcloud-sdk/src/token_source/ext_creds_source/mod.rs @@ -227,7 +227,8 @@ mod aws { let regional_cred_verification_url = regional_cred_verification_url.replace("{region}", region.as_ref()); let subject_token_url = regional_cred_verification_url; - let url = url::Url::parse(&subject_token_url).unwrap(); + let url = url::Url::parse(&subject_token_url) + .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))?; let method = Method::POST; let mut headers = vec![("x-goog-cloud-target-resource", audience)]; if let Some(host) = url.host_str() { @@ -237,7 +238,9 @@ mod aws { for header in &headers { req = req.header(header.0, header.1); } - let mut request = req.body(()).unwrap(); + let mut request = req + .body(()) + .map_err(|e| Error::from(ErrorKind::ExternalCredsSourceError(e.to_string())))?; let signable_request = aws_sigv4::http_request::SignableRequest::new( method.as_str(),