NIFI-786 AWS credential refactoring and enhancements

Signed-off-by: Joe Skora <jskora@gmail.com>
This closes #244.
This commit is contained in:
James Wing 2016-02-22 10:14:47 -08:00 committed by Joe Skora
parent 4dd50c80a4
commit 9bb6dcb5e5
16 changed files with 1283 additions and 131 deletions

View File

@ -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")

View File

@ -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();
}

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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());
}
}