Tuesday 1 January 2019

Spring Cloud AWS - Parameter Store

Externalising configuration is key to managing and automating the deployment of an application into different environments. Since Spring Boot all application configuration can be managed in one single properties or yaml file which can be baked into an image, added to a container or pulled from a source at runtime. Spring Cloud AWS now integrated with the System Manager which allows application configuration to be externalised into the Parameter Store: a simple name value store which allows access to parameter values to be controlled with IAM roles. Parameter values are read from the store and automatically injected into the application by the property placeholder configurator, negating the need for application properties to be stored in a file.

As with all cloud services, the key to its effectiveness is governance. We can restrict access to different parameters, or different named parameter groups, using IAM policies attached to the resource running our application. Coupled with Spring Profiles, this allows us to create a powerful process for the management of environments within the same account and VPC.

In this simple example I'll create a Spring Boot application which will run on an EC2 instance and read its configuration from the System Manager Parameter Store. I will show how to ensure that the application accesses only those parameters specific to the environment in which its deployed using Spring Profiles and IAM policies.


First we'll create the simple Spring Boot application and import the Spring Cloud AWS SSM dependency. It's worth ensuring that we only import the Spring Cloud dependencies we need otherwise convention over configuration will attempt to access lots of other AWS resources we don't want to use.

No we'll create two parameters in the SSM store with the same property name but for different environments: development and production. Creating a new parameter is quite simple and requires a key, description and a value. Spring Cloud AWS requires the key to be named in a specific format which can be configured in a bootstrap.yml file but defaults to:

/config/application.name/

The key must start with a forward slash, can be configured in a boot strap parameter named aws.paramstore.prefix and defaults to config. The second path element of the key defaults to the name of the application as defined in parameter spring.application.name

The rest of the key, after the application name element, must be the name of the parameter identified in the application. e.g.

/config/application.name/some.parameter.name

In the application this could be referenced with the following annotation:


The application name element of the key can be suffixed with an environment label allowing us to specify different values for development and production, e.g.

/config/application.name-production/some.parameter.name

/config/application.name-development/some.parameter.name

Now that we have two different parameters for each environment referenced by the same name we can put some access control in to ensure that only those values can be accessed by resources running in the appropriate environment. The following IAM policy will be attached to the production EC2 instances, on which the Spring Boot app will run, and will ensure that only production parameter values cannot be read by production resources. A similar policy can be created for development resources.

When we run the application we can activate specific Spring Profiles: development or production and Spring will automatically attempt to access the named parameter suffixed with that profile name. For example, to run the application in production:

java -jar -Dspring.profiles.active=production my-app.jar

So long as we can ensure the EC2 instance, or container, running the application has the correct IAM role associated we can be certain that only those parameter resources for that environment will be accessed.

6 comments: