Repository: nifi Updated Branches: refs/heads/master 979b4d8ab -> 6dc2f1419
NIFI-2799 AWS Assume Role Credentials With Proxy This closes #1112. Signed-off-by: James Wing <jvw...@gmail.com> Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/6dc2f141 Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/6dc2f141 Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/6dc2f141 Branch: refs/heads/master Commit: 6dc2f14198bb475ace8e762e348ca5294400cccb Parents: 979b4d8 Author: Keren Tseytlin <keren.tseyt...@capitalone.com> Authored: Thu Oct 6 17:04:12 2016 -0400 Committer: James Wing <jvw...@gmail.com> Committed: Wed Oct 12 17:19:13 2016 -0700 ---------------------------------------------------------------------- .../factory/CredentialPropertyDescriptors.java | 23 ++++++++++ .../AssumeRoleCredentialsStrategy.java | 46 ++++++++++++++++++-- ...AWSCredentialsProviderControllerService.java | 16 ++++--- .../provider/factory/MockAWSProcessor.java | 6 ++- .../factory/TestCredentialsProviderFactory.java | 43 ++++++++++++++++++ 5 files changed, 123 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/6dc2f141/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 index 04330ab..920ec32 100644 --- 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 @@ -155,4 +155,27 @@ public class CredentialPropertyDescriptors { .description("External ID for cross-account access. This is used in conjunction with role arn, " + "role name, and optional session time out") .build(); + + /** + * Assume Role Proxy variables for configuring proxy to retrieve keys + */ + public static final PropertyDescriptor ASSUME_ROLE_PROXY_HOST = new PropertyDescriptor.Builder() + .name("assume-role-proxy-host") + .displayName("Assume Role Proxy Host") + .expressionLanguageSupported(false) + .required(false) + .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) + .sensitive(false) + .description("Proxy host for cross-account access, if needed within your environment. This will configure a proxy to request for temporary access keys into another AWS account") + .build(); + + public static final PropertyDescriptor ASSUME_ROLE_PROXY_PORT = new PropertyDescriptor.Builder() + .name("assume-role-proxy-port") + .displayName("Assume Role Proxy Port") + .expressionLanguageSupported(false) + .required(false) + .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR) + .sensitive(false) + .description("Proxy pot for cross-account access, if needed within your environment. This will configure a proxy to request for temporary access keys into another AWS account") + .build(); } http://git-wip-us.apache.org/repos/asf/nifi/blob/6dc2f141/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 index 186a97b..2a52dc9 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/credentials/provider/factory/strategies/AssumeRoleCredentialsStrategy.java @@ -24,13 +24,18 @@ 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 static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.MAX_SESSION_TIME; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_NAME; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsStrategy; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; +import com.amazonaws.services.securitytoken.AWSSecurityTokenService; +import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient; /** @@ -66,6 +71,16 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { return false; } + public boolean proxyVariablesValidForAssumeRole(Map<PropertyDescriptor, String> properties){ + final String assumeRoleProxyHost = properties.get(ASSUME_ROLE_PROXY_HOST); + final String assumeRoleProxyPort = properties.get(ASSUME_ROLE_PROXY_PORT); + if (assumeRoleProxyHost != null && !assumeRoleProxyHost.isEmpty() + && assumeRoleProxyPort != null && !assumeRoleProxyPort.isEmpty()) { + return true; + } + return false; + } + @Override public Collection<ValidationResult> validate(final ValidationContext validationContext, final CredentialsStrategy primaryStrategy) { @@ -73,6 +88,8 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { 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 boolean assumeRoleProxyHostIsSet = validationContext.getProperty(ASSUME_ROLE_PROXY_HOST).isSet(); + final boolean assumeRoleProxyPortIsSet = validationContext.getProperty(ASSUME_ROLE_PROXY_PORT).isSet(); final Collection<ValidationResult> validationFailureResults = new ArrayList<ValidationResult>(); @@ -96,6 +113,14 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { .build()); } + // Both proxy host and proxy port are required if present + if (assumeRoleProxyHostIsSet ^ assumeRoleProxyPortIsSet){ + validationFailureResults.add(new ValidationResult.Builder().input("Assume Role Proxy Host and Port") + .valid(false) + .explanation("Assume role with proxy requires both host and port for the proxy to be set") + .build()); + } + return validationFailureResults; } @@ -113,14 +138,27 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy { 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; + ClientConfiguration config = new ClientConfiguration(); + + // If proxy variables are set, then create Client Configuration with those values + if (proxyVariablesValidForAssumeRole(properties)) { + final String assumeRoleProxyHost = properties.get(ASSUME_ROLE_PROXY_HOST); + final Integer assumeRoleProxyPort = Integer.parseInt(properties.get(ASSUME_ROLE_PROXY_PORT)); + config.withProxyHost(assumeRoleProxyHost); + config.withProxyPort(assumeRoleProxyPort); + } - STSAssumeRoleSessionCredentialsProvider.Builder builder = new STSAssumeRoleSessionCredentialsProvider + AWSSecurityTokenService securityTokenService = new AWSSecurityTokenServiceClient(primaryCredentialsProvider, config); + builder = new STSAssumeRoleSessionCredentialsProvider .Builder(assumeRoleArn, assumeRoleName) - .withLongLivedCredentialsProvider(primaryCredentialsProvider) + .withStsClient(securityTokenService) .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/6dc2f141/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 7c09bd4..189dac5 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 @@ -35,15 +35,17 @@ import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPro import org.apache.nifi.processors.aws.credentials.provider.factory.CredentialsProviderFactory; import org.apache.nifi.reporting.InitializationException; -import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS; +import com.amazonaws.auth.AWSCredentialsProvider; + 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.ASSUME_ROLE_EXTERNAL_ID; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.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.SECRET_KEY; 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 static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.USE_DEFAULT_CREDENTIALS; /** * Implementation of AWSCredentialsProviderService interface @@ -75,6 +77,8 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS props.add(ASSUME_ROLE_NAME); props.add(MAX_SESSION_TIME); props.add(ASSUME_ROLE_EXTERNAL_ID); + props.add(ASSUME_ROLE_PROXY_HOST); + props.add(ASSUME_ROLE_PROXY_PORT); properties = Collections.unmodifiableList(props); } @@ -109,4 +113,4 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS public String toString() { return "AWSCredentialsProviderService[id=" + getIdentifier() + "]"; } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/6dc2f141/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 index d76db53..5c7d57b 100644 --- a/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java +++ b/nifi-nar-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/credentials/provider/factory/MockAWSProcessor.java @@ -34,6 +34,8 @@ import static org.apache.nifi.processors.aws.credentials.provider.factory.Creden 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_PROXY_PORT; +import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_HOST; import static org.apache.nifi.processors.aws.credentials.provider.factory.CredentialPropertyDescriptors.ASSUME_ROLE_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; @@ -57,7 +59,9 @@ public class MockAWSProcessor extends AbstractAWSCredentialsProviderProcessor<Am ASSUME_ROLE_ARN, ASSUME_ROLE_NAME, MAX_SESSION_TIME, - ASSUME_ROLE_EXTERNAL_ID + ASSUME_ROLE_EXTERNAL_ID, + ASSUME_ROLE_PROXY_HOST, + ASSUME_ROLE_PROXY_PORT ); @Override http://git-wip-us.apache.org/repos/asf/nifi/blob/6dc2f141/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 index ccdffe3..f26ce81 100644 --- 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 @@ -198,4 +198,47 @@ public class TestCredentialsProviderFactory { assertEquals("credentials provider should be equal", ProfileCredentialsProvider.class, credentialsProvider.getClass()); } + + @Test + public void testAssumeRoleCredentialsWithProxy() 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.ASSUME_ROLE_PROXY_HOST, "proxy.company.com"); + runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT, "8080"); + 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 testAssumeRoleMissingProxyHost() 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_PROXY_PORT, "8080"); + runner.assertNotValid(); + } + + @Test + public void testAssumeRoleMissingProxyPort() 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_PROXY_HOST, "proxy.company.com"); + runner.assertNotValid(); + } + + @Test + public void testAssumeRoleInvalidProxyPort() 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_PROXY_HOST, "proxy.company.com"); + runner.setProperty(CredentialPropertyDescriptors.ASSUME_ROLE_PROXY_PORT, "notIntPort"); + runner.assertNotValid(); + } }