diff --git a/src/main/java/com/netflix/simianarmy/aws/STSAssumeRoleSessionCredentialsProvider.java b/src/main/java/com/netflix/simianarmy/aws/STSAssumeRoleSessionCredentialsProvider.java index 0d34b14c..772343be 100644 --- a/src/main/java/com/netflix/simianarmy/aws/STSAssumeRoleSessionCredentialsProvider.java +++ b/src/main/java/com/netflix/simianarmy/aws/STSAssumeRoleSessionCredentialsProvider.java @@ -69,6 +69,22 @@ public STSAssumeRoleSessionCredentialsProvider(String roleArn) { securityTokenService = new AWSSecurityTokenServiceClient(); } + /** + * Constructs a new STSAssumeRoleSessionCredentialsProvider, which makes a + * request to the AWS Security Token Service (STS), uses the provided + * {@link #roleArn} to assume a role and then request short lived session + * credentials, which will then be returned by this class's + * {@link #getCredentials()} method. + * @param roleArn + * The AWS ARN of the Role to be assumed. + * @param clientConfiguration + * The AWS ClientConfiguration to use when making AWS API requests. + */ + public STSAssumeRoleSessionCredentialsProvider(String roleArn, ClientConfiguration clientConfiguration) { + this.roleArn = roleArn; + securityTokenService = new AWSSecurityTokenServiceClient(clientConfiguration); + } + /** * Constructs a new STSAssumeRoleSessionCredentialsProvider, which will use * the specified long lived AWS credentials to make a request to the AWS diff --git a/src/main/java/com/netflix/simianarmy/basic/BasicSimianArmyContext.java b/src/main/java/com/netflix/simianarmy/basic/BasicSimianArmyContext.java index 260fd4c9..f5836358 100644 --- a/src/main/java/com/netflix/simianarmy/basic/BasicSimianArmyContext.java +++ b/src/main/java/com/netflix/simianarmy/basic/BasicSimianArmyContext.java @@ -28,6 +28,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; @@ -86,6 +87,17 @@ public class BasicSimianArmyContext implements Monkey.Context { private final String region; + private ClientConfiguration awsClientConfig = new ClientConfiguration(); + + /* If configured, the proxy to be used when making AWS API requests */ + private final String proxyHost; + + private final String proxyPort; + + private final String proxyUsernaem; + + private final String proxyPassword; + /** protected constructor as the Shell is meant to be subclassed. */ protected BasicSimianArmyContext(String... configFiles) { eventReport = new LinkedList(); @@ -105,9 +117,23 @@ protected BasicSimianArmyContext(String... configFiles) { secret = config.getStr("simianarmy.client.aws.secretKey"); region = config.getStrOrElse("simianarmy.client.aws.region", "us-east-1"); + // Check for and configure optional proxy configuration + proxyHost = config.getStr("simianarmy.client.aws.proxyHost"); + proxyPort = config.getStr("simianarmy.client.aws.proxyPort"); + proxyUsernaem = config.getStr("simianarmy.client.aws.proxyUser"); + proxyPassword = config.getStr("simianarmy.client.aws.proxyPassword"); + if ((proxyHost != null) && (proxyPort != null)) { + awsClientConfig.setProxyHost(proxyHost); + awsClientConfig.setProxyPort(Integer.parseInt(proxyPort)); + if ((proxyUsernaem != null) && (proxyPassword != null)) { + awsClientConfig.setProxyUsername(proxyUsernaem); + awsClientConfig.setProxyPassword(proxyPassword); + } + } + assumeRoleArn = config.getStr("simianarmy.client.aws.assumeRoleArn"); if (assumeRoleArn != null) { - this.awsCredentialsProvider = new STSAssumeRoleSessionCredentialsProvider(assumeRoleArn); + this.awsCredentialsProvider = new STSAssumeRoleSessionCredentialsProvider(assumeRoleArn, awsClientConfig); } // if credentials are set explicitly make them available to the AWS SDK @@ -173,11 +199,12 @@ protected void createClient() { } /** - * Create the specific client within passed region, using the appropriate AWS credentials provider. + * Create the specific client within passed region, using the appropriate AWS credentials provider + * and client configuration. * @param clientRegion */ protected void createClient(String clientRegion) { - this.client = new AWSClient(clientRegion, awsCredentialsProvider); + this.client = new AWSClient(clientRegion, awsCredentialsProvider, awsClientConfig); setCloudClient(this.client); } diff --git a/src/main/java/com/netflix/simianarmy/client/aws/AWSClient.java b/src/main/java/com/netflix/simianarmy/client/aws/AWSClient.java index baac755b..7345f7fd 100644 --- a/src/main/java/com/netflix/simianarmy/client/aws/AWSClient.java +++ b/src/main/java/com/netflix/simianarmy/client/aws/AWSClient.java @@ -18,6 +18,7 @@ package com.netflix.simianarmy.client.aws; import com.amazonaws.AmazonServiceException; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.autoscaling.AmazonAutoScalingClient; import com.amazonaws.services.autoscaling.model.AutoScalingGroup; @@ -116,6 +117,8 @@ public class AWSClient implements CloudClient { private final AWSCredentialsProvider awsCredentialsProvider; + private final ClientConfiguration awsClientConfig; + private ComputeService jcloudsComputeService; /** @@ -153,6 +156,7 @@ public class AWSClient implements CloudClient { public AWSClient(String region) { this.region = region; this.awsCredentialsProvider = null; + this.awsClientConfig = null; } /** @@ -165,6 +169,35 @@ public AWSClient(String region) { public AWSClient(String region, AWSCredentialsProvider awsCredentialsProvider) { this.region = region; this.awsCredentialsProvider = awsCredentialsProvider; + this.awsClientConfig = null; + } + + /** + * The constructor allows you to provide your own AWS client configuration. + * @param region + * the region + * @param awsClientConfig + * the AWS client configuration + */ + public AWSClient(String region, ClientConfiguration awsClientConfig) { + this.region = region; + this.awsCredentialsProvider = null; + this.awsClientConfig = awsClientConfig; + } + + /** + * The constructor allows you to provide your own AWS credentials provider and client config. + * @param region + * the region + * @param awsCredentialsProvider + * the AWS credentials provider + * @param awsClientConfig + * the AWS client configuration + */ + public AWSClient(String region, AWSCredentialsProvider awsCredentialsProvider, ClientConfiguration awsClientConfig) { + this.region = region; + this.awsCredentialsProvider = awsCredentialsProvider; + this.awsClientConfig = awsClientConfig; } /** @@ -183,10 +216,18 @@ public String region() { */ protected AmazonEC2 ec2Client() { AmazonEC2 client; - if (awsCredentialsProvider == null) { - client = new AmazonEC2Client(); + if (awsClientConfig == null) { + if (awsCredentialsProvider == null) { + client = new AmazonEC2Client(); + } else { + client = new AmazonEC2Client(awsCredentialsProvider); + } } else { - client = new AmazonEC2Client(awsCredentialsProvider); + if (awsCredentialsProvider == null) { + client = new AmazonEC2Client(awsClientConfig); + } else { + client = new AmazonEC2Client(awsCredentialsProvider, awsClientConfig); + } } client.setEndpoint("ec2." + region + ".amazonaws.com"); return client; @@ -199,10 +240,18 @@ protected AmazonEC2 ec2Client() { */ protected AmazonAutoScalingClient asgClient() { AmazonAutoScalingClient client; - if (awsCredentialsProvider == null) { - client = new AmazonAutoScalingClient(); + if (awsClientConfig == null) { + if (awsCredentialsProvider == null) { + client = new AmazonAutoScalingClient(); + } else { + client = new AmazonAutoScalingClient(awsCredentialsProvider); + } } else { - client = new AmazonAutoScalingClient(awsCredentialsProvider); + if (awsCredentialsProvider == null) { + client = new AmazonAutoScalingClient(awsClientConfig); + } else { + client = new AmazonAutoScalingClient(awsCredentialsProvider, awsClientConfig); + } } client.setEndpoint("autoscaling." + region + ".amazonaws.com"); return client; @@ -215,10 +264,18 @@ protected AmazonAutoScalingClient asgClient() { */ protected AmazonElasticLoadBalancingClient elbClient() { AmazonElasticLoadBalancingClient client; - if (awsCredentialsProvider == null) { - client = new AmazonElasticLoadBalancingClient(); + if (awsClientConfig == null) { + if (awsCredentialsProvider == null) { + client = new AmazonElasticLoadBalancingClient(); + } else { + client = new AmazonElasticLoadBalancingClient(awsCredentialsProvider); + } } else { - client = new AmazonElasticLoadBalancingClient(awsCredentialsProvider); + if (awsCredentialsProvider == null) { + client = new AmazonElasticLoadBalancingClient(awsClientConfig); + } else { + client = new AmazonElasticLoadBalancingClient(awsCredentialsProvider, awsClientConfig); + } } client.setEndpoint("elasticloadbalancing." + region + ".amazonaws.com"); return client; @@ -231,10 +288,18 @@ protected AmazonElasticLoadBalancingClient elbClient() { */ public AmazonSimpleDB sdbClient() { AmazonSimpleDB client; - if (awsCredentialsProvider == null) { - client = new AmazonSimpleDBClient(); + if (awsClientConfig == null) { + if (awsCredentialsProvider == null) { + client = new AmazonSimpleDBClient(); + } else { + client = new AmazonSimpleDBClient(awsCredentialsProvider); + } } else { - client = new AmazonSimpleDBClient(awsCredentialsProvider); + if (awsCredentialsProvider == null) { + client = new AmazonSimpleDBClient(awsClientConfig); + } else { + client = new AmazonSimpleDBClient(awsCredentialsProvider, awsClientConfig); + } } // us-east-1 has special naming // http://docs.amazonwebservices.com/general/latest/gr/rande.html#sdb_region @@ -310,9 +375,9 @@ public List describeElasticLoadBalancers(String... name } /** - * Describe a set of specific ELBs. + * Describe a specific ELB. * - * @param names the ELB names + * @param name the ELB names * @return the ELBs */ public LoadBalancerAttributes describeElasticLoadBalancerAttributes(String name) { diff --git a/src/main/resources/client.properties b/src/main/resources/client.properties index 33e07ba9..4fd4de92 100644 --- a/src/main/resources/client.properties +++ b/src/main/resources/client.properties @@ -44,4 +44,11 @@ simianarmy.client.aws.region = us-west-1 ### Operate in Cloud Formation mode - the random suffix appended to Auto Scaling Group names is ignored ### (specify ASG names as usual with no suffix in chaos.properties) # -#simianarmy.client.chaos.class=com.netflix.simianarmy.basic.chaos.CloudFormationChaosMonkey \ No newline at end of file +#simianarmy.client.chaos.class=com.netflix.simianarmy.basic.chaos.CloudFormationChaosMonkey + +# Use the following if a proxy is needed to connect to AWS APIs +# proxyHost and proxyPort are required to connect through a proxy, proxyUser and proxyPassword are optional +#simianarmy.client.aws.proxyHost= +#simianarmy.client.aws.proxyPort= +#simianarmy.client.aws.proxyUser= +#simianarmy.client.aws.proxyPassword=