skip to Main Content

I’m working on a Spring Boot backend service where I need to access certain S3 buckets programmatically using IAM Roles Anywhere. I found the following documentation for RolesAnywhereClient in the AWS SDK for Java V2:

https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rolesanywhere/RolesAnywhereClient.html

However, I’m unsure how to use it to create IAM Roles Anywhere sessions and authenticate to access S3.

I have all credentials needed for IAM roles anywhere: profile-arn, trust-anchor-arn, role-arn, certificate and private key. How to programmatically create IAM Roles Anywhere sessions with AWS SDK for Java V2 in a Spring Boot service to access S3 buckets?

2

Answers


  1. I had exact requirements for JAVA + Spring Boot!

    ⚠️ one may do some tweaks to make it non spring boot based ⚠️

    I had created a blog relating to the almost same problem/ integration. Link here

    The example code is on Github here

    Main part is that I created a new Credential Provider that extends the AWS SDKs credential provider, that internally binds to a RestClient which calls the roles anywhere /sessions endpoint

    🎉 Bonus Part 🎉 The code refreshes the AWS credentials just before expiry of the previous set of credentials. This action is configurable based on a simple boolean flag.

    This approach, does not requires to create a customization around the build package to mandate the inclusion the aws signing helper

    Additionally, with some tweaks this can be made reusable for non Spring based projects too.

    Happy to assist further

    Example configuration:-

    @Configuration
    public class AwsConfig {
    
        @Bean
        public AwsCredentialsProvider awsCredentialsProvider(final AwsRolesAnywhereProperties awsRolesAnywhereProperties,
                                                             final ObjectMapper objectMapper) {
            var rolesAnywhereCredentialsProvider = new IAMRolesAnywhereSessionsCredentialsProvider
                    .Builder(awsRolesAnywhereProperties, objectMapper)
                    .asyncCredentialUpdateEnabled(true)
                    .build();
            return rolesAnywhereCredentialsProvider;
        }
    
        @Bean
        public AwsCredentialsProvider awsCredentialsProviderV2(final AwsRolesAnywhereProperties awsRolesAnywhereProperties,
                                                               final ObjectMapper objectMapper) {
            var rolesAnywhereCredentialsProvider = new IAMRolesAnywhereSessionsCredentialsProvider
                    .Builder(objectMapper)
                    .roleArn(awsRolesAnywhereProperties.getRoleArn())
                    .profileArn(awsRolesAnywhereProperties.getProfileArn())
                    .trustAnchorArn(awsRolesAnywhereProperties.getTrustAnchorArn())
                    .encodedPrivateKey(awsRolesAnywhereProperties.getEncodedPrivateKey())
                    .encodedX509Certificate(awsRolesAnywhereProperties.getEncodedX509Certificate())
                    .durationSeconds(awsRolesAnywhereProperties.getDurationSeconds())
                    .region(awsRolesAnywhereProperties.getRegion())
                    .asyncCredentialUpdateEnabled(true)
                    .prefetch(true)
                    .build();
            return rolesAnywhereCredentialsProvider;
        }
    
        // pass the credentials provider as anyone would generally do
        @Bean
        S3Client s3Client(final AwsCredentialsProvider awsCredentialsProvider,
                          final AwsRolesAnywhereProperties awsRolesAnywhereProperties) {
            return S3Client.builder().credentialsProvider(awsCredentialsProvider).region(Region.of(awsRolesAnywhereProperties.getRegion())).build();
        }
    
    }
    

    Example application properties, strictly coupled with AwsRolesAnywhereProperties

    # AWS account id
    aws.account.id=111111111111
    # AWS region for the aws roles anywhere, actual AWS resource client may use a different region
    aws.roles.anywhere.region=us-east-1
    # AWS IAM roles anywhere trusted role
    aws.roles.anywhere.role-arn=arn:aws:iam::${aws.account.id}:role/ROLES_ANYWHERE_S3_READ_ONLY
    # AWS IAM roles anywhere profile
    aws.roles.anywhere.profile-arn=arn:aws:rolesanywhere:us-east-1:${aws.account.id}:profile/a-random-long-id
    # AWS IAM roles anywhere trust anchor
    aws.roles.anywhere.trust-anchor-arn=arn:aws:rolesanywhere:us-east-1:${aws.account.id}:trust-anchor/a-random-long-id
    # AWS IAM roles anywhere session duration
    aws.roles.anywhere.duration-seconds=900
    # AWS IAM roles anywhere access related private key, in pem format, base 64 encoded
    aws.roles.anywhere.encoded-private-key=removed for security and brevity
    # AWS IAM roles anywhere access related X509 Cert, in pem format, base 64 encoded
    aws.roles.anywhere.encoded-x509-certificate=removed for security and brevity
    
    Login or Signup to reply.
  2. As a quick way to create a session and get temporary creds, you can leverage the credential helper tool.

    After you get all the pieces assembled locally and you get the helper tool working from the command line to return temp creds, you can add the command to the ~/.aws/config file:

    [profile roles_anywhere]
        credential_process = ./aws_signing_helper credential-process --certificate /path/to/certificate --private-key /path/to/private-key --trust-anchor-arn arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID --profile-arn arn:aws:rolesanywhere:region:account:profile/PROFILE_ID --role-arn arn:aws:iam::account:role/role-name-with-path
    

    Then in Java:

    ProfileCredentialsProvider profileCredentialsProvider =  
                ProfileCredentialsProvider.builder()
                        .profileName("roles_anywhere")
                        .build();
     s3Client = S3Client.builder()
                      .credentialsProvider(profileCredentialsProvider)
                      .build();
    

    Or use a ProcessCredentialsProvider if you want to do it all in code:

                    ProcessCredentialsProvider processCredentialsProvider = ProcessCredentialsProvider.builder()
                        .command("""
                                ./aws_signing_helper credential-process 
                                --certificate /path/to/certificate 
                                --private-key /path/to/private-key 
                                --trust-anchor-arn arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID 
                                --profile-arn arn:aws:rolesanywhere:region:account:profile/PROFILE_ID 
                                --role-arn arn:aws:iam::account:role/role-name-with-path
                            """).build();
    
    
                    s3Client = S3Client.builder()//.create();
                      .credentialsProvider(processCredentialsProvider)
                      .build();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search