From 5a0765c6779ef0601dbc118f66f44cc97e27fc48 Mon Sep 17 00:00:00 2001 From: Gagan Yarramsetty Date: Fri, 22 May 2026 22:29:35 +0530 Subject: [PATCH 1/2] fix: load IRSA web identity config for S3 --- src/storage/s3.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/storage/s3.rs b/src/storage/s3.rs index b66bd5a6e..dc956f34c 100644 --- a/src/storage/s3.rs +++ b/src/storage/s3.rs @@ -69,6 +69,9 @@ use super::{ // in bytes // const MULTIPART_UPLOAD_SIZE: usize = 1024 * 1024 * 100; const AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: &str = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; +const AWS_WEB_IDENTITY_TOKEN_FILE: &str = "AWS_WEB_IDENTITY_TOKEN_FILE"; +const AWS_ROLE_ARN: &str = "AWS_ROLE_ARN"; +const AWS_ROLE_SESSION_NAME: &str = "AWS_ROLE_SESSION_NAME"; #[derive(Debug, Clone, clap::Args)] #[command( @@ -269,6 +272,20 @@ impl S3Config { .with_secret_access_key(secret_key); } + if self.access_key_id.is_none() && self.secret_key.is_none() { + if let Ok(token_file) = std::env::var(AWS_WEB_IDENTITY_TOKEN_FILE) { + builder = builder.with_config(AmazonS3ConfigKey::WebIdentityTokenFile, token_file); + } + + if let Ok(role_arn) = std::env::var(AWS_ROLE_ARN) { + builder = builder.with_config(AmazonS3ConfigKey::RoleArn, role_arn); + } + + if let Ok(session_name) = std::env::var(AWS_ROLE_SESSION_NAME) { + builder = builder.with_config(AmazonS3ConfigKey::RoleSessionName, session_name); + } + } + if let Some(ssec_encryption_key) = &self.ssec_encryption_key { match ssec_encryption_key { SSECEncryptionKey::SseC { From b5c312a48d4ea309040edd34a8097c9f35120c23 Mon Sep 17 00:00:00 2001 From: Gagan Yarramsetty Date: Fri, 22 May 2026 23:29:40 +0530 Subject: [PATCH 2/2] Addressed with a smaller invariant-based implementation. Static S3 credentials and IRSA web identity values are now validated as pairs --- src/storage/s3.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/storage/s3.rs b/src/storage/s3.rs index dc956f34c..589d71b94 100644 --- a/src/storage/s3.rs +++ b/src/storage/s3.rs @@ -264,25 +264,34 @@ impl S3Config { builder = builder.with_checksum_algorithm(Checksum::SHA256) } + assert!( + self.access_key_id.is_some() == self.secret_key.is_some(), + "P_S3_ACCESS_KEY and P_S3_SECRET_KEY must be set together" + ); + if let Some((access_key, secret_key)) = self.access_key_id.as_ref().zip(self.secret_key.as_ref()) { builder = builder .with_access_key_id(access_key) .with_secret_access_key(secret_key); - } + } else { + let token_file = std::env::var(AWS_WEB_IDENTITY_TOKEN_FILE).ok(); + let role_arn = std::env::var(AWS_ROLE_ARN).ok(); - if self.access_key_id.is_none() && self.secret_key.is_none() { - if let Ok(token_file) = std::env::var(AWS_WEB_IDENTITY_TOKEN_FILE) { - builder = builder.with_config(AmazonS3ConfigKey::WebIdentityTokenFile, token_file); - } + assert!( + token_file.is_some() == role_arn.is_some(), + "{AWS_WEB_IDENTITY_TOKEN_FILE} and {AWS_ROLE_ARN} must be set together" + ); - if let Ok(role_arn) = std::env::var(AWS_ROLE_ARN) { - builder = builder.with_config(AmazonS3ConfigKey::RoleArn, role_arn); - } + if let Some((token_file, role_arn)) = token_file.zip(role_arn) { + builder = builder + .with_config(AmazonS3ConfigKey::WebIdentityTokenFile, token_file) + .with_config(AmazonS3ConfigKey::RoleArn, role_arn); - if let Ok(session_name) = std::env::var(AWS_ROLE_SESSION_NAME) { - builder = builder.with_config(AmazonS3ConfigKey::RoleSessionName, session_name); + if let Ok(session_name) = std::env::var(AWS_ROLE_SESSION_NAME) { + builder = builder.with_config(AmazonS3ConfigKey::RoleSessionName, session_name); + } } }