You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by js...@apache.org on 2016/05/24 04:25:58 UTC
nifi git commit: NIFI-786 AWS credential refactoring and enhancements
Repository: nifi
Updated Branches:
refs/heads/0.x 718212aac -> de7ecd719
NIFI-786 AWS credential refactoring and enhancements
Signed-off-by: Joe Skora <js...@gmail.com>
This closes #244.
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/de7ecd71
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/de7ecd71
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/de7ecd71
Branch: refs/heads/0.x
Commit: de7ecd719a2e9907042628ea3a8283cfe2d4fbac
Parents: 718212a
Author: James Wing <jv...@gmail.com>
Authored: Mon Feb 22 10:14:47 2016 -0800
Committer: Joe Skora <js...@gmail.com>
Committed: Tue May 24 00:23:04 2016 -0400
----------------------------------------------------------------------
.../processors/aws/AbstractAWSProcessor.java | 26 +--
.../factory/CredentialPropertyDescriptors.java | 158 +++++++++++++++
.../factory/CredentialsProviderFactory.java | 125 ++++++++++++
.../provider/factory/CredentialsStrategy.java | 75 +++++++
.../AbstractBooleanCredentialsStrategy.java | 70 +++++++
.../strategies/AbstractCredentialsStrategy.java | 101 ++++++++++
.../AccessKeyPairCredentialsStrategy.java | 52 +++++
.../AnonymousCredentialsStrategy.java | 47 +++++
.../AssumeRoleCredentialsStrategy.java | 128 ++++++++++++
.../ExplicitDefaultCredentialsStrategy.java | 46 +++++
.../strategies/FileCredentialsStrategy.java | 53 +++++
.../ImplicitDefaultCredentialsStrategy.java | 43 ++++
.../NamedProfileCredentialsStrategy.java | 48 +++++
...AWSCredentialsProviderControllerService.java | 137 +++----------
.../provider/factory/MockAWSProcessor.java | 104 ++++++++++
.../factory/TestCredentialsProviderFactory.java | 201 +++++++++++++++++++
16 files changed, 1283 insertions(+), 131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAWSProcessor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAWSProcessor.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAWSProcessor.java
index e2c2196..3d4e458 100644
--- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAWSProcessor.java
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAWSProcessor.java
@@ -41,6 +41,7 @@ import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors;
import org.apache.nifi.ssl.SSLContextService;
import com.amazonaws.AmazonWebServiceClient;
@@ -72,28 +73,9 @@ public abstract class AbstractAWSProcessor<ClientType extends AmazonWebServiceCl
public static final Set<Relationship> relationships = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(REL_SUCCESS, REL_FAILURE)));
- public static final PropertyDescriptor CREDENTIALS_FILE = new PropertyDescriptor.Builder()
- .name("Credentials File")
- .expressionLanguageSupported(false)
- .required(false)
- .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
- .build();
-
- public static final PropertyDescriptor ACCESS_KEY = new PropertyDescriptor.Builder()
- .name("Access Key")
- .expressionLanguageSupported(true)
- .required(false)
- .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
- .sensitive(true)
- .build();
-
- public static final PropertyDescriptor SECRET_KEY = new PropertyDescriptor.Builder()
- .name("Secret Key")
- .expressionLanguageSupported(true)
- .required(false)
- .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
- .sensitive(true)
- .build();
+ public static final PropertyDescriptor CREDENTIALS_FILE = CredentialPropertyDescriptors.CREDENTIALS_FILE;
+ public static final PropertyDescriptor ACCESS_KEY = CredentialPropertyDescriptors.ACCESS_KEY;
+ public static final PropertyDescriptor SECRET_KEY = CredentialPropertyDescriptors.SECRET_KEY;
public static final PropertyDescriptor PROXY_HOST = new PropertyDescriptor.Builder()
.name("Proxy Host")
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java
new file mode 100644
index 0000000..04330ab
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialPropertyDescriptors.java
@@ -0,0 +1,158 @@
+/*
+ * 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.factory;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.processor.util.StandardValidators;
+
+/**
+ * Shared definitions of properties that specify various AWS credentials.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/credentials.html">
+ * Providing AWS Credentials in the AWS SDK for Java</a>
+ */
+public class CredentialPropertyDescriptors {
+
+ /**
+ * Specifies use of the Default Credential Provider Chain
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/credentials.html#id1">
+ * AWS SDK: Default Credential Provider Chain
+ * </a>
+ */
+ public static final PropertyDescriptor USE_DEFAULT_CREDENTIALS = new PropertyDescriptor.Builder()
+ .name("default-credentials")
+ .displayName("Use Default Credentials")
+ .expressionLanguageSupported(false)
+ .required(false)
+ .addValidator(StandardValidators.BOOLEAN_VALIDATOR)
+ .sensitive(false)
+ .allowableValues("true", "false")
+ .defaultValue("false")
+ .description("If true, uses the Default Credential chain, including EC2 instance profiles or roles, " +
+ "environment variables, default user credentials, etc.")
+ .build();
+
+ public static final PropertyDescriptor CREDENTIALS_FILE = new PropertyDescriptor.Builder()
+ .name("Credentials File")
+ .displayName("Credentials File")
+ .expressionLanguageSupported(false)
+ .required(false)
+ .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
+ .description("Path to a file containing AWS access key and secret key in properties file format.")
+ .build();
+
+ public static final PropertyDescriptor ACCESS_KEY = new PropertyDescriptor.Builder()
+ .name("Access Key")
+ .displayName("Access Key")
+ .expressionLanguageSupported(true)
+ .required(false)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(true)
+ .build();
+
+ public static final PropertyDescriptor SECRET_KEY = new PropertyDescriptor.Builder()
+ .name("Secret Key")
+ .displayName("Secret Key")
+ .expressionLanguageSupported(true)
+ .required(false)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(true)
+ .build();
+
+ /**
+ * Specifies use of a named profile credential.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/profile/ProfileCredentialsProvider.html">
+ * ProfileCredentialsProvider</a>
+ */
+ public static final PropertyDescriptor PROFILE_NAME = new PropertyDescriptor.Builder()
+ .name("profile-name")
+ .displayName("Profile Name")
+ .expressionLanguageSupported(true)
+ .required(false)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(false)
+ .description("The AWS profile name for credentials from the profile configuration file.")
+ .build();
+
+ public static final PropertyDescriptor USE_ANONYMOUS_CREDENTIALS = new PropertyDescriptor.Builder()
+ .name("anonymous-credentials")
+ .displayName("Use Anonymous Credentials")
+ .expressionLanguageSupported(false)
+ .required(false)
+ .addValidator(StandardValidators.BOOLEAN_VALIDATOR)
+ .sensitive(false)
+ .allowableValues("true", "false")
+ .defaultValue("false")
+ .description("If true, uses Anonymous credentials")
+ .build();
+
+ /**
+ * AWS Role Arn used for cross account access
+ *
+ * @see <a href="http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-arns">AWS ARN</a>
+ */
+ public static final PropertyDescriptor ASSUME_ROLE_ARN = new PropertyDescriptor.Builder()
+ .name("Assume Role ARN")
+ .displayName("Assume Role ARN")
+ .expressionLanguageSupported(false)
+ .required(false)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(false)
+ .description("The AWS Role ARN for cross account access. This is used in conjunction with role name and session timeout")
+ .build();
+
+ /**
+ * The role name while creating aws role
+ */
+ public static final PropertyDescriptor ASSUME_ROLE_NAME = new PropertyDescriptor.Builder()
+ .name("Assume Role Session Name")
+ .displayName("Assume Role Session Name")
+ .expressionLanguageSupported(false)
+ .required(false)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(false)
+ .description("The AWS Role Name for cross account access. This is used in conjunction with role ARN and session time out")
+ .build();
+
+ /**
+ * Max session time for role based credentials. The range is between 900 and 3600 seconds.
+ */
+ public static final PropertyDescriptor MAX_SESSION_TIME = new PropertyDescriptor.Builder()
+ .name("Session Time")
+ .description("Session time for role based session (between 900 and 3600 seconds). This is used in conjunction with role ARN and name")
+ .defaultValue("3600")
+ .required(false)
+ .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+ .sensitive(false)
+ .build();
+
+ /**
+ * The ExternalId used while creating aws role.
+ */
+ public static final PropertyDescriptor ASSUME_ROLE_EXTERNAL_ID = new PropertyDescriptor.Builder()
+ .name("assume-role-external-id")
+ .displayName("Assume Role External ID")
+ .expressionLanguageSupported(false)
+ .required(false)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(false)
+ .description("External ID for cross-account access. This is used in conjunction with role arn, " +
+ "role name, and optional session time out")
+ .build();
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsProviderFactory.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..94f0410
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsProviderFactory.java
@@ -0,0 +1,125 @@
+/*
+ * 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.factory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+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.strategies.ExplicitDefaultCredentialsStrategy;
+import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.AccessKeyPairCredentialsStrategy;
+import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.FileCredentialsStrategy;
+import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.NamedProfileCredentialsStrategy;
+import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.AnonymousCredentialsStrategy;
+import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.ImplicitDefaultCredentialsStrategy;
+import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.AssumeRoleCredentialsStrategy;
+
+import com.amazonaws.auth.AWSCredentialsProvider;
+
+
+/**
+ * Generates AWS credentials in the form of AWSCredentialsProvider implementations for processors
+ * and controller services. The factory supports a number of strategies for specifying and validating
+ * AWS credentials, interpreted as an ordered list of most-preferred to least-preferred. It also supports
+ * derived credential strategies like Assume Role, which require a primary credential as an input.
+ *
+ * Additional strategies should implement CredentialsStrategy, then be added to the strategies list in the
+ * constructor.
+ *
+ * @see org.apache.nifi.processors.aws.credentials.provider.factory.strategies
+ */
+public class CredentialsProviderFactory {
+
+ private final List<CredentialsStrategy> strategies = new ArrayList<CredentialsStrategy>();
+
+ public CredentialsProviderFactory() {
+ // Primary Credential Strategies
+ strategies.add(new ExplicitDefaultCredentialsStrategy());
+ strategies.add(new AccessKeyPairCredentialsStrategy());
+ strategies.add(new FileCredentialsStrategy());
+ strategies.add(new NamedProfileCredentialsStrategy());
+ strategies.add(new AnonymousCredentialsStrategy());
+
+ // Implicit Default is the catch-all primary strategy
+ strategies.add(new ImplicitDefaultCredentialsStrategy());
+
+ // Derived Credential Strategies
+ strategies.add(new AssumeRoleCredentialsStrategy());
+ }
+
+ public CredentialsStrategy selectPrimaryStrategy(final Map<PropertyDescriptor, String> properties) {
+ for (CredentialsStrategy strategy : strategies) {
+ if (strategy.canCreatePrimaryCredential(properties)) {
+ return strategy;
+ }
+ }
+ return null;
+ }
+
+ public CredentialsStrategy selectPrimaryStrategy(final ValidationContext validationContext) {
+ final Map<PropertyDescriptor, String> properties = validationContext.getProperties();
+ return selectPrimaryStrategy(properties);
+ }
+
+ /**
+ * Validates AWS credential properties against the configured strategies to report any validation errors.
+ * @return Validation errors
+ */
+ public Collection<ValidationResult> validate(final ValidationContext validationContext) {
+ final CredentialsStrategy selectedStrategy = selectPrimaryStrategy(validationContext);
+ final ArrayList<ValidationResult> validationFailureResults = new ArrayList<ValidationResult>();
+
+ for (CredentialsStrategy strategy : strategies) {
+ final Collection<ValidationResult> strategyValidationFailures = strategy.validate(validationContext,
+ selectedStrategy);
+ if (strategyValidationFailures != null) {
+ validationFailureResults.addAll(strategyValidationFailures);
+ }
+ }
+
+ return validationFailureResults;
+ }
+
+ /**
+ * Produces the AWSCredentialsProvider according to the given property set and the strategies configured in
+ * the factory.
+ * @return AWSCredentialsProvider implementation
+ */
+ public AWSCredentialsProvider getCredentialsProvider(final Map<PropertyDescriptor, String> properties) {
+ final CredentialsStrategy primaryStrategy = selectPrimaryStrategy(properties);
+ AWSCredentialsProvider primaryCredentialsProvider = primaryStrategy.getCredentialsProvider(properties);
+ AWSCredentialsProvider derivedCredentialsProvider = null;
+
+ for (CredentialsStrategy strategy : strategies) {
+ if (strategy.canCreateDerivedCredential(properties)) {
+ derivedCredentialsProvider = strategy.getDerivedCredentialsProvider(properties,
+ primaryCredentialsProvider);
+ break;
+ }
+ }
+
+ if (derivedCredentialsProvider != null) {
+ return derivedCredentialsProvider;
+ } else {
+ return primaryCredentialsProvider;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..d5d93a7
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/CredentialsStrategy.java
@@ -0,0 +1,75 @@
+/*
+ * 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.factory;
+
+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 com.amazonaws.auth.AWSCredentialsProvider;
+
+
+/**
+ * Specifies a strategy for validating and creating AWS credentials from a list of properties configured on a
+ * Processor, Controller Service, Reporting Service, or other component. Supports both primary credentials like
+ * default credentials or API keys and also derived credentials from Assume Role.
+ */
+public interface CredentialsStrategy {
+
+ /**
+ * Name of the strategy, suitable for displaying to a user in validation messages.
+ * @return strategy name
+ */
+ String getName();
+
+ /**
+ * Determines if this strategy can create primary credentials using the given properties.
+ * @return true if primary credentials can be created
+ */
+ boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> properties);
+
+ /**
+ * Determines if this strategy can create derived credentials using the given properties.
+ * @return true if derived credentials can be created
+ */
+ boolean canCreateDerivedCredential(Map<PropertyDescriptor, String> properties);
+
+ /**
+ * Validates the properties belonging to this strategy, given the selected primary strategy. Errors may result
+ * from individually malformed properties, invalid combinations of properties, or inappropriate use of properties
+ * not consistent with the primary strategy.
+ * @param primaryStrategy the prevailing primary strategy
+ * @return validation errors
+ */
+ Collection<ValidationResult> validate(ValidationContext validationContext, CredentialsStrategy primaryStrategy);
+
+ /**
+ * Creates an AWSCredentialsProvider instance for this strategy, given the properties defined by the user.
+ */
+ AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties);
+
+ /**
+ * Creates an AWSCredentialsProvider instance for this strategy, given the properties defined by the user and
+ * the AWSCredentialsProvider from the winning primary strategy.
+ */
+ AWSCredentialsProvider getDerivedCredentialsProvider(Map<PropertyDescriptor, String> properties,
+ AWSCredentialsProvider primaryCredentialsProvider);
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractBooleanCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..2c5b9a3
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractBooleanCredentialsStrategy.java
@@ -0,0 +1,70 @@
+/*
+ * 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.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 org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy;
+
+
+/**
+ * Partial implementation of CredentialsStrategy to provide support for credential strategies specified by
+ * a single boolean property.
+ */
+public abstract class AbstractBooleanCredentialsStrategy extends AbstractCredentialsStrategy {
+
+ private PropertyDescriptor strategyProperty;
+
+ public AbstractBooleanCredentialsStrategy(String name, PropertyDescriptor strategyProperty) {
+ super("Default Credentials", new PropertyDescriptor[]{
+ strategyProperty
+ });
+ this.strategyProperty = strategyProperty;
+ }
+
+ @Override
+ public boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> properties) {
+ String useStrategyString = properties.get(strategyProperty);
+ Boolean useStrategy = Boolean.parseBoolean(useStrategyString);
+ return useStrategy;
+ }
+
+ @Override
+ public Collection<ValidationResult> validate(final ValidationContext validationContext,
+ final CredentialsStrategy primaryStrategy) {
+ boolean thisIsSelectedStrategy = this == primaryStrategy;
+ Boolean useStrategy = validationContext.getProperty(strategyProperty).asBoolean();
+ if (!thisIsSelectedStrategy && useStrategy) {
+ String failureFormat = "property %1$s cannot be used with %2$s";
+ Collection<ValidationResult> validationFailureResults = new ArrayList<ValidationResult>();
+ String message = String.format(failureFormat, strategyProperty.getDisplayName(),
+ primaryStrategy.getName());
+ validationFailureResults.add(new ValidationResult.Builder()
+ .subject(strategyProperty.getDisplayName())
+ .valid(false)
+ .explanation(message).build());
+ return validationFailureResults;
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..29f1000
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AbstractCredentialsStrategy.java
@@ -0,0 +1,101 @@
+/*
+ * 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.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 org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy;
+
+import com.amazonaws.auth.AWSCredentialsProvider;
+
+
+/**
+ * Partial implementation of CredentialsStrategy to support most simple property-based strategies.
+ */
+public abstract class AbstractCredentialsStrategy implements CredentialsStrategy {
+ private final String name;
+ private final PropertyDescriptor[] requiredProperties;
+
+ public AbstractCredentialsStrategy(String name, PropertyDescriptor[] requiredProperties) {
+ this.name = name;
+ this.requiredProperties = requiredProperties;
+ }
+
+ @Override
+ public boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> properties) {
+ for (PropertyDescriptor requiredProperty : requiredProperties) {
+ boolean containsRequiredProperty = properties.containsKey(requiredProperty);
+ String propertyValue = properties.get(requiredProperty);
+ boolean containsValue = propertyValue != null;
+ if (!containsRequiredProperty || !containsValue) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public Collection<ValidationResult> 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;
+ Collection<ValidationResult> validationFailureResults = null;
+
+ for (PropertyDescriptor requiredProperty : requiredProperties) {
+ boolean requiredPropertyIsSet = validationContext.getProperty(requiredProperty).isSet();
+ if (requiredPropertyIsSet != thisIsSelectedStrategy) {
+ String message = String.format(failureFormat, requiredProperty.getDisplayName(),
+ primaryStrategy.getName());
+ if (validationFailureResults == null) {
+ validationFailureResults = new ArrayList<ValidationResult>();
+ }
+ validationFailureResults.add(new ValidationResult.Builder()
+ .subject(requiredProperty.getDisplayName())
+ .valid(false)
+ .explanation(message).build());
+ }
+ }
+
+ return validationFailureResults;
+ }
+
+ public abstract AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties);
+
+ public String getName() {
+ return name;
+ }
+
+
+ @Override
+ public boolean canCreateDerivedCredential(Map<PropertyDescriptor, String> properties) {
+ return false;
+ }
+
+ @Override
+ public AWSCredentialsProvider getDerivedCredentialsProvider(Map<PropertyDescriptor, String> properties,
+ AWSCredentialsProvider primaryCredentialsProvider) {
+ throw new UnsupportedOperationException();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AccessKeyPairCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..5cf8869
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AccessKeyPairCredentialsStrategy.java
@@ -0,0 +1,52 @@
+/*
+ * 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.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;
+
+
+/**
+ * Supports AWS credentials defined by an Access Key and Secret Key pair.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/BasicAWSCredentials.html">
+ * BasicAWSCredentials</a>
+ */
+public class AccessKeyPairCredentialsStrategy extends AbstractCredentialsStrategy {
+
+ public AccessKeyPairCredentialsStrategy() {
+ super("Access Key Pair", new PropertyDescriptor[] {
+ CredentialPropertyDescriptors.ACCESS_KEY,
+ CredentialPropertyDescriptors.SECRET_KEY
+ });
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> 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);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AnonymousCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..4f8368e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AnonymousCredentialsStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * 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.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;
+
+
+/**
+ * Supports Anonymous AWS credentials.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/AnonymousAWSCredentials.html">
+ * AnonymousAWSCredentials</a>
+ */
+public class AnonymousCredentialsStrategy extends AbstractBooleanCredentialsStrategy {
+
+ public AnonymousCredentialsStrategy() {
+ super("Anonymous Credentials", CredentialPropertyDescriptors.USE_ANONYMOUS_CREDENTIALS);
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties) {
+ AnonymousAWSCredentials creds = new AnonymousAWSCredentials();
+ return new StaticCredentialsProvider(creds);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..186a97b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java
@@ -0,0 +1,128 @@
+/*
+ * 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.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_NAME;
+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_EXTERNAL_ID;
+import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy;
+
+import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
+
+
+/**
+ * Supports AWS credentials via Assume Role. Assume Role is a derived credential strategy, requiring a primary
+ * credential to retrieve and periodically refresh temporary credentials.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/STSAssumeRoleSessionCredentialsProvider.html">
+ * STSAssumeRoleCredentialsProvider</a>
+ */
+public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy {
+
+ public AssumeRoleCredentialsStrategy() {
+ super("Assume Role", new PropertyDescriptor[] {
+ ASSUME_ROLE_ARN,
+ ASSUME_ROLE_NAME,
+ MAX_SESSION_TIME,
+ });
+ }
+
+ @Override
+ public boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> properties) {
+ return false;
+ }
+
+ @Override
+ public boolean canCreateDerivedCredential(Map<PropertyDescriptor, String> properties) {
+ final String assumeRoleArn = properties.get(ASSUME_ROLE_ARN);
+ final String assumeRoleName = properties.get(ASSUME_ROLE_NAME);
+ if (assumeRoleArn != null && !assumeRoleArn.isEmpty()
+ && assumeRoleName != null && !assumeRoleName.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Collection<ValidationResult> validate(final ValidationContext validationContext,
+ final CredentialsStrategy primaryStrategy) {
+ final boolean assumeRoleArnIsSet = validationContext.getProperty(ASSUME_ROLE_ARN).isSet();
+ final boolean assumeRoleNameIsSet = validationContext.getProperty(ASSUME_ROLE_NAME).isSet();
+ final Integer maxSessionTime = validationContext.getProperty(MAX_SESSION_TIME).asInteger();
+ final boolean assumeRoleExternalIdIsSet = validationContext.getProperty(ASSUME_ROLE_EXTERNAL_ID).isSet();
+
+ final Collection<ValidationResult> validationFailureResults = new ArrayList<ValidationResult>();
+
+ // Both role and arn name are req if present
+ if (assumeRoleArnIsSet ^ assumeRoleNameIsSet ) {
+ validationFailureResults.add(new ValidationResult.Builder().input("Assume Role Arn and Name")
+ .valid(false).explanation("Assume role requires both arn and name to be set").build());
+ }
+
+ // Session time only b/w 900 to 3600 sec (see sts session class)
+ if ( maxSessionTime < 900 || maxSessionTime > 3600 )
+ validationFailureResults.add(new ValidationResult.Builder().valid(false).input(maxSessionTime + "")
+ .explanation(MAX_SESSION_TIME.getDisplayName() +
+ " must be between 900 and 3600 seconds").build());
+
+ // External ID should only be provided with viable Assume Role ARN and Name
+ if (assumeRoleExternalIdIsSet && (!assumeRoleArnIsSet || !assumeRoleNameIsSet)) {
+ validationFailureResults.add(new ValidationResult.Builder().input("Assume Role External ID")
+ .valid(false)
+ .explanation("Assume role requires both arn and name to be set with External ID")
+ .build());
+ }
+
+ return validationFailureResults;
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AWSCredentialsProvider getDerivedCredentialsProvider(Map<PropertyDescriptor, String> 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) ? rawMaxSessionTime : MAX_SESSION_TIME.getDefaultValue();
+ final Integer maxSessionTime = Integer.parseInt(rawMaxSessionTime.trim());
+ final String assumeRoleExternalId = properties.get(ASSUME_ROLE_EXTERNAL_ID);
+
+ STSAssumeRoleSessionCredentialsProvider.Builder builder = new STSAssumeRoleSessionCredentialsProvider
+ .Builder(assumeRoleArn, assumeRoleName)
+ .withLongLivedCredentialsProvider(primaryCredentialsProvider)
+ .withRoleSessionDurationSeconds(maxSessionTime);
+ if (assumeRoleExternalId != null && !assumeRoleExternalId.isEmpty()) {
+ builder = builder.withExternalId(assumeRoleExternalId);
+ }
+ final AWSCredentialsProvider credsProvider = builder.build();
+
+ return credsProvider;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ExplicitDefaultCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..a8ac2e8
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ExplicitDefaultCredentialsStrategy.java
@@ -0,0 +1,46 @@
+/*
+ * 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.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.DefaultAWSCredentialsProviderChain;
+
+
+/**
+ * Supports AWS Default Credentials. Compared to ImplicitDefaultCredentialsStrategy, this strategy is designed to be
+ * visible to the user, and depends on an affirmative selection from the user.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html">
+ * DefaultAWSCredentialsProviderChain</a>
+ */
+public class ExplicitDefaultCredentialsStrategy extends AbstractBooleanCredentialsStrategy {
+
+ public ExplicitDefaultCredentialsStrategy() {
+ super("Default Credentials", CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS);
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties) {
+ return new DefaultAWSCredentialsProviderChain();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/FileCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..7fdf93b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/FileCredentialsStrategy.java
@@ -0,0 +1,53 @@
+/*
+ * 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.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;
+
+
+/**
+ * Supports AWS credentials stored in a file. The file format should be a Java properties file like the following:
+ *
+ * <code>
+ * accessKey = XXXXXXXXXXXXXXXXXXXX
+ * secretKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ * </code>
+ *
+ * * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/PropertiesFileCredentialsProvider.html">
+ * PropertiesFileCredentialsProvider</a>
+ */
+public class FileCredentialsStrategy extends AbstractCredentialsStrategy {
+
+ public FileCredentialsStrategy() {
+ super("Credentials File", new PropertyDescriptor[] {
+ CredentialPropertyDescriptors.CREDENTIALS_FILE
+ });
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties) {
+ String credsFile = properties.get(CredentialPropertyDescriptors.CREDENTIALS_FILE);
+ return new PropertiesFileCredentialsProvider(credsFile);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ImplicitDefaultCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..d9717b3
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/ImplicitDefaultCredentialsStrategy.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.factory.strategies;
+
+import java.util.Map;
+
+import org.apache.nifi.components.PropertyDescriptor;
+
+import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
+
+
+/**
+ * Supports AWS Default Credentials. Compared to ExplicitDefaultCredentialsStrategy, this strategy is always
+ * willing to provide primary credentials, regardless of user input. It is intended to be used as an invisible
+ * fallback or default strategy.
+ */
+public class ImplicitDefaultCredentialsStrategy extends AbstractCredentialsStrategy {
+
+ public ImplicitDefaultCredentialsStrategy() {
+ super("Default Credentials", new PropertyDescriptor[]{});
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties) {
+ return new DefaultAWSCredentialsProviderChain();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/NamedProfileCredentialsStrategy.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..294f2ed
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/NamedProfileCredentialsStrategy.java
@@ -0,0 +1,48 @@
+/*
+ * 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.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.profile.ProfileCredentialsProvider;
+
+
+/**
+ * Supports AWS Credentials using a named profile configured in the credentials file (typically ~/.aws/credentials).
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/profile/ProfileCredentialsProvider.html">
+ * ProfileCredentialsProvider</a>
+ */
+public class NamedProfileCredentialsStrategy extends AbstractCredentialsStrategy {
+
+ public NamedProfileCredentialsStrategy() {
+ super("Named Profile", new PropertyDescriptor[] {
+ CredentialPropertyDescriptors.PROFILE_NAME
+ });
+ }
+
+ @Override
+ public AWSCredentialsProvider getCredentialsProvider(Map<PropertyDescriptor, String> properties) {
+ String profileName = properties.get(CredentialPropertyDescriptors.PROFILE_NAME);
+ return new ProfileCredentialsProvider(profileName);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/service/AWSCredentialsProviderControllerService.java
----------------------------------------------------------------------
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 ecc64e2..7c09bd4 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
@@ -15,10 +15,12 @@
* limitations under the License.
*/
package org.apache.nifi.processors.aws.credentials.provider.service;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
@@ -29,72 +31,55 @@ import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.processor.exception.ProcessException;
-import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors;
+import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsProviderFactory;
import org.apache.nifi.reporting.InitializationException;
-import static org.apache.nifi.processors.aws.AbstractAWSProcessor.ACCESS_KEY;
-import static org.apache.nifi.processors.aws.AbstractAWSProcessor.SECRET_KEY;
-import static org.apache.nifi.processors.aws.AbstractAWSProcessor.CREDENTIALS_FILE;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ACCESS_KEY;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.SECRET_KEY;
+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;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.USE_ANONYMOUS_CREDENTIALS;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_EXTERNAL_ID;
import com.amazonaws.auth.AWSCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
-import com.amazonaws.auth.PropertiesFileCredentialsProvider;
-import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
-import com.amazonaws.internal.StaticCredentialsProvider;
/**
* Implementation of AWSCredentialsProviderService interface
*
* @see AWSCredentialsProviderService
*/
-@CapabilityDescription("Defines credentials for Amazon Web Services processors.")
+@CapabilityDescription("Defines credentials for Amazon Web Services processors. " +
+ "Uses default credentials without configuration. " +
+ "Default credentials support EC2 instance profile/role, default user profile, environment variables, etc. " +
+ "Additional options include access key / secret key pairs, credentials file, named profile, and assume role credentials.")
@Tags({ "aws", "credentials","provider" })
public class AWSCredentialsProviderControllerService extends AbstractControllerService implements AWSCredentialsProviderService {
- /**
- * AWS Role Arn used for cross account access
- *
- * @see <a href="http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-arns">AWS ARN</a>
- */
- public static final PropertyDescriptor ASSUME_ROLE_ARN = new PropertyDescriptor.Builder().name("Assume Role ARN")
- .expressionLanguageSupported(false).required(false).addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
- .sensitive(false).description("The AWS Role ARN for cross account access. This is used in conjunction with role name and session timeout").build();
-
- /**
- * The role name while creating aws role
- */
- public static final PropertyDescriptor ASSUME_ROLE_NAME = new PropertyDescriptor.Builder().name("Assume Role Session Name")
- .expressionLanguageSupported(false).required(false).addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
- .sensitive(false).description("The aws role name for cross account access. This is used in conjunction with role arn and session time out").build();
-
- /**
- * Max session time for role based credentials. The range is between 900 and 3600 seconds.
- */
- public static final PropertyDescriptor MAX_SESSION_TIME = new PropertyDescriptor.Builder()
- .name("Session Time")
- .description("Session time for role based session (between 900 and 3600 seconds). This is used in conjunction with role arn and name")
- .defaultValue("3600")
- .required(false)
- .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
- .sensitive(false)
- .build();
+ 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;
private static final List<PropertyDescriptor> properties;
static {
final List<PropertyDescriptor> props = new ArrayList<>();
+ props.add(USE_DEFAULT_CREDENTIALS);
props.add(ACCESS_KEY);
props.add(SECRET_KEY);
props.add(CREDENTIALS_FILE);
+ props.add(PROFILE_NAME);
+ props.add(USE_ANONYMOUS_CREDENTIALS);
props.add(ASSUME_ROLE_ARN);
props.add(ASSUME_ROLE_NAME);
props.add(MAX_SESSION_TIME);
-
+ props.add(ASSUME_ROLE_EXTERNAL_ID);
properties = Collections.unmodifiableList(props);
}
private volatile AWSCredentialsProvider credentialsProvider;
+ protected final CredentialsProviderFactory credentialsProviderFactory = new CredentialsProviderFactory();
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
@@ -108,82 +93,16 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS
@Override
protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) {
-
- final boolean accessKeySet = validationContext.getProperty(ACCESS_KEY).isSet();
- final boolean secretKeySet = validationContext.getProperty(SECRET_KEY).isSet();
- final boolean assumeRoleArnIsSet = validationContext.getProperty(ASSUME_ROLE_ARN).isSet();
- final boolean assumeRoleNameIsSet = validationContext.getProperty(ASSUME_ROLE_NAME).isSet();
- final Integer maxSessionTime = validationContext.getProperty(MAX_SESSION_TIME).asInteger();
-
- final boolean credentialsFileSet = validationContext.getProperty(CREDENTIALS_FILE).isSet();
-
- final Collection<ValidationResult> validationFailureResults = new ArrayList<>();
-
- // both keys are required if present
- if ((accessKeySet && !secretKeySet) || (secretKeySet && !accessKeySet)) {
- validationFailureResults.add(new ValidationResult.Builder().input("Access Key").valid(false)
- .explanation("If setting Secret Key or Access Key, must set both").build());
- }
-
- // Either keys or creds file is valid
- if ((secretKeySet || accessKeySet) && credentialsFileSet) {
- validationFailureResults.add(new ValidationResult.Builder().input("Access Key").valid(false)
- .explanation("Cannot set both Credentials File and Secret Key/Access Key").build());
- }
-
- // Both role and arn name are req if present
- if (assumeRoleArnIsSet ^ assumeRoleNameIsSet ) {
- validationFailureResults.add(new ValidationResult.Builder().input("Assume Role Arn and Name")
- .valid(false).explanation("Assume role requires both arn and name to be set").build());
- }
-
- // Session time only b/w 900 to 3600 sec (see sts session class)
- if ( maxSessionTime < 900 || maxSessionTime > 3600 )
- validationFailureResults.add(new ValidationResult.Builder().valid(false).input(maxSessionTime + "")
- .subject(MAX_SESSION_TIME.getDisplayName() +
- " can have value only between 900 and 3600 seconds").build());
-
+ final Collection<ValidationResult> validationFailureResults =
+ credentialsProviderFactory.validate(validationContext);
return validationFailureResults;
}
@OnEnabled
public void onConfigured(final ConfigurationContext context) throws InitializationException {
-
- final String accessKey = context.getProperty(ACCESS_KEY).evaluateAttributeExpressions().getValue();
- final String secretKey = context.getProperty(SECRET_KEY).evaluateAttributeExpressions().getValue();
- final String assumeRoleArn = context.getProperty(ASSUME_ROLE_ARN).getValue();
- final Integer maxSessionTime = context.getProperty(MAX_SESSION_TIME).asInteger();
- final String assumeRoleName = context.getProperty(ASSUME_ROLE_NAME).getValue();
- final String credentialsFile = context.getProperty(CREDENTIALS_FILE).getValue();
-
- // Create creds provider from file or keys
- if (credentialsFile != null) {
- try {
- getLogger().debug("Creating properties file credentials provider");
- credentialsProvider = new PropertiesFileCredentialsProvider(credentialsFile);
- } catch (final Exception ioe) {
- throw new ProcessException("Could not read Credentials File", ioe);
- }
- }
-
- if (credentialsProvider == null && accessKey != null && secretKey != null) {
- getLogger().debug("Creating static credentials provider");
- credentialsProvider = new StaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey));
- }
-
- // If no credentials explicitly provided, then create default one
- if (credentialsProvider == null) {
- getLogger().debug("Creating default credentials provider");
- credentialsProvider = new DefaultAWSCredentialsProviderChain();
- }
-
- if (credentialsProvider != null && assumeRoleArn != null && assumeRoleName != null) {
- getLogger().debug("Creating sts assume role session credentials provider");
-
- credentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(assumeRoleArn, assumeRoleName)
- .withLongLivedCredentialsProvider(credentialsProvider)
- .withRoleSessionDurationSeconds(maxSessionTime).build();
- }
+ final Map<PropertyDescriptor, String> properties = context.getProperties();
+ credentialsProvider = credentialsProviderFactory.getCredentialsProvider(context.getProperties());
+ getLogger().debug("Using credentials provider: " + credentialsProvider.getClass());
}
@Override
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..d76db53
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java
@@ -0,0 +1,104 @@
+/*
+ * 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.factory;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.auth.AWSCredentials;
+import com.amazonaws.services.s3.AmazonS3Client;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.PROFILE_NAME;
+import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.USE_ANONYMOUS_CREDENTIALS;
+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_NAME;
+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_EXTERNAL_ID;
+
+import com.amazonaws.auth.AWSCredentialsProvider;
+import org.apache.nifi.processors.aws.AbstractAWSCredentialsProviderProcessor;
+
+
+/**
+ * Mock Processor implementation used to test CredentialsProviderFactory.
+ */
+public class MockAWSProcessor extends AbstractAWSCredentialsProviderProcessor<AmazonS3Client> {
+
+ public final List<PropertyDescriptor> properties = Arrays.asList(
+ USE_DEFAULT_CREDENTIALS,
+ ACCESS_KEY,
+ SECRET_KEY,
+ CREDENTIALS_FILE,
+ PROFILE_NAME,
+ USE_ANONYMOUS_CREDENTIALS,
+ ASSUME_ROLE_ARN,
+ ASSUME_ROLE_NAME,
+ MAX_SESSION_TIME,
+ ASSUME_ROLE_EXTERNAL_ID
+ );
+
+ @Override
+ protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+ return properties;
+ }
+
+ @Override
+ public void onTrigger(final ProcessContext context, final ProcessSession session) {
+
+ }
+
+ @Override
+ protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) {
+ CredentialsProviderFactory credsFactory = new CredentialsProviderFactory();
+ final Collection<ValidationResult> validationFailureResults = credsFactory.validate(validationContext);
+ return validationFailureResults;
+ }
+
+ /**
+ * Create client using credentials provider. This is the preferred way for creating clients
+ */
+ @Override
+ protected AmazonS3Client createClient(final ProcessContext context, final AWSCredentialsProvider credentialsProvider, final ClientConfiguration config) {
+ getLogger().info("Creating client with credentials provider");
+ final AmazonS3Client s3 = new AmazonS3Client(credentialsProvider, config);
+ return s3;
+ }
+
+ /**
+ * Create client using AWSCredentials
+ *
+ * @deprecated use {@link #createClient(ProcessContext, AWSCredentialsProvider, ClientConfiguration)} instead
+ */
+ @Override
+ protected AmazonS3Client createClient(final ProcessContext context, final AWSCredentials credentials, final ClientConfiguration config) {
+ getLogger().info("Creating client with awd credentials");
+
+ final AmazonS3Client s3 = new AmazonS3Client(credentials, config);
+
+ return s3;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/de7ecd71/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/TestCredentialsProviderFactory.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/TestCredentialsProviderFactory.java b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/TestCredentialsProviderFactory.java
new file mode 100644
index 0000000..ccdffe3
--- /dev/null
+++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/TestCredentialsProviderFactory.java
@@ -0,0 +1,201 @@
+/*
+ * 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.factory;
+
+import java.util.Map;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.processors.aws.s3.FetchS3Object;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+
+import com.amazonaws.auth.AnonymousAWSCredentials;
+import com.amazonaws.auth.AWSCredentials;
+import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
+import com.amazonaws.auth.PropertiesFileCredentialsProvider;
+import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
+import com.amazonaws.internal.StaticCredentialsProvider;
+
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests of the validation and credentials provider capabilities of CredentialsProviderFactory.
+ */
+public class TestCredentialsProviderFactory {
+
+ @Test
+ public void testImpliedDefaultCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ assertEquals("credentials provider should be equal", DefaultAWSCredentialsProviderChain.class,
+ credentialsProvider.getClass());
+ }
+
+ @Test
+ public void testExplicitDefaultCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS, "true");
+ runner.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ assertEquals("credentials provider should be equal", DefaultAWSCredentialsProviderChain.class,
+ credentialsProvider.getClass());
+ }
+
+ @Test
+ public void testExplicitDefaultCredentialsExclusive() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS, "true");
+ runner.setProperty(CredentialPropertyDescriptors.ACCESS_KEY, "BogusAccessKey");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testAccessKeyPairCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS, "false");
+ runner.setProperty(CredentialPropertyDescriptors.ACCESS_KEY, "BogusAccessKey");
+ runner.setProperty(CredentialPropertyDescriptors.SECRET_KEY, "BogusSecretKey");
+ runner.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ assertEquals("credentials provider should be equal", StaticCredentialsProvider.class,
+ credentialsProvider.getClass());
+ }
+
+ @Test
+ public void testAccessKeyPairIncomplete() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.ACCESS_KEY, "BogusAccessKey");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testAccessKeyPairIncompleteS3() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(FetchS3Object.class);
+ runner.setProperty(CredentialPropertyDescriptors.ACCESS_KEY, "BogusAccessKey");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testFileCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.CREDENTIALS_FILE, "src/test/resources/mock-aws-credentials.properties");
+ runner.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ assertEquals("credentials provider should be equal", PropertiesFileCredentialsProvider.class,
+ credentialsProvider.getClass());
+ }
+
+ @Test
+ public void testAssumeRoleCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ 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.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ assertEquals("credentials provider should be equal", STSAssumeRoleSessionCredentialsProvider.class,
+ credentialsProvider.getClass());
+ }
+
+ @Test
+ public void testAssumeRoleCredentialsMissingARN() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.CREDENTIALS_FILE, "src/test/resources/mock-aws-credentials.properties");
+ runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_NAME, "BogusSession");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testAssumeRoleCredentialsInvalidSessionTime() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ 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.MAX_SESSION_TIME, "10");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testAssumeRoleExternalIdMissingArnAndName() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.CREDENTIALS_FILE, "src/test/resources/mock-aws-credentials.properties");
+ runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_EXTERNAL_ID, "BogusExternalId");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testAnonymousCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.USE_ANONYMOUS_CREDENTIALS, "true");
+ runner.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ final AWSCredentials creds = credentialsProvider.getCredentials();
+ assertEquals("credentials should be equal", AnonymousAWSCredentials.class, creds.getClass());
+ }
+
+ @Test
+ public void testAnonymousAndDefaultCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS, "true");
+ runner.setProperty(CredentialPropertyDescriptors.USE_ANONYMOUS_CREDENTIALS, "true");
+ runner.assertNotValid();
+ }
+
+ @Test
+ public void testNamedProfileCredentials() throws Throwable {
+ final TestRunner runner = TestRunners.newTestRunner(MockAWSProcessor.class);
+ runner.setProperty(CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS, "false");
+ runner.setProperty(CredentialPropertyDescriptors.PROFILE_NAME, "BogusProfile");
+ runner.assertValid();
+
+ Map<PropertyDescriptor, String> properties = runner.getProcessContext().getProperties();
+ final CredentialsProviderFactory factory = new CredentialsProviderFactory();
+ final AWSCredentialsProvider credentialsProvider = factory.getCredentialsProvider(properties);
+ Assert.assertNotNull(credentialsProvider);
+ assertEquals("credentials provider should be equal", ProfileCredentialsProvider.class,
+ credentialsProvider.getClass());
+ }
+}