Resolving Spring Boot Properties Using the AWS Parameter Store (SSM)

Last Updated:  June 16, 2022 | Published: April 18, 2020

If you are familiar with the AWS services landscape, you might already know the Parameter Store (part of the AWS System Manager, in short, SSM). This service allows us to store parameters for our application as a String, StringList or SecureString (encrypted using KMS keys). We can use this AWS service to configure both plain text properties (e.g., name of a queue) and secrets (e.g., database passwords, OAuth2 credentials, etc.). With this blog post, you'll learn how to configure your Spring Boot application to retrieve configuration properties from the AWS Systems Manager Parameter Store.

UPDATE: The configuration processing slightly changed with Spring Boot 2.4. Take a look at the last section that discusses how to include this functionality for recent Spring Boot versions.

Spring Boot Application Setup

For the demo application, we're using Spring Boot 2.2.6 and Java 11. Besides the spring-boot-starter-web, the application includes two Spring Cloud AWS dependencies:

Configure Credentials to Access the AWS Parameter Store

First, we need to configure proper access from our Spring Boot application to AWS. For this, you'll need to obtain credentials from your AWS account. You can follow the steps mentioned in this blog post to get them.

There are multiple ways to configure credentials for the underlying Amazon Java SDK. As we are using the Spring Cloud AWS Starter, we can specify the AWS access and secret key inside our application.properties or application.yml file using the cloud.aws.credentials namespace.

While this works well for other Spring Cloud AWS components (like SQS, S3, SNS, etc.), we can't use it for the Parameter Store and Secrets Manager configuration.  This is because both rely on the DefaultAWSCredentialsProviderChain by default. There are ways to override this (read the docs for more information), but for the sake of simplicity, we'll use one of the providers of the default AWS provider chain.

The default AWS provider chain looks for the AWS credentials at the following places:

  1. Environment variables (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY or AWS_ACCESS_KEY and AWS_SECRET_KEY)
  2. Java System Properties (aws.accessKeyId and aws.secretKey)
  3. Credentials profile (default location is (~/.aws/credentials)
  4. Credentials delivered through the Amazon EC2 container service
  5. Instance profile credentials delivered through the Amazon EC2 metadata service

We're going with the first approach and add two environment variables AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY to the launch configuration of the Spring Boot application in IntelliJ.

We can also set these variables in our current shell session (from which we start our application) or our whole system.

Setting AWS Credentials in IntelliJ

Resolve AWS Properties Inside Our Spring Boot Application

First, it's important to configure the correct AWS region.

Make sure to use the same region where you created the parameters; otherwise, our Spring application won't find them.

For the demo application, we're using the AWS region eu-central-1 (Frankfurt, Germany) and set the region using the configuration property cloud.aws.region.static inside our application.yml:

Following the default convention, the parameters inside the Parameter Store require a specific naming structure:

We can configure the name of our Spring application inside the application.yml

Given this structure, let's define two parameters as SecretString for the default and production profile inside the AWS Systems Manager:

AWS Systems Manager set parameter

Note: You can omit the profile name for properties targeting the default profile.

Before we can start the application on a local machine, we ensure to disable the automatic stack detection inside the application.yml as we are not starting the application inside an AWS stack (e.g., on EC2):

Given this setup, the spring-cloud-starter-aws-parameter-store-config will now autoconfigure a AwsParameterStorePropertySourceLocator.

This class implements the PropertySourceLocator interface and Spring will use it to locate properties requested by the application e.g. @Value("${my.property}").

For a quick demo, let's request both Parameter Store properties and print them during application startup:

Running the application with the default profile results in the following log output:

… and using the production profile in the following:

Overriding the Default AWS Parameter Store Configuration

If the default parameter convention does not fit our needs, we can override it using a bootstrap.yml or bootstrap.properties file inside src/main/resources.

This allows us to e.g., override the prefix (default is /config), the name of the application (default is Spring application name) and the profile separator between name and application profile (default is _):

Updates For Spring Boot 2.4.0

Starting with version 2.4.0, Spring Boot changed some internals in regards to config file processing. There's a blog post available that discusses the reasoning and changes in detail and also a migration guide.

This change impacts this feature, and from now on, we have to explicitly import the aws-parameterstore as a possible configuration property location:

Summary

Using the Parameter Store of the AWS Systems Manager (SSM), we can easily configure our Spring Boot application thanks to Spring Cloud AWS. With this functionality, we can outsource the configuration of sensitive values to a central place inside AWS.

With the Spring Cloud AWS dependencies, there is almost no further setup required. If you plan to start using it for your application, ensure the following:

  • use one of the default provider chains to configure the AWS credentials (e.g., using environment variables)
  • configure the same AWS region you used to configure the parameters in the AWS console
  • follow the default property naming structure or define your own

You can find the application for this blog post on GitHub.

PS: If your application uses Eclipse MicroProfile, you can achieve something similar by creating a custom ConfigSource using the MicroProfile Config specification.

For more practical hands-on advice on developing Spring Boot applications on AWS, take a look at the Stratospheric project where we develop a real-world application while integrating several AWS services.

Have fun retrieving your Spring Boot application properties using the AWS Parameter Store,

Phil

>