From 807e7f822cd0a785ae89dfd30640a3e7a8452271 Mon Sep 17 00:00:00 2001 From: Joshua Morris Date: Mon, 22 Aug 2016 20:28:16 +0000 Subject: [PATCH] Added the ability to use AWSCredentialsProvider's that require non-empty contructor args e.g. ProfileCredentialsProvider where you provide the profile name to use from your ~/.aws/credentials file --- pom.xml | 5 + ...edentialsProviderPropertyValueDecoder.java | 34 ++++-- ...tialsProviderPropertyValueDecoderTest.java | 104 ++++++++++++++++++ .../KinesisClientLibConfigurationTest.java | 8 +- 4 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/test/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoderTest.java diff --git a/pom.xml b/pom.xml index f6648d81..b3427bed 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,11 @@ aws-java-sdk-cloudwatch ${aws-java-sdk.version} + + com.amazonaws + aws-java-sdk-sts + ${aws-java-sdk.version} + com.google.guava guava diff --git a/src/main/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoder.java b/src/main/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoder.java index 1f508771..9976b071 100644 --- a/src/main/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoder.java +++ b/src/main/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoder.java @@ -17,6 +17,7 @@ package com.amazonaws.services.kinesis.clientlibrary.config; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.lang.reflect.Constructor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -30,6 +31,7 @@ class AWSCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode private static final Log LOG = LogFactory.getLog(AWSCredentialsProviderPropertyValueDecoder.class); private static final String AUTH_PREFIX = "com.amazonaws.auth."; private static final String LIST_DELIMITER = ","; + private static final String ARG_DELIMITER = "|"; /** * Constructor. @@ -39,7 +41,7 @@ class AWSCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode /** * Get AWSCredentialsProvider property. - * + * * @param value property value as String * @return corresponding variable in correct type */ @@ -70,11 +72,25 @@ class AWSCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode private static List getValidCredentialsProviders(List providerNames) { List credentialsProviders = new ArrayList(); for (String providerName : providerNames) { - try { - Class className = Class.forName(providerName); - credentialsProviders.add((AWSCredentialsProvider) className.newInstance()); - } catch (Exception e) { - LOG.debug("Can't find any credentials provider matching " + providerName + "."); + if (providerName.contains(ARG_DELIMITER)) { + String[] nameAndArgs = providerName.split("\\" + ARG_DELIMITER); + Class[] argTypes = new Class[nameAndArgs.length - 1]; + Arrays.fill(argTypes, String.class); + try { + Class className = Class.forName(nameAndArgs[0]); + Constructor c = className.getConstructor(argTypes); + credentialsProviders.add((AWSCredentialsProvider) c.newInstance( + Arrays.copyOfRange(nameAndArgs, 1, nameAndArgs.length))); + } catch (Exception e) { + LOG.debug("Can't find any credentials provider matching " + providerName + "."); + } + } else { + try { + Class className = Class.forName(providerName); + credentialsProviders.add((AWSCredentialsProvider) className.newInstance()); + } catch (Exception e) { + LOG.debug("Can't find any credentials provider matching " + providerName + "."); + } } } return credentialsProviders; @@ -97,13 +113,13 @@ class AWSCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode private static List getPossibleFullClassNames(String s) { /* * We take care of three cases : - * + * * 1. Customer provides a short name of common providers in com.amazonaws.auth package i.e. any classes * implementing the AWSCredentialsProvider interface: * http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/AWSCredentialsProvider.html - * + * * 2. Customer provides a full name of common providers e.g. com.amazonaws.auth.ClasspathFileCredentialsProvider - * + * * 3. Customer provides a custom credentials provider with full name of provider */ diff --git a/src/test/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoderTest.java b/src/test/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoderTest.java new file mode 100644 index 00000000..23515926 --- /dev/null +++ b/src/test/java/com/amazonaws/services/kinesis/clientlibrary/config/AWSCredentialsProviderPropertyValueDecoderTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Amazon Software License (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/asl/ + * + * or in the "license" file accompanying this file. This file 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 com.amazonaws.services.kinesis.clientlibrary.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Set; +import java.io.File; +import java.io.IOException; + +import org.apache.commons.lang.StringUtils; +import org.junit.Test; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSCredentialsProviderChain; +import com.amazonaws.auth.profile.ProfileCredentialsProvider; +import com.amazonaws.services.kinesis.clientlibrary.config.AWSCredentialsProviderPropertyValueDecoder; + +public class AWSCredentialsProviderPropertyValueDecoderTest { + + private String credentialName1 = + "com.amazonaws.services.kinesis.clientlibrary.config.KinesisClientLibConfiguratorTest$AlwaysSucceedCredentialsProvider"; + private String credentialName2 = + "com.amazonaws.services.kinesis.clientlibrary.config.KinesisClientLibConfiguratorTest$AlwaysFailCredentialsProvider"; + private AWSCredentialsProviderPropertyValueDecoder decoder = new AWSCredentialsProviderPropertyValueDecoder(); + + @Test + public void testSingleProvider() { + AWSCredentialsProvider provider = decoder.decodeValue(credentialName1); + assertEquals(provider.getClass(), AWSCredentialsProviderChain.class); + } + + @Test + public void testTwoProviders() { + AWSCredentialsProvider provider = decoder.decodeValue(credentialName1 + "," + credentialName2); + assertEquals(provider.getClass(), AWSCredentialsProviderChain.class); + } + + @Test + public void testProfileProviderWithOneArg() { + AWSCredentialsProvider provider = decoder.decodeValue(ProfileCredentialsProvider.class.getName() + "|profileName"); + assertEquals(provider.getClass(), AWSCredentialsProviderChain.class); + } + + @Test + public void testProfileProviderWithTwoArgs() throws IOException { + File temp = File.createTempFile("test-profiles-file", ".tmp"); + temp.deleteOnExit(); + AWSCredentialsProvider provider = decoder.decodeValue(ProfileCredentialsProvider.class.getName() + + "|" + temp.getAbsolutePath() + "|profileName"); + assertEquals(provider.getClass(), AWSCredentialsProviderChain.class); + } + + /** + * This credentials provider will always succeed + */ + public static class AlwaysSucceedCredentialsProvider implements AWSCredentialsProvider { + + @Override + public AWSCredentials getCredentials() { + return null; + } + + @Override + public void refresh() { + } + + } + + /** + * This credentials provider will always fail + */ + public static class AlwaysFailCredentialsProvider implements AWSCredentialsProvider { + + @Override + public AWSCredentials getCredentials() { + throw new IllegalArgumentException(); + } + + @Override + public void refresh() { + } + + } +} diff --git a/src/test/java/com/amazonaws/services/kinesis/clientlibrary/lib/worker/KinesisClientLibConfigurationTest.java b/src/test/java/com/amazonaws/services/kinesis/clientlibrary/lib/worker/KinesisClientLibConfigurationTest.java index 588c6d79..9da391af 100644 --- a/src/test/java/com/amazonaws/services/kinesis/clientlibrary/lib/worker/KinesisClientLibConfigurationTest.java +++ b/src/test/java/com/amazonaws/services/kinesis/clientlibrary/lib/worker/KinesisClientLibConfigurationTest.java @@ -56,6 +56,7 @@ public class KinesisClientLibConfigurationTest { // Test constructor with all valid arguments. config = new KinesisClientLibConfiguration(TEST_STRING, + TEST_STRING, TEST_STRING, TEST_STRING, null, @@ -93,6 +94,7 @@ public class KinesisClientLibConfigurationTest { try { config = new KinesisClientLibConfiguration(TEST_STRING, + TEST_STRING, TEST_STRING, TEST_STRING, null, @@ -126,6 +128,7 @@ public class KinesisClientLibConfigurationTest { try { config = new KinesisClientLibConfiguration(TEST_STRING, + TEST_STRING, TEST_STRING, TEST_STRING, null, @@ -203,7 +206,7 @@ public class KinesisClientLibConfigurationTest { AmazonDynamoDBClient dclient = Mockito.mock(AmazonDynamoDBClient.class); AmazonCloudWatchClient cclient = Mockito.mock(AmazonCloudWatchClient.class); Region region = RegionUtils.getRegion("us-west-2"); - + AWSCredentialsProvider credentialsProvider = Mockito.mock(AWSCredentialsProvider.class); KinesisClientLibConfiguration kclConfig = new KinesisClientLibConfiguration("Test", "Test", credentialsProvider, "0") @@ -256,7 +259,7 @@ public class KinesisClientLibConfigurationTest { Mockito.verify(kclConfig, Mockito.times(9)).getRegionName(); Mockito.verify(kclConfig, Mockito.times(4)).getKinesisEndpoint(); - + kclConfig = Mockito.spy( new KinesisClientLibConfiguration("Test", "Test", credentialsProvider, "0") .withKinesisEndpoint("https://kinesis.eu-west-1.amazonaws.com")); @@ -288,6 +291,7 @@ public class KinesisClientLibConfigurationTest { Mockito.mock(AWSCredentialsProvider.class); try { new KinesisClientLibConfiguration(TEST_STRING, + TEST_STRING, TEST_STRING, TEST_STRING, null,