From fe16b8525c59b611c62aa2802768424bb885bdf3 Mon Sep 17 00:00:00 2001 From: nvivot Date: Thu, 18 Jul 2024 09:04:47 +0900 Subject: [PATCH 1/6] feat: use token or identity source for gke metadata server use case --- foundation/auth/src/project.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/foundation/auth/src/project.rs b/foundation/auth/src/project.rs index 150ce645..747dadda 100644 --- a/foundation/auth/src/project.rs +++ b/foundation/auth/src/project.rs @@ -3,6 +3,7 @@ use google_cloud_metadata::on_gce; use crate::credentials::CredentialsFile; use crate::misc::EMPTY; use crate::token_source::authorized_user_token_source::UserAccountTokenSource; +use crate::token_source::compute_identity_source::ComputeIdentitySource; use crate::token_source::compute_token_source::ComputeTokenSource; use crate::token_source::reuse_token_source::ReuseTokenSource; use crate::token_source::service_account_token_source::OAuth2ServiceAccountTokenSource; @@ -84,11 +85,34 @@ pub async fn create_token_source_from_credentials( credentials: &CredentialsFile, config: &Config<'_>, ) -> Result, error::Error> { + println!("create_token_source_from_credentials"); let ts = credentials_from_json_with_params(credentials, config).await?; let token = ts.token().await?; Ok(Box::new(ReuseTokenSource::new(ts, token))) } +/// Creates token source using gke metadata server +pub async fn create_token_source_from_metadata_server(config: &Config<'_>,) -> Result, error::Error> { + println!("create_token_source_from_metadata_server"); + match config.audience { + Some(audience) => { + println!("compute identity source used"); + let ts = ComputeIdentitySource::new(audience)?; + let token = ts.token().await?; + Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) + }, + None => { + if config.scopes.is_none() { + return Err(error::Error::ScopeOrAudienceRequired); + } + println!("compute token source used"); + let ts = ComputeTokenSource::new(&config.scopes_to_string(","))?; + let token = ts.token().await?; + Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) + } + } +} + /// create_token_source_from_project creates the token source. pub async fn create_token_source_from_project( project: &Project, @@ -96,11 +120,7 @@ pub async fn create_token_source_from_project( ) -> Result, error::Error> { match project { Project::FromFile(file) => create_token_source_from_credentials(file, &config).await, - Project::FromMetadataServer(_) => { - let ts = ComputeTokenSource::new(&config.scopes_to_string(","))?; - let token = ts.token().await?; - Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) - } + Project::FromMetadataServer(_) => create_token_source_from_metadata_server(&config).await, } } From bc3c2d9ce19d9ab48b5f1b258f159d533bd108b8 Mon Sep 17 00:00:00 2001 From: nvivot Date: Thu, 18 Jul 2024 11:00:25 +0900 Subject: [PATCH 2/6] chore: doc and cleanup --- foundation/auth/src/project.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/foundation/auth/src/project.rs b/foundation/auth/src/project.rs index 747dadda..160c8d30 100644 --- a/foundation/auth/src/project.rs +++ b/foundation/auth/src/project.rs @@ -85,18 +85,20 @@ pub async fn create_token_source_from_credentials( credentials: &CredentialsFile, config: &Config<'_>, ) -> Result, error::Error> { - println!("create_token_source_from_credentials"); let ts = credentials_from_json_with_params(credentials, config).await?; let token = ts.token().await?; Ok(Box::new(ReuseTokenSource::new(ts, token))) } -/// Creates token source using gke metadata server +/// Creates token source using gke metadata server. +/// +/// Will use the audience if provided, generating an identity token source. +/// Otherwise, will use the scopes if provided, generating an access token source. +/// +/// Returns an error if neither audience nor scopes are provided, or if any technical error occurs. pub async fn create_token_source_from_metadata_server(config: &Config<'_>,) -> Result, error::Error> { - println!("create_token_source_from_metadata_server"); match config.audience { Some(audience) => { - println!("compute identity source used"); let ts = ComputeIdentitySource::new(audience)?; let token = ts.token().await?; Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) @@ -105,7 +107,6 @@ pub async fn create_token_source_from_metadata_server(config: &Config<'_>,) -> R if config.scopes.is_none() { return Err(error::Error::ScopeOrAudienceRequired); } - println!("compute token source used"); let ts = ComputeTokenSource::new(&config.scopes_to_string(","))?; let token = ts.token().await?; Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) From 0f4064c8ab5c8d5bc62b773e773013f90a4e5e68 Mon Sep 17 00:00:00 2001 From: nvivot Date: Wed, 24 Jul 2024 16:03:27 +0900 Subject: [PATCH 3/6] feat: introduce use_id_token configuration --- foundation/auth/src/idtoken.rs | 2 +- foundation/auth/src/project.rs | 49 ++++++++++++++++------------------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/foundation/auth/src/idtoken.rs b/foundation/auth/src/idtoken.rs index 7af70e35..13cfb5dc 100644 --- a/foundation/auth/src/idtoken.rs +++ b/foundation/auth/src/idtoken.rs @@ -68,7 +68,7 @@ pub async fn create_id_token_source( } } -async fn id_token_source_from_credentials( +pub(crate) async fn id_token_source_from_credentials( custom_claims: &HashMap, credentials: &CredentialsFile, audience: &str, diff --git a/foundation/auth/src/project.rs b/foundation/auth/src/project.rs index 160c8d30..edcc4a7f 100644 --- a/foundation/auth/src/project.rs +++ b/foundation/auth/src/project.rs @@ -1,6 +1,7 @@ use google_cloud_metadata::on_gce; use crate::credentials::CredentialsFile; +use crate::idtoken::id_token_source_from_credentials; use crate::misc::EMPTY; use crate::token_source::authorized_user_token_source::UserAccountTokenSource; use crate::token_source::compute_identity_source::ComputeIdentitySource; @@ -21,6 +22,7 @@ pub struct Config<'a> { pub audience: Option<&'a str>, pub scopes: Option<&'a [&'a str]>, pub sub: Option<&'a str>, + pub use_id_token: bool, } impl Config<'_> { @@ -90,38 +92,33 @@ pub async fn create_token_source_from_credentials( Ok(Box::new(ReuseTokenSource::new(ts, token))) } -/// Creates token source using gke metadata server. -/// -/// Will use the audience if provided, generating an identity token source. -/// Otherwise, will use the scopes if provided, generating an access token source. -/// -/// Returns an error if neither audience nor scopes are provided, or if any technical error occurs. -pub async fn create_token_source_from_metadata_server(config: &Config<'_>,) -> Result, error::Error> { - match config.audience { - Some(audience) => { - let ts = ComputeIdentitySource::new(audience)?; - let token = ts.token().await?; - Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) - }, - None => { - if config.scopes.is_none() { - return Err(error::Error::ScopeOrAudienceRequired); - } - let ts = ComputeTokenSource::new(&config.scopes_to_string(","))?; - let token = ts.token().await?; - Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) - } - } -} - /// create_token_source_from_project creates the token source. pub async fn create_token_source_from_project( project: &Project, config: Config<'_>, ) -> Result, error::Error> { match project { - Project::FromFile(file) => create_token_source_from_credentials(file, &config).await, - Project::FromMetadataServer(_) => create_token_source_from_metadata_server(&config).await, + Project::FromFile(file) => { + if config.use_id_token { + id_token_source_from_credentials(&Default::default(), file, config.audience.unwrap_or_default()).await + } else { + create_token_source_from_credentials(file, &config).await + } + } + Project::FromMetadataServer(_) => { + if config.use_id_token { + let ts = ComputeIdentitySource::new(&config.audience.unwrap_or_default())?; + let token = ts.token().await?; + Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) + } else { + if config.scopes.is_none() { + return Err(error::Error::ScopeOrAudienceRequired); + } + let ts = ComputeTokenSource::new(&config.scopes_to_string(","))?; + let token = ts.token().await?; + Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) + } + } } } From 3be8756c1e30f056030582921ff4895ca871d6eb Mon Sep 17 00:00:00 2001 From: nvivot Date: Thu, 25 Jul 2024 10:29:20 +0900 Subject: [PATCH 4/6] chore: update auth setup with defaults for other client types --- artifact-registry/src/client.rs | 1 + bigquery/src/client.rs | 2 ++ bigquery/src/http/bigquery_client.rs | 1 + kms/src/client.rs | 1 + pubsub/src/client.rs | 1 + spanner/src/client.rs | 1 + storage/src/client.rs | 1 + storage/src/http/service_account_client.rs | 1 + storage/src/http/storage_client.rs | 1 + 9 files changed, 10 insertions(+) diff --git a/artifact-registry/src/client.rs b/artifact-registry/src/client.rs index cad55b7f..3e6c8835 100644 --- a/artifact-registry/src/client.rs +++ b/artifact-registry/src/client.rs @@ -49,6 +49,7 @@ impl ClientConfig { audience: None, scopes: Some(&SCOPES), sub: None, + ..Default::default() } } } diff --git a/bigquery/src/client.rs b/bigquery/src/client.rs index 7dd15481..4ad581d5 100644 --- a/bigquery/src/client.rs +++ b/bigquery/src/client.rs @@ -132,6 +132,7 @@ impl ClientConfig { audience: None, scopes: Some(&crate::http::bigquery_client::SCOPES), sub: None, + ..Default::default() } } @@ -140,6 +141,7 @@ impl ClientConfig { audience: Some(crate::grpc::apiv1::conn_pool::AUDIENCE), scopes: Some(&crate::grpc::apiv1::conn_pool::SCOPES), sub: None, + ..Default::default() } } } diff --git a/bigquery/src/http/bigquery_client.rs b/bigquery/src/http/bigquery_client.rs index 821b0995..b481be25 100644 --- a/bigquery/src/http/bigquery_client.rs +++ b/bigquery/src/http/bigquery_client.rs @@ -135,6 +135,7 @@ pub(crate) mod test { audience: None, scopes: Some(&SCOPES), sub: None, + ..Default::default() }) .await .unwrap(); diff --git a/kms/src/client.rs b/kms/src/client.rs index aa6c0444..96b83df7 100644 --- a/kms/src/client.rs +++ b/kms/src/client.rs @@ -47,6 +47,7 @@ impl ClientConfig { audience: None, scopes: Some(&SCOPES), sub: None, + ..Default::default() } } } diff --git a/pubsub/src/client.rs b/pubsub/src/client.rs index c0cace61..11241266 100644 --- a/pubsub/src/client.rs +++ b/pubsub/src/client.rs @@ -81,6 +81,7 @@ impl ClientConfig { audience: Some(crate::apiv1::conn_pool::AUDIENCE), scopes: Some(&crate::apiv1::conn_pool::SCOPES), sub: None, + ..Default::default() } } } diff --git a/spanner/src/client.rs b/spanner/src/client.rs index 49227a0b..f3da2c87 100644 --- a/spanner/src/client.rs +++ b/spanner/src/client.rs @@ -128,6 +128,7 @@ impl ClientConfig { audience: Some(crate::apiv1::conn_pool::AUDIENCE), scopes: Some(&crate::apiv1::conn_pool::SCOPES), sub: None, + ..Default::default() } } } diff --git a/storage/src/client.rs b/storage/src/client.rs index 28e05c1c..4e41e164 100644 --- a/storage/src/client.rs +++ b/storage/src/client.rs @@ -118,6 +118,7 @@ impl ClientConfig { audience: None, scopes: Some(&crate::http::storage_client::SCOPES), sub: None, + ..Default::default() } } } diff --git a/storage/src/http/service_account_client.rs b/storage/src/http/service_account_client.rs index 1d094cd9..8dd3dc12 100644 --- a/storage/src/http/service_account_client.rs +++ b/storage/src/http/service_account_client.rs @@ -77,6 +77,7 @@ mod test { audience: None, scopes: Some(&["https://www.googleapis.com/auth/cloud-platform"]), sub: None, + ..Default::default() }) .await .unwrap(); diff --git a/storage/src/http/storage_client.rs b/storage/src/http/storage_client.rs index 939f08f9..81c5a20d 100644 --- a/storage/src/http/storage_client.rs +++ b/storage/src/http/storage_client.rs @@ -1421,6 +1421,7 @@ pub(crate) mod test { audience: None, scopes: Some(&SCOPES), sub: None, + ..Default::default() }) .await .unwrap(); From 3cf4a362d4ce394dabf89738b71e39447d1d44d6 Mon Sep 17 00:00:00 2001 From: nvivot Date: Thu, 25 Jul 2024 10:31:33 +0900 Subject: [PATCH 5/6] chore: fix tests --- spanner/tests/change_stream_test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/spanner/tests/change_stream_test.rs b/spanner/tests/change_stream_test.rs index c2722088..7c8cc639 100644 --- a/spanner/tests/change_stream_test.rs +++ b/spanner/tests/change_stream_test.rs @@ -114,6 +114,7 @@ async fn create_environment() -> Environment { audience: Some(google_cloud_spanner::apiv1::conn_pool::AUDIENCE), scopes: Some(&google_cloud_spanner::apiv1::conn_pool::SCOPES), sub: None, + ..Default::default() }) .await .unwrap(); From 322445d15c5c3036af141801ce53022d7305c4e9 Mon Sep 17 00:00:00 2001 From: nvivot Date: Fri, 26 Jul 2024 09:28:38 +0900 Subject: [PATCH 6/6] chore: clippy and small refactoring --- foundation/auth/src/project.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/foundation/auth/src/project.rs b/foundation/auth/src/project.rs index edcc4a7f..6ec9240e 100644 --- a/foundation/auth/src/project.rs +++ b/foundation/auth/src/project.rs @@ -107,14 +107,14 @@ pub async fn create_token_source_from_project( } Project::FromMetadataServer(_) => { if config.use_id_token { - let ts = ComputeIdentitySource::new(&config.audience.unwrap_or_default())?; + let ts = ComputeIdentitySource::new(config.audience.unwrap_or_default())?; let token = ts.token().await?; Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) } else { if config.scopes.is_none() { return Err(error::Error::ScopeOrAudienceRequired); } - let ts = ComputeTokenSource::new(&config.scopes_to_string(","))?; + let ts = ComputeTokenSource::new(config.scopes_to_string(",").as_str())?; let token = ts.token().await?; Ok(Box::new(ReuseTokenSource::new(Box::new(ts), token))) }