From 31af82275e81d8f932a7346fee36857e8fcafcd9 Mon Sep 17 00:00:00 2001 From: Joe Gresock Date: Fri, 11 Nov 2022 05:07:07 -0500 Subject: [PATCH] NIFI-10791 Added AWS SDK v2 support to AWSCredentialsProviderControllerService This closes #6661 Signed-off-by: David Handermann --- .../nifi-aws-abstract-processors/pom.xml | 8 ++ .../CredentialPropertyDescriptors.java | 29 +++++ .../nifi-aws-processors/pom.xml | 4 + .../PropertiesCredentialsProvider.java | 63 ++++++++++ .../factory/CredentialsProviderFactory.java | 21 ++++ .../provider/factory/CredentialsStrategy.java | 20 ++- .../AbstractBooleanCredentialsStrategy.java | 18 +-- .../AbstractCredentialsStrategy.java | 42 ++++--- .../AccessKeyPairCredentialsStrategy.java | 28 +++-- .../AnonymousCredentialsStrategy.java | 22 ++-- .../AssumeRoleCredentialsStrategy.java | 114 ++++++++++++++---- .../ExplicitDefaultCredentialsStrategy.java | 9 +- .../strategies/FileCredentialsStrategy.java | 24 ++-- .../ImplicitDefaultCredentialsStrategy.java | 15 ++- .../NamedProfileCredentialsStrategy.java | 10 +- ...SCredentialsProviderControllerService.java | 29 +++-- .../provider/factory/MockAWSProcessor.java | 4 +- .../TestCredentialsProviderFactory.java | 54 ++++++++- ...dentialsProviderControllerServiceTest.java | 26 ++++ .../nifi-aws-service-api/pom.xml | 4 + .../AwsCredentialsProviderService.java | 43 +++++++ .../AWSCredentialsProviderService.java | 9 +- 22 files changed, 491 insertions(+), 105 deletions(-) create mode 100644 nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/PropertiesCredentialsProvider.java create mode 100644 nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/AwsCredentialsProviderService.java diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/pom.xml b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/pom.xml index 173b8a5d94..da99b90d32 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/pom.xml +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/pom.xml @@ -48,6 +48,14 @@ + + software.amazon.awssdk + s3 + + + software.amazon.awssdk + apache-client + org.slf4j jcl-over-slf4j diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java index 707d39a60e..78e60f09b3 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java @@ -16,11 +16,16 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory; +import org.apache.nifi.components.AllowableValue; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.resource.ResourceCardinality; import org.apache.nifi.components.resource.ResourceType; import org.apache.nifi.expression.ExpressionLanguageScope; import org.apache.nifi.processor.util.StandardValidators; +import software.amazon.awssdk.regions.Region; + +import java.util.ArrayList; +import java.util.List; /** * Shared definitions of properties that specify various AWS credentials. @@ -194,4 +199,28 @@ public class CredentialPropertyDescriptors { "this property to \"sts.cn-north-1.amazonaws.com.cn\" when you are requesting session credentials " + "for services in China(Beijing) region or to \"sts.us-gov-west-1.amazonaws.com\" for GovCloud.") .build(); + + public static final PropertyDescriptor ASSUME_ROLE_REGION = new PropertyDescriptor.Builder() + .name("assume-role-sts-region") + .displayName("Region") + .description("The AWS Security Token Service (STS) region") + .dependsOn(ASSUME_ROLE_ARN) + .allowableValues(getAvailableRegions()) + .defaultValue(createAllowableValue(Region.US_WEST_2).getValue()) + .build(); + + public static AllowableValue createAllowableValue(final Region region) { + return new AllowableValue(region.id(), region.metadata().description(), "AWS Region Code : " + region.id()); + } + + public static AllowableValue[] getAvailableRegions() { + final List values = new ArrayList<>(); + for (final Region region : Region.regions()) { + if (region.isGlobalRegion()) { + continue; + } + values.add(createAllowableValue(region)); + } + return values.toArray(new AllowableValue[0]); + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/pom.xml b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/pom.xml index d3c3b59077..49bc3aef24 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/pom.xml +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/pom.xml @@ -74,6 +74,10 @@ com.amazonaws aws-java-sdk-sts + + software.amazon.awssdk + sts + commons-beanutils commons-beanutils diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/PropertiesCredentialsProvider.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/PropertiesCredentialsProvider.java new file mode 100644 index 0000000000..1e37392b7b --- /dev/null +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/PropertiesCredentialsProvider.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.processors.aws.credentials.provider; + + +import org.apache.nifi.processor.exception.ProcessException; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; + +public class PropertiesCredentialsProvider implements AwsCredentialsProvider { + + private final String accessKey; + private final String secretAccessKey; + + public PropertiesCredentialsProvider(final File credentialsProperties) { + try { + if (!credentialsProperties.exists()) { + throw new FileNotFoundException("File doesn't exist: " + credentialsProperties.getAbsolutePath()); + } + + try (final FileInputStream stream = new FileInputStream(credentialsProperties)) { + final Properties accountProperties = new Properties(); + accountProperties.load(stream); + + if (accountProperties.getProperty("accessKey") == null || accountProperties.getProperty("secretKey") == null) { + throw new IllegalArgumentException(String.format("The specified file (%s) doesn't contain the expected properties " + + "'accessKey' and 'secretKey'.", credentialsProperties.getAbsolutePath())); + } + + accessKey = accountProperties.getProperty("accessKey"); + secretAccessKey = accountProperties.getProperty("secretKey"); + } + } catch (final IOException e) { + throw new ProcessException("Failed to load AWS credentials properties " + credentialsProperties, e); + } + } + + @Override + public AwsCredentials resolveCredentials() { + return AwsBasicCredentials.create(accessKey, secretAccessKey); + } +} \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsProviderFactory.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsProviderFactory.java index 94f041005c..545f3a283a 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsProviderFactory.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsProviderFactory.java @@ -33,6 +33,7 @@ import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.Im import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.AssumeRoleCredentialsStrategy; import com.amazonaws.auth.AWSCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; /** @@ -122,4 +123,24 @@ public class CredentialsProviderFactory { return primaryCredentialsProvider; } } + + /** + * Produces the AwsCredentialsProvider according to the given property set and the strategies configured in + * the factory. + * @return AwsCredentialsProvider implementation + */ + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + final CredentialsStrategy primaryStrategy = selectPrimaryStrategy(properties); + final AwsCredentialsProvider primaryCredentialsProvider = primaryStrategy.getAwsCredentialsProvider(properties); + AwsCredentialsProvider derivedCredentialsProvider = null; + + for (final CredentialsStrategy strategy : strategies) { + if (strategy.canCreateDerivedCredential(properties)) { + derivedCredentialsProvider = strategy.getDerivedAwsCredentialsProvider(properties, primaryCredentialsProvider); + break; + } + } + + return derivedCredentialsProvider == null ? primaryCredentialsProvider : derivedCredentialsProvider; + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsStrategy.java index d5d93a7277..05dc871ca4 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsStrategy.java @@ -16,14 +16,14 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory; -import java.util.Collection; -import java.util.Map; - +import com.amazonaws.auth.AWSCredentialsProvider; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.ValidationContext; import org.apache.nifi.components.ValidationResult; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import com.amazonaws.auth.AWSCredentialsProvider; +import java.util.Collection; +import java.util.Map; /** @@ -72,4 +72,16 @@ public interface CredentialsStrategy { AWSCredentialsProvider getDerivedCredentialsProvider(Map properties, AWSCredentialsProvider primaryCredentialsProvider); + /** + * Creates an AwsCredentialsProvider instance for this strategy, given the properties defined by the user. + */ + AwsCredentialsProvider getAwsCredentialsProvider(Map properties); + + /** + * Creates an AwsCredentialsProvider instance for this strategy, given the properties defined by the user and + * the AwsCredentialsProvider from the winning primary strategy. + */ + AwsCredentialsProvider getDerivedAwsCredentialsProvider(Map properties, + AwsCredentialsProvider primaryCredentialsProvider); + } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractBooleanCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractBooleanCredentialsStrategy.java index 2c5b9a39db..4079d5a364 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractBooleanCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractBooleanCredentialsStrategy.java @@ -34,7 +34,7 @@ public abstract class AbstractBooleanCredentialsStrategy extends AbstractCredent private PropertyDescriptor strategyProperty; - public AbstractBooleanCredentialsStrategy(String name, PropertyDescriptor strategyProperty) { + public AbstractBooleanCredentialsStrategy(final String name, final PropertyDescriptor strategyProperty) { super("Default Credentials", new PropertyDescriptor[]{ strategyProperty }); @@ -42,21 +42,21 @@ public abstract class AbstractBooleanCredentialsStrategy extends AbstractCredent } @Override - public boolean canCreatePrimaryCredential(Map properties) { - String useStrategyString = properties.get(strategyProperty); - Boolean useStrategy = Boolean.parseBoolean(useStrategyString); + public boolean canCreatePrimaryCredential(final Map properties) { + final String useStrategyString = properties.get(strategyProperty); + final Boolean useStrategy = Boolean.parseBoolean(useStrategyString); return useStrategy; } @Override public Collection validate(final ValidationContext validationContext, final CredentialsStrategy primaryStrategy) { - boolean thisIsSelectedStrategy = this == primaryStrategy; - Boolean useStrategy = validationContext.getProperty(strategyProperty).asBoolean(); + final boolean thisIsSelectedStrategy = this == primaryStrategy; + final Boolean useStrategy = validationContext.getProperty(strategyProperty).asBoolean(); if (!thisIsSelectedStrategy && useStrategy) { - String failureFormat = "property %1$s cannot be used with %2$s"; - Collection validationFailureResults = new ArrayList(); - String message = String.format(failureFormat, strategyProperty.getDisplayName(), + final String failureFormat = "property %1$s cannot be used with %2$s"; + final Collection validationFailureResults = new ArrayList(); + final String message = String.format(failureFormat, strategyProperty.getDisplayName(), primaryStrategy.getName()); validationFailureResults.add(new ValidationResult.Builder() .subject(strategyProperty.getDisplayName()) diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractCredentialsStrategy.java index 29f1000318..5940bf28f2 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractCredentialsStrategy.java @@ -26,6 +26,7 @@ import org.apache.nifi.components.ValidationResult; import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy; import com.amazonaws.auth.AWSCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; /** @@ -35,17 +36,17 @@ public abstract class AbstractCredentialsStrategy implements CredentialsStrategy private final String name; private final PropertyDescriptor[] requiredProperties; - public AbstractCredentialsStrategy(String name, PropertyDescriptor[] requiredProperties) { + public AbstractCredentialsStrategy(final String name, PropertyDescriptor[] requiredProperties) { this.name = name; this.requiredProperties = requiredProperties; } @Override - public boolean canCreatePrimaryCredential(Map properties) { - for (PropertyDescriptor requiredProperty : requiredProperties) { - boolean containsRequiredProperty = properties.containsKey(requiredProperty); - String propertyValue = properties.get(requiredProperty); - boolean containsValue = propertyValue != null; + public boolean canCreatePrimaryCredential(final Map properties) { + for (final PropertyDescriptor requiredProperty : requiredProperties) { + final boolean containsRequiredProperty = properties.containsKey(requiredProperty); + final String propertyValue = properties.get(requiredProperty); + final boolean containsValue = propertyValue != null; if (!containsRequiredProperty || !containsValue) { return false; } @@ -56,19 +57,19 @@ public abstract class AbstractCredentialsStrategy implements CredentialsStrategy @Override public Collection validate(final ValidationContext validationContext, final CredentialsStrategy primaryStrategy) { - boolean thisIsSelectedStrategy = this == primaryStrategy; - String requiredMessageFormat = "property %1$s must be set with %2$s"; - String excludedMessageFormat = "property %1$s cannot be used with %2$s"; - String failureFormat = thisIsSelectedStrategy ? requiredMessageFormat : excludedMessageFormat; + final boolean thisIsSelectedStrategy = this == primaryStrategy; + final String requiredMessageFormat = "property %1$s must be set with %2$s"; + final String excludedMessageFormat = "property %1$s cannot be used with %2$s"; + final String failureFormat = thisIsSelectedStrategy ? requiredMessageFormat : excludedMessageFormat; Collection validationFailureResults = null; - for (PropertyDescriptor requiredProperty : requiredProperties) { - boolean requiredPropertyIsSet = validationContext.getProperty(requiredProperty).isSet(); + for (final PropertyDescriptor requiredProperty : requiredProperties) { + final boolean requiredPropertyIsSet = validationContext.getProperty(requiredProperty).isSet(); if (requiredPropertyIsSet != thisIsSelectedStrategy) { String message = String.format(failureFormat, requiredProperty.getDisplayName(), primaryStrategy.getName()); if (validationFailureResults == null) { - validationFailureResults = new ArrayList(); + validationFailureResults = new ArrayList<>(); } validationFailureResults.add(new ValidationResult.Builder() .subject(requiredProperty.getDisplayName()) @@ -80,7 +81,7 @@ public abstract class AbstractCredentialsStrategy implements CredentialsStrategy return validationFailureResults; } - public abstract AWSCredentialsProvider getCredentialsProvider(Map properties); + public abstract AWSCredentialsProvider getCredentialsProvider(final Map properties); public String getName() { return name; @@ -88,14 +89,19 @@ public abstract class AbstractCredentialsStrategy implements CredentialsStrategy @Override - public boolean canCreateDerivedCredential(Map properties) { + public boolean canCreateDerivedCredential(final Map properties) { return false; } @Override - public AWSCredentialsProvider getDerivedCredentialsProvider(Map properties, - AWSCredentialsProvider primaryCredentialsProvider) { - throw new UnsupportedOperationException(); + public AWSCredentialsProvider getDerivedCredentialsProvider(final Map properties, + final AWSCredentialsProvider primaryCredentialsProvider) { + return null; } + @Override + public AwsCredentialsProvider getDerivedAwsCredentialsProvider(final Map properties, + final AwsCredentialsProvider primaryCredentialsProvider) { + return null; + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AccessKeyPairCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AccessKeyPairCredentialsStrategy.java index 5cf8869276..16251dae5b 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AccessKeyPairCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AccessKeyPairCredentialsStrategy.java @@ -16,14 +16,15 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory.strategies; -import java.util.Map; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; - import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.internal.StaticCredentialsProvider; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; + +import java.util.Map; /** @@ -42,11 +43,18 @@ public class AccessKeyPairCredentialsStrategy extends AbstractCredentialsStrateg } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { - String accessKey = properties.get(CredentialPropertyDescriptors.ACCESS_KEY); - String secretKey = properties.get(CredentialPropertyDescriptors.SECRET_KEY); - BasicAWSCredentials creds = new BasicAWSCredentials(accessKey, secretKey); - return new StaticCredentialsProvider(creds); + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { + final String accessKey = properties.get(CredentialPropertyDescriptors.ACCESS_KEY); + final String secretKey = properties.get(CredentialPropertyDescriptors.SECRET_KEY); + final BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + return new StaticCredentialsProvider(credentials); + } + + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + final String accessKey = properties.get(CredentialPropertyDescriptors.ACCESS_KEY); + final String secretKey = properties.get(CredentialPropertyDescriptors.SECRET_KEY); + return software.amazon.awssdk.auth.credentials.StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey)); } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AnonymousCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AnonymousCredentialsStrategy.java index 4f8368ed14..416163d0ce 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AnonymousCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AnonymousCredentialsStrategy.java @@ -16,14 +16,15 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory.strategies; -import java.util.Map; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; - import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.AnonymousAWSCredentials; import com.amazonaws.internal.StaticCredentialsProvider; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; + +import java.util.Map; /** @@ -39,9 +40,14 @@ public class AnonymousCredentialsStrategy extends AbstractBooleanCredentialsStra } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { - AnonymousAWSCredentials creds = new AnonymousAWSCredentials(); - return new StaticCredentialsProvider(creds); + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { + AnonymousAWSCredentials credentials = new AnonymousAWSCredentials(); + return new StaticCredentialsProvider(credentials); + } + + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + return AnonymousCredentialsProvider.create(); } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java index 32439a9aee..5766332436 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java @@ -16,27 +16,37 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory.strategies; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.components.ValidationContext; -import org.apache.nifi.components.ValidationResult; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_ARN; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_EXTERNAL_ID; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.MAX_SESSION_TIME; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_NAME; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_STS_ENDPOINT; -import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy; - import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; import com.amazonaws.services.securitytoken.AWSSecurityTokenService; import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.sts.StsClient; +import software.amazon.awssdk.services.sts.StsClientBuilder; +import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider; +import software.amazon.awssdk.services.sts.model.AssumeRoleRequest; + +import java.net.URI; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_ARN; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_EXTERNAL_ID; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_NAME; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_STS_ENDPOINT; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.MAX_SESSION_TIME; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_REGION; /** @@ -57,12 +67,12 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { } @Override - public boolean canCreatePrimaryCredential(Map properties) { + public boolean canCreatePrimaryCredential(final Map properties) { return false; } @Override - public boolean canCreateDerivedCredential(Map properties) { + public boolean canCreateDerivedCredential(final Map properties) { final String assumeRoleArn = properties.get(ASSUME_ROLE_ARN); final String assumeRoleName = properties.get(ASSUME_ROLE_NAME); if (assumeRoleArn != null && !assumeRoleArn.isEmpty() @@ -72,7 +82,7 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { return false; } - public boolean proxyVariablesValidForAssumeRole(Map properties){ + public boolean proxyVariablesValidForAssumeRole(final Map properties){ final String assumeRoleProxyHost = properties.get(ASSUME_ROLE_PROXY_HOST); final String assumeRoleProxyPort = properties.get(ASSUME_ROLE_PROXY_PORT); if (assumeRoleProxyHost != null && !assumeRoleProxyHost.isEmpty() @@ -135,17 +145,17 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { throw new UnsupportedOperationException(); } @Override - public AWSCredentialsProvider getDerivedCredentialsProvider(Map properties, - AWSCredentialsProvider primaryCredentialsProvider) { + public AWSCredentialsProvider getDerivedCredentialsProvider(final Map properties, + final AWSCredentialsProvider primaryCredentialsProvider) { final String assumeRoleArn = properties.get(ASSUME_ROLE_ARN); final String assumeRoleName = properties.get(ASSUME_ROLE_NAME); String rawMaxSessionTime = properties.get(MAX_SESSION_TIME); - rawMaxSessionTime = (rawMaxSessionTime != null) ? rawMaxSessionTime : MAX_SESSION_TIME.getDefaultValue(); + rawMaxSessionTime = rawMaxSessionTime == null ? MAX_SESSION_TIME.getDefaultValue() : rawMaxSessionTime; final Integer maxSessionTime = Integer.parseInt(rawMaxSessionTime.trim()); final String assumeRoleExternalId = properties.get(ASSUME_ROLE_EXTERNAL_ID); final String assumeRoleSTSEndpoint = properties.get(ASSUME_ROLE_STS_ENDPOINT); @@ -177,4 +187,62 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { return credsProvider; } + + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + throw new UnsupportedOperationException(); + } + + @Override + public AwsCredentialsProvider getDerivedAwsCredentialsProvider(final Map properties, + AwsCredentialsProvider primaryCredentialsProvider) { + final String assumeRoleArn = properties.get(ASSUME_ROLE_ARN); + final String assumeRoleName = properties.get(ASSUME_ROLE_NAME); + String rawMaxSessionTime = properties.get(MAX_SESSION_TIME); + rawMaxSessionTime = rawMaxSessionTime == null ? MAX_SESSION_TIME.getDefaultValue() : rawMaxSessionTime; + final Integer maxSessionTime = Integer.parseInt(rawMaxSessionTime.trim()); + final String assumeRoleExternalId = properties.get(ASSUME_ROLE_EXTERNAL_ID); + final String assumeRoleSTSEndpoint = properties.get(ASSUME_ROLE_STS_ENDPOINT); + final String stsRegion = properties.get(ASSUME_ROLE_REGION); + + final StsAssumeRoleCredentialsProvider.Builder builder = StsAssumeRoleCredentialsProvider.builder(); + + // If proxy variables are set, then create Client Configuration with those values + final ApacheHttpClient.Builder httpClientBuilder = ApacheHttpClient.builder(); + if (proxyVariablesValidForAssumeRole(properties)) { + final String assumeRoleProxyHost = properties.get(ASSUME_ROLE_PROXY_HOST); + final Integer assumeRoleProxyPort = Integer.parseInt(properties.get(ASSUME_ROLE_PROXY_PORT)); + final software.amazon.awssdk.http.apache.ProxyConfiguration proxyConfig = software.amazon.awssdk.http.apache.ProxyConfiguration.builder() + .endpoint(URI.create(String.format("%s:%s", assumeRoleProxyHost, assumeRoleProxyPort))) + .build(); + httpClientBuilder.proxyConfiguration(proxyConfig); + } + + if (stsRegion == null) { + throw new IllegalStateException("Assume Role Region is required to interact with STS"); + } + + final StsClientBuilder stsClientBuilder = StsClient.builder() + .credentialsProvider(primaryCredentialsProvider) + .region(Region.of(stsRegion)) + .httpClient(httpClientBuilder.build()); + if (assumeRoleSTSEndpoint != null && !assumeRoleSTSEndpoint.isEmpty()) { + stsClientBuilder.endpointOverride(URI.create(assumeRoleSTSEndpoint)); + } + final StsClient stsClient = stsClientBuilder.build(); + + final AssumeRoleRequest.Builder roleRequestBuilder = AssumeRoleRequest.builder() + .roleArn(assumeRoleArn) + .roleSessionName(assumeRoleName); + + if (assumeRoleExternalId != null && !assumeRoleExternalId.isEmpty()) { + roleRequestBuilder.externalId(assumeRoleExternalId); + } + + builder.refreshRequest(roleRequestBuilder.build()) + .stsClient(stsClient) + .staleTime(Duration.ofSeconds(maxSessionTime)); + + return builder.build(); + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ExplicitDefaultCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ExplicitDefaultCredentialsStrategy.java index a8ac2e8605..03c2ba9a3f 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ExplicitDefaultCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ExplicitDefaultCredentialsStrategy.java @@ -23,6 +23,8 @@ import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPro import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; /** @@ -39,8 +41,13 @@ public class ExplicitDefaultCredentialsStrategy extends AbstractBooleanCredentia } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { return new DefaultAWSCredentialsProviderChain(); } + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + return DefaultCredentialsProvider.create(); + } + } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/FileCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/FileCredentialsStrategy.java index 7fdf93b4d5..06bfec0139 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/FileCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/FileCredentialsStrategy.java @@ -16,13 +16,15 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory.strategies; -import java.util.Map; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; - import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.PropertiesFileCredentialsProvider; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.processors.aws.credentials.provider.PropertiesCredentialsProvider; +import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; + +import java.io.File; +import java.util.Map; /** @@ -45,9 +47,15 @@ public class FileCredentialsStrategy extends AbstractCredentialsStrategy { } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { - String credsFile = properties.get(CredentialPropertyDescriptors.CREDENTIALS_FILE); - return new PropertiesFileCredentialsProvider(credsFile); + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { + final String credentialsFile = properties.get(CredentialPropertyDescriptors.CREDENTIALS_FILE); + return new PropertiesFileCredentialsProvider(credentialsFile); + } + + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + final String credentialsFile = properties.get(CredentialPropertyDescriptors.CREDENTIALS_FILE); + return new PropertiesCredentialsProvider(new File(credentialsFile)); } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ImplicitDefaultCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ImplicitDefaultCredentialsStrategy.java index d9717b31d9..ab4e025f06 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ImplicitDefaultCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ImplicitDefaultCredentialsStrategy.java @@ -16,12 +16,13 @@ */ package org.apache.nifi.processors.aws.credentials.provider.factory.strategies; -import java.util.Map; - -import org.apache.nifi.components.PropertyDescriptor; - import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; +import org.apache.nifi.components.PropertyDescriptor; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; + +import java.util.Map; /** @@ -36,8 +37,12 @@ public class ImplicitDefaultCredentialsStrategy extends AbstractCredentialsStrat } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { return new DefaultAWSCredentialsProviderChain(); } + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + return DefaultCredentialsProvider.create(); + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/NamedProfileCredentialsStrategy.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/NamedProfileCredentialsStrategy.java index 294f2ed073..8f9ff36fa4 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/NamedProfileCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/NamedProfileCredentialsStrategy.java @@ -23,6 +23,7 @@ import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPro import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.profile.ProfileCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; /** @@ -40,9 +41,14 @@ public class NamedProfileCredentialsStrategy extends AbstractCredentialsStrategy } @Override - public AWSCredentialsProvider getCredentialsProvider(Map properties) { - String profileName = properties.get(CredentialPropertyDescriptors.PROFILE_NAME); + public AWSCredentialsProvider getCredentialsProvider(final Map properties) { + final String profileName = properties.get(CredentialPropertyDescriptors.PROFILE_NAME); return new ProfileCredentialsProvider(profileName); } + @Override + public AwsCredentialsProvider getAwsCredentialsProvider(final Map properties) { + final String profileName = properties.get(CredentialPropertyDescriptors.PROFILE_NAME); + return software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider.create(profileName); + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java index 476a41cf79..fa99e2cddc 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java @@ -16,13 +16,7 @@ */ package org.apache.nifi.processors.aws.credentials.provider.service; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.amazonaws.auth.AWSCredentialsProvider; import org.apache.nifi.annotation.behavior.Restricted; import org.apache.nifi.annotation.behavior.Restriction; import org.apache.nifi.annotation.documentation.CapabilityDescription; @@ -37,13 +31,19 @@ import org.apache.nifi.controller.ConfigurationContext; import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors; import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsProviderFactory; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import com.amazonaws.auth.AWSCredentialsProvider; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ACCESS_KEY; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_EXTERNAL_ID; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_STS_ENDPOINT; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.CREDENTIALS_FILE; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.PROFILE_NAME; @@ -74,6 +74,7 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS public static final PropertyDescriptor ASSUME_ROLE_ARN = CredentialPropertyDescriptors.ASSUME_ROLE_ARN; public static final PropertyDescriptor ASSUME_ROLE_NAME = CredentialPropertyDescriptors.ASSUME_ROLE_NAME; public static final PropertyDescriptor MAX_SESSION_TIME = CredentialPropertyDescriptors.MAX_SESSION_TIME; + public static final PropertyDescriptor ASSUME_ROLE_REGION = CredentialPropertyDescriptors.ASSUME_ROLE_REGION; private static final List properties; @@ -92,10 +93,12 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS props.add(ASSUME_ROLE_PROXY_HOST); props.add(ASSUME_ROLE_PROXY_PORT); props.add(ASSUME_ROLE_STS_ENDPOINT); + props.add(ASSUME_ROLE_REGION); properties = Collections.unmodifiableList(props); } private volatile AWSCredentialsProvider credentialsProvider; + private volatile Map evaluatedProperties; protected final CredentialsProviderFactory credentialsProviderFactory = new CredentialsProviderFactory(); @Override @@ -108,6 +111,12 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS return credentialsProvider; } + @Override + public AwsCredentialsProvider getAwsCredentialsProvider() { + // Avoiding instantiation until actually used, in case v1-related configuration is not compatible with v2 clients + return credentialsProviderFactory.getAwsCredentialsProvider(evaluatedProperties); + } + @Override protected Collection customValidate(final ValidationContext validationContext) { return credentialsProviderFactory.validate(validationContext); @@ -115,7 +124,7 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS @OnEnabled public void onConfigured(final ConfigurationContext context) { - final Map evaluatedProperties = new HashMap<>(context.getProperties()); + evaluatedProperties = new HashMap<>(context.getProperties()); evaluatedProperties.keySet().forEach(propertyDescriptor -> { if (propertyDescriptor.isExpressionLanguageSupported()) { evaluatedProperties.put(propertyDescriptor, diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java index 700c99ad49..2f9ca8a733 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java @@ -36,6 +36,7 @@ import static org.apache.nifi.processors.aws.credentials.provider.factory.Creden import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_NAME; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_REGION; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_STS_ENDPOINT; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.MAX_SESSION_TIME; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.PROFILE_NAME; @@ -61,7 +62,8 @@ public class MockAWSProcessor extends AbstractAWSCredentialsProviderProcessor properties = runner.getProcessContext().getProperties(); + final Map properties = runner.getProcessContext().getProperties(); final CredentialsProviderFactory factory = new CredentialsProviderFactory(); final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties); assertNotNull(credentialsProvider); assertEquals(STSAssumeRoleSessionCredentialsProvider.class, credentialsProvider.getClass(), "credentials provider should be equal"); + + assertThrows(IllegalStateException.class, () -> factory.getAwsCredentialsProvider(properties)); + + runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_REGION, Region.US_WEST_1.id()); + final Map properties2 = runner.getProcessContext().getProperties(); + final AwsCredentialsProvider credentialsProviderV2 = factory.getAwsCredentialsProvider(properties2); + assertNotNull(credentialsProviderV2); + assertEquals(StsAssumeRoleCredentialsProvider.class, + credentialsProviderV2.getClass(), "credentials provider should be equal"); } @Test @@ -181,6 +217,11 @@ public class TestCredentialsProviderFactory { assertNotNull(credentialsProvider); final AWSCredentials creds = credentialsProvider.getCredentials(); assertEquals(AnonymousAWSCredentials.class, creds.getClass(), "credentials should be equal"); + + final AwsCredentialsProvider credentialsProviderV2 = factory.getAwsCredentialsProvider(properties); + assertNotNull(credentialsProviderV2); + assertEquals(AnonymousCredentialsProvider.class, + credentialsProviderV2.getClass(), "credentials provider should be equal"); } @Test @@ -204,6 +245,11 @@ public class TestCredentialsProviderFactory { assertNotNull(credentialsProvider); assertEquals(ProfileCredentialsProvider.class, credentialsProvider.getClass(), "credentials provider should be equal"); + + final AwsCredentialsProvider credentialsProviderV2 = factory.getAwsCredentialsProvider(properties); + assertNotNull(credentialsProviderV2); + assertEquals(software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider.class, + credentialsProviderV2.getClass(), "credentials provider should be equal"); } @Test @@ -212,6 +258,7 @@ public class TestCredentialsProviderFactory { runner.setProperty(CredentialPropertyDescriptors.CREDENTIALS_FILE, "src/test/resources/mock-aws-credentials.properties"); runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_ARN, "BogusArn"); runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_NAME, "BogusSession"); + runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_REGION, Region.US_WEST_2.id()); runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST, "proxy.company.com"); runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT, "8080"); runner.assertValid(); @@ -222,6 +269,11 @@ public class TestCredentialsProviderFactory { assertNotNull(credentialsProvider); assertEquals(STSAssumeRoleSessionCredentialsProvider.class, credentialsProvider.getClass(), "credentials provider should be equal"); + + final AwsCredentialsProvider credentialsProviderV2 = factory.getAwsCredentialsProvider(properties); + assertNotNull(credentialsProviderV2); + assertEquals(StsAssumeRoleCredentialsProvider.class, + credentialsProviderV2.getClass(), "credentials provider should be equal"); } @Test diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java index f2a3e3459b..fd2dc183b9 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerServiceTest.java @@ -27,6 +27,9 @@ import org.apache.nifi.processors.aws.s3.FetchS3Object; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.regions.Region; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -77,6 +80,7 @@ public class AWSCredentialsProviderControllerServiceTest { runner.addControllerService("awsCredentialsProvider", serviceImpl); runner.setProperty(serviceImpl, AbstractAWSProcessor.ACCESS_KEY, "awsAccessKey"); runner.setProperty(serviceImpl, AbstractAWSProcessor.SECRET_KEY, "awsSecretKey"); + runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_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); @@ -98,6 +102,7 @@ public class AWSCredentialsProviderControllerServiceTest { runner.addControllerService("awsCredentialsProvider", serviceImpl); runner.setProperty(serviceImpl, AbstractAWSProcessor.ACCESS_KEY, "awsAccessKey"); runner.setProperty(serviceImpl, AbstractAWSProcessor.SECRET_KEY, "awsSecretKey"); + runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_REGION, Region.US_WEST_1.id()); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_ARN, "Role"); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_NAME, "RoleName"); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.MAX_SESSION_TIME, "1000"); @@ -120,6 +125,7 @@ public class AWSCredentialsProviderControllerServiceTest { runner.addControllerService("awsCredentialsProvider", serviceImpl); runner.setProperty(serviceImpl, AbstractAWSProcessor.ACCESS_KEY, "awsAccessKey"); runner.setProperty(serviceImpl, AbstractAWSProcessor.SECRET_KEY, "awsSecretKey"); + runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_REGION, Region.US_WEST_1.id()); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_ARN, "Role"); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_NAME, "RoleName"); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.MAX_SESSION_TIME, "900"); @@ -135,6 +141,7 @@ public class AWSCredentialsProviderControllerServiceTest { runner.addControllerService("awsCredentialsProvider", serviceImpl); runner.setProperty(serviceImpl, AbstractAWSProcessor.ACCESS_KEY, "awsAccessKey"); runner.setProperty(serviceImpl, AbstractAWSProcessor.SECRET_KEY, "awsSecretKey"); + runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_REGION, Region.US_WEST_1.id()); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_ARN, "Role"); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_NAME, "RoleName"); runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.MAX_SESSION_TIME, "900"); @@ -200,6 +207,7 @@ public class AWSCredentialsProviderControllerServiceTest { runner.addControllerService("awsCredentialsProvider", serviceImpl); runner.setProperty(serviceImpl, AbstractAWSProcessor.CREDENTIALS_FILE, "src/test/resources/mock-aws-credentials.properties"); + runner.setProperty(serviceImpl, AWSCredentialsProviderControllerService.ASSUME_ROLE_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); @@ -322,4 +330,22 @@ public class AWSCredentialsProviderControllerServiceTest { "awsSecretKey", service.getCredentialsProvider().getCredentials().getAWSSecretKey(), "Expression language should be supported for " + CredentialPropertyDescriptors.SECRET_KEY.getName()); } + + @Test + public void testDefaultAWSCredentialsProviderChainV2() throws Throwable { + final TestRunner runner = TestRunners.newTestRunner(FetchS3Object.class); + final AWSCredentialsProviderControllerService serviceImpl = new AWSCredentialsProviderControllerService(); + runner.addControllerService("awsCredentialsProvider", serviceImpl); + + runner.enableControllerService(serviceImpl); + + runner.assertValid(serviceImpl); + final AWSCredentialsProviderService service = (AWSCredentialsProviderService) runner.getProcessContext() + .getControllerServiceLookup().getControllerService("awsCredentialsProvider"); + assertNotNull(service); + final AwsCredentialsProvider credentialsProvider = service.getAwsCredentialsProvider(); + assertNotNull(credentialsProvider); + assertEquals(DefaultCredentialsProvider.class, + credentialsProvider.getClass(), "credentials provider should be equal"); + } } diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/pom.xml b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/pom.xml index 941adc3bd4..aaf46c2f69 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/pom.xml +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/pom.xml @@ -28,6 +28,10 @@ com.amazonaws aws-java-sdk-core + + software.amazon.awssdk + auth + com.amazonaws aws-java-sdk-s3 diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/AwsCredentialsProviderService.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/AwsCredentialsProviderService.java new file mode 100644 index 0000000000..27aec26f7e --- /dev/null +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/AwsCredentialsProviderService.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.processors.aws.credentials.provider; + +import org.apache.nifi.annotation.documentation.CapabilityDescription; +import org.apache.nifi.annotation.documentation.Tags; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.processor.exception.ProcessException; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; + +/** + * AwsCredentialsProviderService interface to support getting AwsCredentialsProvider used for instantiating + * aws clients using the v2 SDK. + * + * @see AwsCredentialsProvider + */ +@Tags({"aws", "v2", "security", "credentials", "provider", "session"}) +@CapabilityDescription("Provides AwsCredentialsProvider.") +public interface AwsCredentialsProviderService extends ControllerService { + + /** + * Get credentials provider for Java SDK v2 + * @return credentials provider + * @throws ProcessException process exception in case there is problem in getting credentials provider + * + * @see AwsCredentialsProvider + */ + AwsCredentialsProvider getAwsCredentialsProvider(); +} diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderService.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderService.java index 6b2e165859..c3d0b3e2de 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderService.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-service-api/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderService.java @@ -16,12 +16,11 @@ */ package org.apache.nifi.processors.aws.credentials.provider.service; +import com.amazonaws.auth.AWSCredentialsProvider; import org.apache.nifi.annotation.documentation.CapabilityDescription; import org.apache.nifi.annotation.documentation.Tags; -import org.apache.nifi.controller.ControllerService; import org.apache.nifi.processor.exception.ProcessException; - -import com.amazonaws.auth.AWSCredentialsProvider; +import org.apache.nifi.processors.aws.credentials.provider.AwsCredentialsProviderService; /** * AWSCredentialsProviderService interface to support getting AWSCredentialsProvider used for instantiating @@ -31,10 +30,10 @@ import com.amazonaws.auth.AWSCredentialsProvider; */ @Tags({"aws", "security", "credentials", "provider", "session"}) @CapabilityDescription("Provides AWSCredentialsProvider.") -public interface AWSCredentialsProviderService extends ControllerService { +public interface AWSCredentialsProviderService extends AwsCredentialsProviderService { /** - * Get credentials provider + * Get credentials provider for Java SDK v1 * @return credentials provider * @throws ProcessException process exception in case there is problem in getting credentials provider *