AWS Systems Manager to store encrypted keys

How to safely store your passwords and other confidential info using AWS Systems Manager Parameter Store
Share this page:

Please, please, never, ever store your passwords, access keys, or any IDs in your code. This happens way too often, and since most of our code is on Public repositories - Amazon actually had to build a service that scans the repos for confidential info, like AWS credentials.

SSM Secret Key

If you’ve just landed here, we’re doing a “Become a Cloud Architect” Unicorn Workshop by building a Unicorn Pursuit Web App step by step, and you’re more then welcome to join!

We have two options: Systems Manager (SSM) and Secrets Manager, and if you’re trying to reduce cost - SSM is free!

About Systems Manager Parameter Store

Systems Manager Parameter Store can be used to store confidential information. You can store it in plain text, or encrypt using KMS. The idea is to use your code and go to Parameter Store to retrieve the value of the Key.

For example, within the EC2 “Instance Type” parameter, we would use SSM to define that devInstance equals whichever instance type we want, and then in the YAML parameter section. This wouldn’t need an encryption:

InstanceType:
 Type: 'AWS::SSM::Parameter::Value<String>'
 Default: devInstances

However, if we are using something like Cognito Application Client ID, this is confidential… it would be like publishing your Passport number with expiration date to the whole world, so we want to encrypt that info.

We need to configure this in the AWS Console. First, find the Systems Manager service from the AWS Console, and go to Parameter Store:

parameter store

Before you create your parameter, make sure you have Keys in your KMS. In Unicorn Pursuit, we’ll use AWS managed keys:

KMS

Watch it here, as you pay US $1/month to store any key that you create. AWS managed keys that are created on your behalf by AWS services are free to store. So let AWS create this key for you, don’t create keys.

Now go back to Systems Managet to create your Parameter, and give it a Name you’ll reference from your code, and a Value (secret stuff you don’t want others seing), as shown below:

App ID

What about Secrets Manager?

We don’t want to be hard-coding Passwords, we want to create reusable code, as much as possible, so for actual production - Secrets Manager might be a better option. Have in mind that the price is 40 cents a month per secret. Not a lot, but… there’s a cost, not like SSM where parameters are for free.

The big advantage of Secrets Managers is that from Secrets Manager we can automatically rotate our keys, and generate random passwords, AND you can share secrets across multiple accounts.

Code

Before we get into Code, let’s understand what we’re building. Check out the diagram below:

Cognito CloudFront Route53

Since in Unicorn Pursuit all the calls to the functions are done from routes.go, that where we’ll establish the SSM session and retrieve our Cognito App Client ID, and store it in the variable ClientIDValue. We need to import the module:

"github.com/aws/aws-sdk-go/service/ssm"

and then, get the value and store it in the new string variable:

// Get value of Cognito Application Client ID
ssmsvc := ssm.New(sess, aws.NewConfig().WithRegion("eu-west-1"))

ClientIDKey := "CognitoAppClientID"
withDecryption := true
param, err := ssmsvc.GetParameter(&ssm.GetParameterInput{
 Name:           &ClientIDKey,
 WithDecryption: &withDecryption,
})

// ClientIDValue stores the value of Cognito Application Client ID
ClientIDValue := *param.Parameter.Value

Before getting to the actual configuration, be sure to check if the SSM is returning the correct value. A neat trick is to print it, so you can compare if everything is Ok.

ClientIDValue := *param.Parameter.Value
fmt.Println(ClientIDValue)

That’s it, we can now reference ClientIDValue in our code instead of exposing confidential information.




Last modified June 8, 2020: AWS Diagrams Added (c98aff0)