For the last couple of years I have had the amazing experience of working with multiple startups and different companies and I had experienced the challenges of building a successful product from scratch, from the design of the cloud architecture to the construction of the devops process and the implementation of all security controls in the cloud.
One of the common challenges I have faced is how to define the best strategy to handle secrets, this always depends on what technology stack we are using, there are many interesting solutions available in the market, however, AWS provides an interesting service that we can use with low cost and easy to configure.
AWS SSM Parameter Store is a service that provides secure, hierarchical storage for configuration data management and secrets management, it can be used to store data such as passwords and secrets. Store values as plain text or encrypted data, also allows multiple versions, labels, and encryption with AWS KMS keys.
Parameter Store has two tier, Standard and Advanced:
Standard:
-
Can store up to 10,000 secrets
-
The maximum size of a parameter value is 4KB
-
Storage pricing is free
Advanced:
-
Can store up to 100,000 secrets
-
The maximum size of a parameter value is 8KB
-
$0.05 per parameter per month
For example, if you have let’s say 5000 secrets in parameter store and have less than 10,000 parameter store api request you’ll pay almost 0$ per month using this service without encryption, however if you decide to include encryption, you have to use a KMS key, the cost of this is 1$ per month, in the end it’ll cost you about 1$ per month to handle 5000 secrets, really budget friendly.
Structure Path For Parameters
Parameter Store provides hierarchical storage, this is one of their best features and allows us to define hierarchical paths, really useful when you need to create paths for variables defined in microservices, pipelines, etc. You can use it to define secrets in multiple environments, for example: development, qa, and production:
- /backend/dev/SECRET1
- /backend/qa/SECRET1
- /backend/prod/SECRET1
SSM Parameter Store As Code
One of the benefits to use a cloud provider as AWS, is that they provide us automation tools that help us to create Infrastructure as code to deploy services, I’ll show you a briefly demo about how to use Parameter Store to define our secrets in multiple environments with Cloudformation:
First we need to clone this github repository.
Next, define environment variables for the deployment of this demo:
INFRA_STACK_NAME=demo
KMS_KEY_ALIAS=KmsKeyAlias
REGION=us-east-1
Deploy Kms key stack for encryption of secret strings in parameter store:
aws cloudformation create-stack \
--region $REGION \
--stack-name $INFRA_STACK_NAME-kms-key \
--template-body file://./kms-key.yml \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
--parameters \
ParameterKey=KmsKeyAlias,ParameterValue=$KMS_KEY_ALIAS
AWS doesn’t allow the creation of secret string variables via Cloudformation, however, we can use a lambda function as a custom resource that will allow us to create these secrets:
aws cloudformation create-stack \
--region $REGION \
--stack-name $INFRA_STACK_NAME-cr-ssm-helper \
--template-body file://./cr-ssm-helper.yml \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
Create secret variables for Dev Environment:
ENVIRONMENT=dev
aws cloudformation create-stack \
--region $REGION \
--stack-name $INFRA_STACK_NAME-ssm-variables-backend \
--template-body file://./ssm-variables-backend.yml \
--parameters \
ParameterKey=Environment,ParameterValue=$ENVIRONMENT \
ParameterKey=KmsKeyAlias,ParameterValue=$KMS_KEY_ALIAS
Create secret variables for Prod Environment:
ENVIRONMENT=prod
aws cloudformation create-stack \
--region $REGION \
--stack-name $INFRA_STACK_NAME-ssm-variables-backend-prod \
--template-body file://./ssm-variables-backend.yml \
--parameters \
ParameterKey=Environment,ParameterValue=$ENVIRONMENT \
ParameterKey=KmsKeyAlias,ParameterValue=$KMS_KEY_ALIAS
You can check the status of the deployment of the stacks in AWS:
You can find all the secret variables from the stack created successfully in AWS:
If we inspect the SECRET_TOKEN variable we can see it was created as SecureString successfully and is ready to be used in AWS.
Query environment variables by path:
ENVIRONMENT=dev
CONFIG_ENV="/backend/$ENVIRONMENT/"
aws ssm get-parameters-by-path \
--path $CONFIG_ENV \
--query 'Parameters[*].[Name,Value]' \
--with-decryption \
--region $REGION \
--output text | \
awk -F ' ' '{print $1"="$2}' | \
sed -e "s|$CONFIG_ENV||g"
Spreadsheet Report For Variables in Multiple Environments
Another great thing about AWS services is that we can create our own custom scripts to extend the functionality of their services, in this example I created a simple python script to generate a Parameter Store report with all secrets for each environment.
Feel free to try this script and generate the report:
cd parameter-store-report
DOCKER_IMAGE="parameter-store-report"
docker image rm $DOCKER_IMAGE || (echo "Image $DOCKER_IMAGE didn't exist so not removed."; exit 0)
docker build . -t $DOCKER_IMAGE
docker run --rm -v $HOME/.aws/credentials:/root/.aws/credentials:ro -v $(pwd):/app/output $DOCKER_IMAGE
Conclusion
As we can see AWS Parameter Store is an excellent, flexible and budget friendly solution option to handle secrets in the cloud.