How to initialize AWS SDK in spring boot application?

Viewed 31735

I am writing a spring boot application which reads messages from SQS. I am able to run the application using environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. However, I was wondering it would be simpler to pass this configuration via a file similar to application.properties. How to achieve this?

6 Answers

In spring boot application you can access properties mentioned in application.yml file with @value annotation. You can create a service like this:

@Service
public class AmazonClient {  
    private AmazonSQS sqsClient;

    @Value("${amazonProperties.accessKey}")
    private String accessKey;
    @Value("${amazonProperties.secretKey}")
    private String secretKey;

    @PostConstruct
    private void initializeAmazon() {
        BasicAWSCredentials awsCredentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
        this.sqsClient = AmazonSQSClientBuilder
                .standard()
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();

    }
}

In application.yml file:

amazonProperties:
   accessKey: <your_access_key>
   secretKey: <your_secret_key>

Change for aws sdk 2.0 is as follows..

    AwsBasicCredentials awsCreds = AwsBasicCredentials.create(this.accessKey, this.secretKey);

    S3Client client = S3Client.builder().region(Region.AP_SOUTH_1)
            .credentialsProvider(StaticCredentialsProvider.create(awsCreds))
            .build();

I avoid using property file, rather use Credential Provider Chain more here, AWS Documentation

Although, property file can also be overridden by environment variable, but If I always need to do so, why should I even mention it in property file. Also I would also like to avoid from committing keys in code ( in properties file)

Moreover, when I look at my CI/CD , it makes sense and also easy to just set environment variable for your Spring Boot Environment - specially on cloud. If using docker env, even more easier and much more cleaner.

There are couple of ways you can manage it.

  1. You can configure aws configure (on your local or Linux machine) which will be required your secret key and access key then you don't need to pass these in api by default constructor you can create connection as it will pick secret key, etc from system path.

    AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient();
    

How to configure aws cli

  1. If you are using AWS EC2 then when you create ec2 instance, make sure assign it a role which has permission to SQS then you don't need to even configure on that machine.

  2. You can define your ACCESS KEY AND SECRET KEY in application/properties and load in sqs class by @Value.

  3. You can create aws.keys in your classpath and can load properties from a file.

  4. Of course you can define them as constant in your Constant class.

If you are running your service in EC2(mostly non-development environments) then there is no need for configuring the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, because of EC2ContainerCredentialsProviderWrapper the credentials will be automatically fetched from the AWS container.

    @Profile({"non-prod", "prod"})
    @Bean("AWSCredentialsProvider")
    public AWSCredentialsProvider amazonAWSCredentialsProvider() {
        return new EC2ContainerCredentialsProviderWrapper();
    }

NOTE: If you decided to use any of below mentioned AWSCredentialsProviderChain then use AWSCredentialsProvider and not AWSStaticCredentialsProvider otherwise you will endup with com.amazonaws.AmazonServiceException: The security token included in the request is expired exception.

  • DefaultAWSCredentialsProviderChain
  • EnvironmentVariableCredentialsProvider
  • SystemPropertiesCredentialsProvider
  • ProfileCredentialsProvider
  • EC2ContainerCredentialsProviderWrapper

If the application running outside the AWS then you can use AWSStaticCredentialsProvider with hard coded values of awsAccessKeyId and awsSecretAccessKey

aws.awsAccessKeyId:AWS_ACCESS_KEY_ID
aws.awsSecretAccessKey:AWS_SECRET_ACCESS_KEY
    @Value("${aws.awsAccessKeyId:}")
    private String awsAccessKeyId;

    @Value("${aws.awsSecretAccessKey:}")
    private String awsSecretAccessKey;

    @Profile({"dev", "test"})
    @Bean("AWSCredentialsProvider")
    public AWSStaticCredentialsProvider amazonAWSCredentialsProviderDevelopment() {
        return new AWSStaticCredentialsProvider(new BasicAWSCredentials(
                awsAccessKeyId, awsSecretAccessKey));
    }
Related