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(