20) Deployment with AWS Lesson

AWS Parameter Store

10 min to complete · By Ryan Desmond, Jared Larsen

Following the previous lesson on AWS CodePipeline, your deployment is now automated. But there is one problem - the application still won't start on the server. In previous deployments, you could enter your database credentials directly on the server, store them in environment variables, or leave them hard-coded within your jar or war file.

Now that your project is pulled and built directly from the GitHub repository, these options are no longer possible. This lesson will teach you how to safely store your secrets directly inside AWS, and pass them to your instance where your application can easily access them.

What is AWS Parameter Store?

Parameter Store is a very helpful feature of AWS Systems Manager. AWS Parameter Store allows you to securely store application configuration data and secrets. You can store all kinds of things - passwords, API URLs, locator IDs, license codes, etc. These values can be stored as plain text or automatically encrypted for extra security.

Parameters can be accessed through other AWS services such as Amazon EC2, Amazon ECS, AWS Lambda, or via API - and access to these parameters can be controlled using IAM.

Spring can provide your application with support for centralized configuration management, which allows remote application properties to be read and made available when the application is started. So in a way, you can think of Parameter Store as a properties file in the cloud. And when your application is running on AWS, accessing values from Parameter Store is a seamless experience.

Creating Parameters

Navigate to the AWS Parameter Store console console and click Create parameter.

Names are important as Parameter Store uses hierarchical paths for parameter organization and identification. These paths generally begin with /config, and can be customized to your liking from there. For example, you might set up your path structure like this:

/config/<service name>/<environment>/<property name>

Which means a service named spring-demo could specify a db-user property for several different profiles like so:

/config/spring-demo/dev/db-user
/config/spring-demo/staging/db-user
/config/spring-demo/prod/db-user

For this example, you will be directly creating the properties for your Spring Data credentials. Create the following parameter in Parameter Store:

  • Name - /config/spring-demo/deploy/spring.datasource.username
  • Tier - Standard
  • Type - String
  • Data type - text
  • Value - the username of the MySQL user on your EC2 instance (from your application-deploy.properties)

Click Create parameter. You'll be taken to the "My parameters" page.

Create another parameter:

  • Name - /config/application/deploy/spring.datasource.password
  • Tier - Standard
  • Type - SecureString
  • Data type - text
  • Value - the password of the MySQL user on your EC2 instance (from your application-deploy.properties)

Now that Parameter Store will provide these properties, you can remove them entirely from your application-deploy.properties file, or comment them out:

# ===============================
# = Deployed Database Config
# ===============================
spring.datasource.url=jdbc:mysql://localhost:3306/hello?useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#now provided by aws parameter store
#spring.datasource.username=
#spring.datasource.password=

Excellent! You've stored your database credential properties inside AWS Parameter Store, and removed them from your project source. But there is some more configuration to do.

Colorful illustration of a light bulb

Tip: You also have the option to pass parameter values directly to existing properties. For example, instead of spring.datasource.username, you can create /config/spring-demo/deploy/DB_USER

Then, inside your properties file you can reference it just as you have with environment variables: spring.datasource.username=${DB_USER} This approach can offer additional parity for specific setups.

Project Dependencies

To enable Spring to integrate with Parameter Store, add the following dependency to your pom.xml file and refresh your Maven config:

<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-parameter-store</artifactId>
    <version>3.1.0</version>
</dependency>

Importing Properties from Parameter Store

To instruct the application to import properties from AWS Parameter Store, add the following to your application.properties file:

spring.config.import=aws-parameterstore:/config/spring-demo/${spring.profiles.active}/

Multiple paths can be imported by separating with a ;:

spring.config.import=aws-parameterstore:/config/spring-demo/common/;/config/spring-demo/${spring.profiles.active}/

You can also break them apart and designate any as optional:

spring.config.import[0]=optional:aws-parameterstore:/config/spring-demo/common/
spring.config.import[1]=aws-parameterstore:/config/spring-demo/${spring.profiles.active}/

That is all it takes for your application to grab your newly created parameters!

You can see that you're using the spring.profiles.active property here to establish the path. This works fine when your setup allows for a single active profile at any given time, but it will take some adjustment if you "stack" profiles.

AWS IAM Configuration

Illustration of a lighthouse

Note: Your application will be able to import parameters with the help of the IAM permissions below because it resides within an Amazon EC2 instance. Additional configuration would be required if the application was hosted outside of AWS.

Now that your application has been appropriately configured, you must give your EC2 instance permission to access Parameter Store. Without these permissions, Spring Cloud AWS would be unable to import any properties. You'll add them to the IAM policy currently used by your EC2 instance profile. Navigate to the IAM Policies console.

In the list, find the CodeDeployDemo-EC2-Permissions policy that you previously created and click on its name. You'll be taken to the policy summary page.

Click the {} JSON button to view the existing JSON, then click Edit policy.

iam edit policy

On the edit page, click the JSON tab and add the following permission to the Action section: ssm:GetParametersByPath

edit ec2 permissions

Click Review policy, then click Save changes.

Colorful illustration of a light bulb

Important: As before, the policy changes should automatically kick in within a few minutes. If you're having trouble with permissions, try rebooting the instance.

Push the Changes

With all the necessary changes in place, you can now simply commit and push the source changes to your GitHub repo. This will automatically trigger your pipeline, which will proceed to build the new source, and deploy a new war file to your instance.

Colorful illustration of a light bulb

Hint: Before pushing the changes, open up your CodePipeline console and head to the detail page for your pipeline. Then, once you push the changes watch as the stages are triggered. Awesome!

After the deployment succeeds, open up your web browser and navigate to your instance IP address on port 8080 - your deployment demo application should be back in business!

Summary: AWS Parameter Store for Secure Secrets Management

With your database credentials safely stored in AWS Parameter Store, you can easily push source changes to GitHub at any time. Each push triggers your deployment pipeline, and within minutes the changes are live on your production instance.

These lessons have provided you with the essential tools necessary to establish continuous delivery with Amazon AWS. There are many other configuration options and possibilities here, this is merely scratching the surface!