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

huaxingao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new 48da548979 AWS: Prefer custom credential provider if specified (#15249)
48da548979 is described below

commit 48da548979099d0c33c8f39062f728175f786538
Author: Bryan Keller <[email protected]>
AuthorDate: Fri Feb 6 18:15:40 2026 -0800

    AWS: Prefer custom credential provider if specified (#15249)
    
    * AWS: Prefer custom credential provider if specified
    
    * add test
---
 .../apache/iceberg/aws/AwsClientProperties.java    | 10 +++++----
 .../apache/iceberg/aws/s3/S3FileIOProperties.java  |  2 +-
 .../iceberg/aws/TestAwsClientProperties.java       | 26 ++++++++++++++++++++++
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/aws/src/main/java/org/apache/iceberg/aws/AwsClientProperties.java 
b/aws/src/main/java/org/apache/iceberg/aws/AwsClientProperties.java
index 056959df23..c5850d0c79 100644
--- a/aws/src/main/java/org/apache/iceberg/aws/AwsClientProperties.java
+++ b/aws/src/main/java/org/apache/iceberg/aws/AwsClientProperties.java
@@ -212,6 +212,12 @@ public class AwsClientProperties implements Serializable {
   @SuppressWarnings("checkstyle:HiddenField")
   public AwsCredentialsProvider credentialsProvider(
       String accessKeyId, String secretAccessKey, String sessionToken) {
+    if (!Strings.isNullOrEmpty(this.clientCredentialsProvider)) {
+      clientCredentialsProviderProperties.put(
+          VendedCredentialsProvider.URI, refreshCredentialsEndpoint);
+      return credentialsProvider(this.clientCredentialsProvider);
+    }
+
     if (refreshCredentialsEnabled && 
!Strings.isNullOrEmpty(refreshCredentialsEndpoint)) {
       clientCredentialsProviderProperties.put(
           VendedCredentialsProvider.URI, refreshCredentialsEndpoint);
@@ -228,10 +234,6 @@ public class AwsClientProperties implements Serializable {
       }
     }
 
-    if (!Strings.isNullOrEmpty(this.clientCredentialsProvider)) {
-      return credentialsProvider(this.clientCredentialsProvider);
-    }
-
     // Create a new credential provider for each client
     return DefaultCredentialsProvider.builder().build();
   }
diff --git 
a/aws/src/main/java/org/apache/iceberg/aws/s3/S3FileIOProperties.java 
b/aws/src/main/java/org/apache/iceberg/aws/s3/S3FileIOProperties.java
index c6c126ef75..ad5181fd27 100644
--- a/aws/src/main/java/org/apache/iceberg/aws/s3/S3FileIOProperties.java
+++ b/aws/src/main/java/org/apache/iceberg/aws/s3/S3FileIOProperties.java
@@ -270,7 +270,7 @@ public class S3FileIOProperties implements Serializable {
    * This expiration time is currently only used in {@link 
VendedCredentialsProvider} for refreshing
    * vended credentials.
    */
-  static final String SESSION_TOKEN_EXPIRES_AT_MS = 
"s3.session-token-expires-at-ms";
+  public static final String SESSION_TOKEN_EXPIRES_AT_MS = 
"s3.session-token-expires-at-ms";
 
   /**
    * Enable to make S3FileIO, to make cross-region call to the region 
specified in the ARN of an
diff --git 
a/aws/src/test/java/org/apache/iceberg/aws/TestAwsClientProperties.java 
b/aws/src/test/java/org/apache/iceberg/aws/TestAwsClientProperties.java
index cac8d892ba..47bb12c83b 100644
--- a/aws/src/test/java/org/apache/iceberg/aws/TestAwsClientProperties.java
+++ b/aws/src/test/java/org/apache/iceberg/aws/TestAwsClientProperties.java
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.AwsCredentials;
 import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
 import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
 import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
@@ -39,6 +40,17 @@ import software.amazon.awssdk.services.s3.S3ClientBuilder;
 
 public class TestAwsClientProperties {
 
+  public static class CustomCredentialProvider implements 
AwsCredentialsProvider {
+    public static AwsCredentialsProvider create(Map<String, String> 
properties) {
+      return new CustomCredentialProvider();
+    }
+
+    @Override
+    public AwsCredentials resolveCredentials() {
+      return AwsBasicCredentials.builder().build();
+    }
+  }
+
   @Test
   public void testApplyClientRegion() {
     Map<String, String> properties = Maps.newHashMap();
@@ -236,4 +248,18 @@ public class TestAwsClientProperties {
                 OAuth2Properties.TOKEN,
                 "oauth-token"));
   }
+
+  @Test
+  public void customCredentialsProviderTakesPrecedence() {
+    AwsClientProperties awsClientProperties =
+        new AwsClientProperties(
+            ImmutableMap.of(
+                AwsClientProperties.REFRESH_CREDENTIALS_ENDPOINT,
+                "http://localhost:1234/v1/credentials";,
+                AwsClientProperties.CLIENT_CREDENTIALS_PROVIDER,
+                CustomCredentialProvider.class.getName()));
+    AwsCredentialsProvider provider =
+        awsClientProperties.credentialsProvider("key", "secret", "token");
+    assertThat(provider).isInstanceOf(CustomCredentialProvider.class);
+  }
 }

Reply via email to