Spring-cloud-aws: Support IAM Roles for Tasks when running in AWS ECS

Created on 1 Feb 2017  路  2Comments  路  Source: spring-cloud/spring-cloud-aws

Spring Cloud has support for using the IAM instance profile for credential credential retrieval when running in AWS. However, when attempting to use AWS ECS IAM roles for tasks the application will still use the host instance profile.

As far as I understand the difference between an instance profile and a task role should be transparent for AWS SDK for Java post version 1.11.16 so I assuming there are some explicit controls in Spring Cloud that prevent IAM roles for tasks from working.

See below the application has a ECS task role inventory-canary-InventoryTaskRole but is using the container host's instance profile role of inventory-canary-EC2Role, and the AWS JDK version is post 1.11.16.

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.aws.core.env.stack.config.StackResourceRegistryFactoryBean]: Factory method 'stackResourceRegistryFactoryBean' threw exception; nested exception is com.amazonaws.AmazonServiceException: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/inventory-canary-EC2Role-10RJ4L9FL173K/i-0a9f98379c2f38e45 is not authorized to perform: cloudformation:DescribeStackResources (Service: AmazonCloudFormation; Status Code: 403; Error Code: AccessDenied; Request ID: 11f41133-e80f-11e6-a093-4737c2e1094e)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.5.RELEASE.jar!/:4.3.5.RELEASE]
... 106 common frames omitted
Caused by: com.amazonaws.AmazonServiceException: User: arn:aws:sts::614382051240:assumed-role/inventory-canary-EC2Role-10RJ4L9FL173K/i-0a9f98379c2f38e45 is not authorized to perform: cloudformation:DescribeStackResources (Service: AmazonCloudFormation; Status Code: 403; Error Code: AccessDenied; Request ID: 11f41133-e80f-11e6-a093-4737c2e1094e)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1378) ~[aws-java-sdk-core-1.11.18.jar!/:na]
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:924) ~[aws-java-sdk-core-1.11.18.jar!/:na]
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:702) ~[aws-java-sdk-core-1.11.18.jar!/:na]
at com.amazonaws.http.AmazonHttpClient.doExecute(AmazonHttpClient.java:454) ~[aws-java-sdk-core-1.11.18.jar!/:na]
at com.amazonaws.http.AmazonHttpClient.executeWithTimer(AmazonHttpClient.java:416) ~[aws-java-sdk-core-1.11.18.jar!/:na]
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:365) ~[aws-java-sdk-core-1.11.18.jar!/:na]
at com.amazonaws.services.cloudformation.AmazonCloudFormationClient.doInvoke(AmazonCloudFormationClient.java:1633) ~[aws-java-sdk-cloudformation-1.11.18.jar!/:na]
at com.amazonaws.services.cloudformation.AmazonCloudFormationClient.invoke(AmazonCloudFormationClient.java:1603) ~[aws-java-sdk-cloudformation-1.11.18.jar!/:na]
at com.amazonaws.services.cloudformation.AmazonCloudFormationClient.describeStackResources(AmazonCloudFormationClient.java:892) ~[aws-java-sdk-cloudformation-1.11.18.jar!/:na]
at org.springframework.cloud.aws.core.env.stack.config.AutoDetectingStackNameProvider.autoDetectStackName(AutoDetectingStackNameProvider.java:76) ~[spring-cloud-aws-core-1.1.3.RELEASE.jar!/:1.1.3.RELEASE]
at org.springframework.cloud.aws.core.env.stack.config.AutoDetectingStackNameProvider.afterPropertiesSet(AutoDetectingStackNameProvider.java:62) ~[spring-cloud-aws-core-1.1.3.RELEASE.jar!/:1.1.3.RELEASE]

Most helpful comment

We work around it by overriding the Spring auth chain with the AWS default ones:

@Configuration
public class AWSConfig {

  @Bean
  public AmazonSQSAsync amazonSQS() {
    return AmazonSQSAsyncClientBuilder.defaultClient();
  }

  @Bean
  public AmazonCloudFormation amazonCloudFormation() {
    return AmazonCloudFormationClientBuilder.defaultClient();
  }

}

All 2 comments

Just ran into this issue today as well. The default keychain in SpringCloud running on an ECS Container pulls credentials from the ECS Host running the container rather than the container itself.

We work around it by overriding the Spring auth chain with the AWS default ones:

@Configuration
public class AWSConfig {

  @Bean
  public AmazonSQSAsync amazonSQS() {
    return AmazonSQSAsyncClientBuilder.defaultClient();
  }

  @Bean
  public AmazonCloudFormation amazonCloudFormation() {
    return AmazonCloudFormationClientBuilder.defaultClient();
  }

}
Was this page helpful?
0 / 5 - 0 ratings