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

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


The following commit(s) were added to refs/heads/main by this push:
     new 0c1e4a0d658 NIFI-15535 - Fixed AWS Connection Pool Shutdown on EKS 
with STS Credential Refresh
0c1e4a0d658 is described below

commit 0c1e4a0d658eb42459d2f101ab9b3950749a5503
Author: Pierre Villard <[email protected]>
AuthorDate: Wed Mar 18 16:36:44 2026 +0100

    NIFI-15535 - Fixed AWS Connection Pool Shutdown on EKS with STS Credential 
Refresh
    
    This closes #11020.
    
    Signed-off-by: Peter Turcsanyi <[email protected]>
---
 .../AWSCredentialsProviderControllerService.java   | 15 +++--
 ...WSCredentialsProviderControllerServiceTest.java | 68 ++++++++++++++++++++++
 2 files changed, 79 insertions(+), 4 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java
index d0808c1dab3..6cfd2e3901a 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java
@@ -20,6 +20,7 @@ import org.apache.nifi.annotation.behavior.Restricted;
 import org.apache.nifi.annotation.behavior.Restriction;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
 import org.apache.nifi.annotation.lifecycle.OnEnabled;
 import org.apache.nifi.components.AllowableValue;
 import org.apache.nifi.components.PropertyDescriptor;
@@ -244,7 +245,7 @@ public class AWSCredentialsProviderControllerService 
extends AbstractControllerS
         OAUTH2_ACCESS_TOKEN_PROVIDER
     );
 
-    private volatile AwsCredentialsProvider credentialsProvider;
+    private volatile ConfigurationContext configurationContext;
 
     private final List<CredentialsStrategy> strategies = List.of(
         // Primary Credential Strategies
@@ -292,7 +293,9 @@ public class AWSCredentialsProviderControllerService 
extends AbstractControllerS
 
     @Override
     public AwsCredentialsProvider getAwsCredentialsProvider() {
-        return credentialsProvider;
+        final AwsCredentialsProvider provider = 
createCredentialsProvider(configurationContext);
+        getLogger().debug("Created AwsCredentialsProvider [{}] instance [{}]", 
provider.getClass().getSimpleName(), System.identityHashCode(provider));
+        return provider;
     }
 
     private AwsCredentialsProvider createCredentialsProvider(final 
PropertyContext context) {
@@ -361,8 +364,12 @@ public class AWSCredentialsProviderControllerService 
extends AbstractControllerS
 
     @OnEnabled
     public void onConfigured(final ConfigurationContext context) {
-        credentialsProvider = createCredentialsProvider(context);
-        getLogger().debug("Using credentials provider: {}", 
credentialsProvider.getClass());
+        this.configurationContext = context;
+    }
+
+    @OnDisabled
+    public void onDisabled() {
+        configurationContext = null;
     }
 
     public static AllowableValue[] getAvailableRegions() {
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java
index 6717e399d30..4340994dec2 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java
@@ -53,6 +53,7 @@ import static 
org.apache.nifi.processors.aws.credentials.provider.service.AWSCre
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
 
 public class AWSCredentialsProviderControllerServiceTest {
 
@@ -409,6 +410,73 @@ public class AWSCredentialsProviderControllerServiceTest {
                 "Derived AssumeRole should not be chained when OAuth2 (Web 
Identity) is configured");
     }
 
+    @Test
+    public void testGetAwsCredentialsProviderReturnsIndependentInstances() 
throws Throwable {
+        final TestRunner runner = 
TestRunners.newTestRunner(FetchS3Object.class);
+        final AWSCredentialsProviderControllerService serviceImpl = new 
AWSCredentialsProviderControllerService();
+        runner.addControllerService("awsCredentialsProvider", serviceImpl);
+        runner.enableControllerService(serviceImpl);
+
+        final AwsCredentialsProviderService service = 
(AwsCredentialsProviderService) runner.getProcessContext()
+                
.getControllerServiceLookup().getControllerService("awsCredentialsProvider");
+
+        final AwsCredentialsProvider first = 
service.getAwsCredentialsProvider();
+        final AwsCredentialsProvider second = 
service.getAwsCredentialsProvider();
+
+        assertNotNull(first);
+        assertNotNull(second);
+        assertNotSame(first, second, "Each call should return an independent 
AwsCredentialsProvider to avoid shared connection pool issues");
+        assertEquals(DefaultCredentialsProvider.class, first.getClass());
+        assertEquals(DefaultCredentialsProvider.class, second.getClass());
+    }
+
+    @Test
+    public void 
testGetAwsCredentialsProviderReturnsIndependentInstancesWithAccessKeys() throws 
Throwable {
+        final TestRunner runner = 
TestRunners.newTestRunner(FetchS3Object.class);
+        final AWSCredentialsProviderControllerService serviceImpl = new 
AWSCredentialsProviderControllerService();
+        runner.addControllerService("awsCredentialsProvider", serviceImpl);
+        runner.setProperty(serviceImpl, ACCESS_KEY_ID, "awsAccessKey");
+        runner.setProperty(serviceImpl, SECRET_KEY, "awsSecretKey");
+        runner.enableControllerService(serviceImpl);
+
+        final AwsCredentialsProviderService service = 
(AwsCredentialsProviderService) runner.getProcessContext()
+                
.getControllerServiceLookup().getControllerService("awsCredentialsProvider");
+
+        final AwsCredentialsProvider first = 
service.getAwsCredentialsProvider();
+        final AwsCredentialsProvider second = 
service.getAwsCredentialsProvider();
+
+        assertNotNull(first);
+        assertNotNull(second);
+        assertNotSame(first, second, "Each call should return an independent 
AwsCredentialsProvider to avoid shared connection pool issues");
+        assertEquals("awsAccessKey", first.resolveCredentials().accessKeyId());
+        assertEquals("awsAccessKey", 
second.resolveCredentials().accessKeyId());
+    }
+
+    @Test
+    public void 
testGetAwsCredentialsProviderReturnsIndependentInstancesWithAssumeRole() throws 
Throwable {
+        final TestRunner runner = 
TestRunners.newTestRunner(FetchS3Object.class);
+        final AWSCredentialsProviderControllerService serviceImpl = new 
AWSCredentialsProviderControllerService();
+        runner.addControllerService("awsCredentialsProvider", serviceImpl);
+        runner.setProperty(serviceImpl, ACCESS_KEY_ID, "awsAccessKey");
+        runner.setProperty(serviceImpl, SECRET_KEY, "awsSecretKey");
+        runner.setProperty(serviceImpl, 
AWSCredentialsProviderControllerService.ASSUME_ROLE_STS_REGION, 
Region.US_WEST_1.id());
+        runner.setProperty(serviceImpl, 
AWSCredentialsProviderControllerService.ASSUME_ROLE_ARN, "Role");
+        runner.setProperty(serviceImpl, 
AWSCredentialsProviderControllerService.ASSUME_ROLE_NAME, "RoleName");
+        runner.enableControllerService(serviceImpl);
+
+        final AwsCredentialsProviderService service = 
(AwsCredentialsProviderService) runner.getProcessContext()
+                
.getControllerServiceLookup().getControllerService("awsCredentialsProvider");
+
+        final AwsCredentialsProvider first = 
service.getAwsCredentialsProvider();
+        final AwsCredentialsProvider second = 
service.getAwsCredentialsProvider();
+
+        assertNotNull(first);
+        assertNotNull(second);
+        assertNotSame(first, second, "Each call should return an independent 
AwsCredentialsProvider to avoid shared connection pool issues");
+        assertEquals(StsAssumeRoleCredentialsProvider.class, first.getClass());
+        assertEquals(StsAssumeRoleCredentialsProvider.class, 
second.getClass());
+    }
+
     @Test
     void testMigration() {
         final Map<String, String> propertyValues = Map.of(

Reply via email to