This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch 6560-reqsign-core-v1-s3
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit d6e5da5078feb6ee9dc671955399300be612f9c6
Author: Xuanwo <[email protected]>
AuthorDate: Mon Oct 13 13:13:47 2025 +0800

    Address assume role support
    
    Signed-off-by: Xuanwo <[email protected]>
---
 core/src/services/s3/backend.rs | 47 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/core/src/services/s3/backend.rs b/core/src/services/s3/backend.rs
index d0cb7a695..5c319b2c7 100644
--- a/core/src/services/s3/backend.rs
+++ b/core/src/services/s3/backend.rs
@@ -35,6 +35,7 @@ use log::warn;
 use md5::Digest;
 use md5::Md5;
 use percent_encoding::percent_decode_str;
+use reqsign_aws_v4::AssumeRoleCredentialProvider;
 use reqsign_aws_v4::Credential;
 use reqsign_aws_v4::DefaultCredentialProvider;
 use reqsign_aws_v4::RequestSigner as AwsV4Signer;
@@ -515,6 +516,22 @@ impl S3Builder {
         self
     }
 
+    /// Append a custom credential provider that will be tried before the 
default chain.
+    ///
+    /// Providers are evaluated in the order they are added.
+    pub fn credential_provider(
+        mut self,
+        provider: impl ProvideCredential<Credential = Credential>,
+    ) -> Self {
+        let chain = self
+            .credential_providers
+            .take()
+            .unwrap_or_default()
+            .push(provider);
+        self.credential_providers = Some(chain);
+        self
+    }
+
     /// Replace the credential providers with a custom chain.
     pub fn credential_provider_chain(mut self, chain: 
ProvideCredentialChain<Credential>) -> Self {
         self.credential_providers = Some(chain);
@@ -854,9 +871,7 @@ impl Builder for S3Builder {
             .with_file_read(TokioFileRead)
             
.with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()));
 
-        let mut provider = if let Some(chain) = credential_providers {
-            chain
-        } else {
+        let mut provider = {
             let mut builder = DefaultCredentialProvider::builder();
 
             if config.disable_config_load {
@@ -870,6 +885,7 @@ impl Builder for S3Builder {
             ProvideCredentialChain::new().push(builder.build())
         };
 
+        // Insert static key if user provided.
         if let (Some(ak), Some(sk)) = (&config.access_key_id, 
&config.secret_access_key) {
             let static_provider = if let Some(token) = 
config.session_token.as_deref() {
                 StaticCredentialProvider::new(ak, sk).with_session_token(token)
@@ -879,6 +895,31 @@ impl Builder for S3Builder {
             provider = provider.push_front(static_provider);
         }
 
+        // Insert assume role provider if user provided.
+        if let Some(role_arn) = &config.role_arn {
+            let sts_ctx = ctx.clone();
+            let sts_request_signer = AwsV4Signer::new("sts", &region);
+            let sts_signer = Signer::new(sts_ctx, provider, 
sts_request_signer);
+            let mut assume_role_provider =
+                AssumeRoleCredentialProvider::new(role_arn.clone(), 
sts_signer);
+
+            if let Some(external_id) = &config.external_id {
+                assume_role_provider = 
assume_role_provider.with_external_id(external_id.clone());
+            }
+            if let Some(role_session_name) = &config.role_session_name {
+                assume_role_provider =
+                    
assume_role_provider.with_role_session_name(role_session_name.clone());
+            }
+            provider = 
ProvideCredentialChain::new().push(assume_role_provider);
+        }
+
+        // Replace provider if user provide their own.
+        let provider = if let Some(credential_providers) = 
credential_providers {
+            credential_providers
+        } else {
+            provider
+        };
+
         // Create request signer for S3
         let request_signer = AwsV4Signer::new("s3", &region);
 

Reply via email to