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

stevel pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new c2caf312e62 HADOOP-19181. S3A: IAMCredentialsProvider throttling 
results in auth failures (#8118)
c2caf312e62 is described below

commit c2caf312e621cf22aaed8897c3d66d23480423f2
Author: Steve Loughran <[email protected]>
AuthorDate: Thu Dec 4 20:01:17 2025 +0000

    HADOOP-19181. S3A: IAMCredentialsProvider throttling results in auth 
failures (#8118)
    
    
    
    Hard-code a 15 minute  advance time for credential renewal, so
    even if a large number of processes simultaneously trying
    to renew their tokens through IAM requests may trigger
    throttling, the asynchronous refresh thread has minutes of
    backoff and retry before the existing credentials become invalid.
    
    + Add a test case to explicitly instantiate the class and ask for 
credentials
      doesn't care about whether credentials are returned (EC2 runs) or
      if NoAwsCredentialsException is returned -any other exception is raised as
      a failure.
    + Make test suite subclass of HadoopTestBase to avoid instantiating s3a fs.
    
    Contains HADOOP-19748: S3A: ITestAssumeRole tests failing now STS returns 
detailed
     error messages
    
    Contributed by Steve Loughran
---
 .../fs/s3a/auth/IAMInstanceCredentialsProvider.java   | 11 +++++++++++
 .../hadoop/fs/s3a/TestS3AAWSCredentialsProvider.java  | 19 ++++++++++++++++++-
 .../apache/hadoop/fs/s3a/auth/ITestAssumeRole.java    |  8 +++++---
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/auth/IAMInstanceCredentialsProvider.java
 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/auth/IAMInstanceCredentialsProvider.java
index b9a7c776b14..3c82b398761 100644
--- 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/auth/IAMInstanceCredentialsProvider.java
+++ 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/auth/IAMInstanceCredentialsProvider.java
@@ -20,6 +20,7 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.time.Duration;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -62,6 +63,12 @@ public class IAMInstanceCredentialsProvider
   private static final Logger LOG =
       LoggerFactory.getLogger(IAMInstanceCredentialsProvider.class);
 
+  /**
+   * How far in advance of credential expiry must IAM credentials be refreshed.
+   * See HADOOP-19181. S3A: IAMCredentialsProvider throttling results in AWS 
auth failures
+   */
+  public static final Duration TIME_BEFORE_EXPIRY = Duration.ofMinutes(5);
+
   /**
    * The credentials provider.
    * Initially a container credentials provider, but if that fails
@@ -130,8 +137,12 @@ private synchronized AwsCredentials getCredentials() {
         // close it to shut down any thread
         iamCredentialsProvider.close();
         isContainerCredentialsProvider = false;
+
+        // create an async credentials provider with a safe credential
+        // expiry time.
         iamCredentialsProvider = InstanceProfileCredentialsProvider.builder()
                 .asyncCredentialUpdateEnabled(true)
+                .staleTime(TIME_BEFORE_EXPIRY)
                 .build();
         return iamCredentialsProvider.resolveCredentials();
       } else {
diff --git 
a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AAWSCredentialsProvider.java
 
b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AAWSCredentialsProvider.java
index c759043252f..4721cc6a973 100644
--- 
a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AAWSCredentialsProvider.java
+++ 
b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/TestS3AAWSCredentialsProvider.java
@@ -55,11 +55,13 @@
 import org.apache.hadoop.fs.s3a.auth.CredentialProviderListFactory;
 import org.apache.hadoop.fs.s3a.auth.IAMInstanceCredentialsProvider;
 import org.apache.hadoop.fs.s3a.auth.NoAuthWithAWSException;
+import org.apache.hadoop.fs.s3a.auth.NoAwsCredentialsException;
 import org.apache.hadoop.fs.s3a.auth.ProfileAWSCredentialsProvider;
 import org.apache.hadoop.fs.s3a.auth.delegation.CountInvocationsProvider;
 import org.apache.hadoop.fs.s3a.impl.InstantiationIOException;
 import org.apache.hadoop.fs.s3a.test.PublicDatasetTestUtils;
 import org.apache.hadoop.io.retry.RetryPolicy;
+import org.apache.hadoop.test.HadoopTestBase;
 import org.apache.hadoop.util.Sets;
 
 import static 
org.apache.hadoop.fs.s3a.Constants.ASSUMED_ROLE_CREDENTIALS_PROVIDER;
@@ -79,7 +81,7 @@
 /**
  * Unit tests for {@link Constants#AWS_CREDENTIALS_PROVIDER} logic.
  */
-public class TestS3AAWSCredentialsProvider extends AbstractS3ATestBase {
+public class TestS3AAWSCredentialsProvider extends HadoopTestBase {
 
   /**
    * URI of the test file: this must be anonymously accessible.
@@ -921,4 +923,19 @@ public static AwsCredentialsProvider create() throws 
ClassNotFoundException {
     }
   }
 
+  @Test
+  public void testIAMInstanceCredentialsProvider() throws Throwable {
+
+    final Configuration conf =
+        createProviderConfiguration(IAMInstanceCredentialsProvider.class);
+    Path testFile = getExternalData(conf);
+    try (AWSCredentialProviderList list = 
createAWSCredentialProviderList(testFile.toUri(), conf)) {
+      try {
+        list.resolveCredentials();
+      } catch (NoAwsCredentialsException e) {
+        ///  this is OK.
+      }
+
+    }
+  }
 }
diff --git 
a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/auth/ITestAssumeRole.java
 
b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/auth/ITestAssumeRole.java
index 58eb3b6ec26..279cbe3e4de 100644
--- 
a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/auth/ITestAssumeRole.java
+++ 
b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/auth/ITestAssumeRole.java
@@ -102,6 +102,8 @@ public class ITestAssumeRole extends AbstractS3ATestBase {
   private static final Statement STATEMENT_ALL_BUCKET_READ_ACCESS
       = statement(true, S3_ALL_BUCKETS, S3_BUCKET_READ_OPERATIONS);
 
+  public static final String MALFORMED_POLICY_DOCUMENT = 
"MalformedPolicyDocument";
+
   /**
    * test URI, built in setup.
    */
@@ -244,13 +246,13 @@ public void testAssumeRoleNoARN() throws Exception {
 
   @Test
   public void testAssumeRoleFSBadPolicy() throws Exception {
-    describe("Attemnpt to create the FS with malformed JSON");
+    describe("Attempt to create the FS with malformed JSON");
     Configuration conf = createAssumedRoleConfig();
     // add some malformed JSON
     conf.set(ASSUMED_ROLE_POLICY,  "}");
     expectFileSystemCreateFailure(conf,
         AWSBadRequestException.class,
-        "JSON");
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test
@@ -261,7 +263,7 @@ public void testAssumeRoleFSBadPolicy2() throws Exception {
     conf.set(ASSUMED_ROLE_POLICY, "{'json':'but not what AWS wants}");
     expectFileSystemCreateFailure(conf,
         AWSBadRequestException.class,
-        "Syntax errors in policy");
+        MALFORMED_POLICY_DOCUMENT);
   }
 
   @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to