Aws-sdk-java: ProfileCredentialsProvider fails if credentials file has a profile with an assume role configuration when using Ec2InstanceMetadata

Created on 6 Aug 2018  路  7Comments  路  Source: aws/aws-sdk-java

Hey,

I have a problem with the credentials file with the following profile:

[default]
region = eu-central-1
credential_source=Ec2InstanceMetadata

[profile1]
role_arn = arn:aws:iam::xxxxxx:role/Jenkins-Deployment-Role
credential_source=Ec2InstanceMetadata
source_profile=default

When using the credentials file and specifying profile1, I am getting the following error:
Exception in thread "main" com.amazonaws.SdkClientException: Unable to load credentials into profile

[default]: AWS Access Key ID is not specified.
at com.amazonaws.auth.profile.internal.ProfileStaticCredentialsProvider.fromStaticCredentials(ProfileStaticCredentialsProvider.java:55)
at com.amazonaws.auth.profile.internal.ProfileStaticCredentialsProvider.(ProfileStaticCredentialsProvider.java:40)
at com.amazonaws.auth.profile.internal.ProfileAssumeRoleCredentialsProvider.fromAssumeRole(ProfileAssumeRoleCredentialsProvider.java:72)
at com.amazonaws.auth.profile.internal.ProfileAssumeRoleCredentialsProvider.(ProfileAssumeRoleCredentialsProvider.java:46)
at com.amazonaws.auth.profile.ProfilesConfigFile.fromProfile(ProfilesConfigFile.java:204)
at com.amazonaws.auth.profile.ProfilesConfigFile.getCredentials(ProfilesConfigFile.java:160)
at com.amazonaws.auth.profile.ProfileCredentialsProvider.getCredentials(ProfileCredentialsProvider.java:161)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1166)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:762)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:724)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:717)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:699)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:667)
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:649)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:513)
at com.amazonaws.services.ecs.AmazonECSClient.doInvoke(AmazonECSClient.java:2745)
at com.amazonaws.services.ecs.AmazonECSClient.invoke(AmazonECSClient.java:2721)
at com.amazonaws.services.ecs.AmazonECSClient.executeDescribeClusters(AmazonECSClient.java:951)
at com.amazonaws.services.ecs.AmazonECSClient.describeClusters(AmazonECSClient.java:926)

Version of sdk used for this test: 1.11.374

I was not able to find out of using Ec2InstanceMetadata is supported as "default" profile officially, but based on the documentation I read above should be correct.

feature-request

Most helpful comment

Looks like we don't support the credentials_source at the moment. I'll go ahead and mark this as a feature request so others can +1 to aide in prioritization.

As for the workaround I suggest using the STSAssumeRoleSessionCredentialsProvider which handles automatically refreshing credentials when close to expiry and actually making the call to STS.

STSAssumeRoleSessionCredentialsProvider credentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(roleArn, customer + "-" + environment + "-restart-acm-tool")
            .withStsClient(AWSSecurityTokenServiceClientBuilder.defaultClient())
            .build();

  AmazonECSClientBuilder ecsClientBuilder = AmazonECSClientBuilder.standard().withRegion(awsRegion)
    .withCredentials(credentialsProvider);
  amazonECS = ecsClientBuilder.build();

All 7 comments

We have now been able to workaround this problem by using

private void initEcsClient(){
AWSStaticCredentialsProvider credentialsProvider;

  logger.debug("DBG: roleArn=" + this.roleArn);

  AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
      .withRegion(awsRegion)
      .build();

  AssumeRoleRequest roleRequest = new AssumeRoleRequest()     
      .withRoleArn(this.roleArn)
      .withRoleSessionName(customer + "-" + environment + "-restart-acm-tool");

  AssumeRoleResult assumeRoleResult = stsClient.assumeRole(roleRequest);
  logger.info ("assumed user arn: " + assumeRoleResult.getAssumedRoleUser());

  Credentials sessionCredentials = assumeRoleResult.getCredentials();
  logger.info ("assumed user credentials: " + sessionCredentials.toString());

  BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(
      sessionCredentials.getAccessKeyId(), 
      sessionCredentials.getSecretAccessKey(),
      sessionCredentials.getSessionToken()
  );      

  credentialsProvider = new AWSStaticCredentialsProvider(basicSessionCredentials);



  AmazonECSClientBuilder ecsClientBuilder = AmazonECSClientBuilder.standard().withRegion(awsRegion)
      .withCredentials(credentialsProvider);
  amazonECS = ecsClientBuilder.build();

  logger.debug("ECSClient: Using credentials Acc-Key: "+ecsClientBuilder.getCredentials().getCredentials().getAWSAccessKeyId());
  logger.debug("ECSClient: Using credentials Sec-Key: "+ecsClientBuilder.getCredentials().getCredentials().getAWSSecretKey());

}

...but this doesnt solve the original problem that we can not use the Java SDK with the same strategy as the aws-cli where the assumeRole stuff is handled automatically.

Looks like we don't support the credentials_source at the moment. I'll go ahead and mark this as a feature request so others can +1 to aide in prioritization.

As for the workaround I suggest using the STSAssumeRoleSessionCredentialsProvider which handles automatically refreshing credentials when close to expiry and actually making the call to STS.

STSAssumeRoleSessionCredentialsProvider credentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(roleArn, customer + "-" + environment + "-restart-acm-tool")
            .withStsClient(AWSSecurityTokenServiceClientBuilder.defaultClient())
            .build();

  AmazonECSClientBuilder ecsClientBuilder = AmazonECSClientBuilder.standard().withRegion(awsRegion)
    .withCredentials(credentialsProvider);
  amazonECS = ecsClientBuilder.build();

馃憤 I just ran into this.

possible duplicate of #1521.

Just ran into this issue myself
Other SDKs already support the credential_source setting so this caught me by surprise

Would like this feature in SDK and SDK 2, breaks our dev work flow.

Was this page helpful?
0 / 5 - 0 ratings