July 9, 2020
Today's applications are broken into smaller and smaller pieces. We've been slowly transitioning away from managing our own infrastructure; from using virtual instances to deploying to clusters. Your environment may have one or more clusters. Those clusters have many services. Those services have many tasks. Each task is an application running in its own container. And more than likely, that application requires configuration.
I want to share with you a simple way to store your sensitive configuration and to have your application retrieve it at startup. This solution is appealing because there's no infrastructure to manage, has little maintenance, and scales beautifully. So let's get started.
Storing your configuration
For a contrived example, I'll store a GitHub Token in AWS Parameter Store and make it available to our Spring Boot application.
What you need to get started, or most likely, what you already have in place:
- A Spring Boot application
- Deployed on AWS
Store your secrets in AWS Parameter Store
Open up AWS Systems Manager then go to Parameter Store under Application Management.
- In the name field, enter
- In the description field, enter
GitHub API Token
SecureStringfrom the type field. Accept the default KMS key source.
- In the text field, enter
Create Parameterto save it.
A few things to note, for the type field I could have used a String but instead I chose SecureString to keep the value encrypted at rest. You can do either, and it will be transparently decrypted when it is retrieved. For the name field, the prefix
/config/application/ is important but everything else is just made up. I'll go into why the prefix is important in just a bit.
The "secret" sauce of this solution is in the integration. Now that your configuration is securely stored in AWS, you need a reliable way to retrieve it. A poor way to integrate would be to specifiy each property in the ECS task definition using ValueFrom mappings. That ends up requiring more configuration with more to maintain. Unsurprisingly, there's a great Spring integration that can help us out called Spring Cloud Starter AWS Parameter Store Config.
Add the Spring Boot starter dependency
In your application's pom.xml, add:
Additionally, if Spring Cloud isn't set up in the project yet, add the following to the pom.xml as well:
<!-- This is the latest version as of the 7/7/2020 -->
That's it! And now, there is some magic happening as is the case with most Spring integrations.
Deploy your application to AWS and Spring Cloud will access the Parameter Store on AWS. Properties are retrieved and injected based on the following prefix conventions:
/config/application/- applies to all applications
/config/application_dev/- applies to all applications with an active
/config/my-api/- applies to only the
my-apiapplication (defined by
spring.application.namein your application properties)
/config/my-api_dev/- applies to only the
my-apiapplication with an active
These conventions provide the flexibility to define global, application-specific, and environment-specific parameters. An added benefit is that parameters can be added/changed/removed in AWS Parameter Store and will sync on application restart. There's no middle layers or task definitions to update.
Access the injected property
github.token property should now be retrieved at application startup from Parameter Store. The parameter's full key is
/config/application/github.token. The prefix,
/config/application, is omitted and what is left is our application property key. The value,
ABC123, is transparently decrypted and provided to the application at runtime.
If this seems simple, it's because it is! Spring Boot's starter packages tend to do a good job out-of-the-box with little to no configuration.
I hope you found this to be easy to follow and beneficial. And remember, keep your secrets out of your source code!