AWS

AWS Parameter Store is the part of AWS Systems Manager. It provides secure storage for parameters and secrets. And grant resilient availability. Let’s dive into it and see how to use it for micro-service platform.

Parameters organisation

For convenience and flexibility, we split parameters into the following categories:

  • Platform parameters - generic for the whole system and all services;
  • Service parameters - parameters specifc for dedicated service, can override platform parameters;

Following diagram describes how to organize parameters in microservice platform from generic to specific.

Envronment parameters

Platform environments

Before promoting the application to production normally it passes acceptance and automated tests. And for each stage services might use different databases and other resources. Therefore we store each parameter for different environments:

  • Staging - environment for accepntance tests
  • Testing - for integration tests
  • Production

Parameter name convention

Names are important and convention help to keep them in a meaningful order. Following convention allows to store platform-specific parameter per environment:

1
${PLATFORM_NAME}/platform-settings/${ENVIRONMENT_NAME}/${PARAMETER_NAME}

For example:

  • /platform-name/platform-settings/account/feature-flag-1
  • /platform-name/platform-settings/production/feature-flag-1

And the service-specific parameter has the following name convention:

1
${PLATFORM_NAME}/${SERVICE_NAME}/${ENVIRONMENT_NAME}/${PARAMETER_NAME}

For example:

  • /platform-name/account/staging/db-passw
  • /platform-name/account/production/db-passw

Role policy configuration

Guided by best practices of just enough administration we should give a minimum amount of right for specific IAM role. Following AWS IAM policy grants developer access to staging environment only:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                // Allows to decrypt secret parameters
                "kms:Decrypt",
                "ssm:DescribeParameters"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "ssm:PutParameter",
                "ssm:LabelParameterVersion",
                "ssm:DeleteParameter",
                "ssm:GetParameterHistory",
                "ssm:GetParametersByPath",
                "ssm:GetParameters",
                "ssm:GetParameter",
                "ssm:DeleteParameters"
            ],
            // Grant access only to staging parameters
            "Resource": "arn:aws:ssm:AWS-Region:AWS-AccountId:parameter/*staging*"
        }
    ]
}

For task runner role, such as AWS Lambda, ECS Task and so on policy need to limited to read-only for staging and production environments:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                // Allows to decrypt secret parameters
                "kms:Decrypt",
                // Allows to read params
                "ssm:GetParametersByPath"
            ],
            // Grant access only to staging parameters
            "Resource": "arn:aws:ssm:AWS-Region:AWS-AccountId:parameter/*staging*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt",
                "ssm:GetParametersByPath"
            ],
            // Grant access only to production parameters
            "Resource": "arn:aws:ssm:AWS-Region:AWS-AccountId:parameter/*production*"
        }        
    ]
}

Parameter Store UI

The easiest way to start an experiment with managing parameter store is open user interface: ServicesSystem ManagerParameter StoreCreate parameter

Let’s add new parameter:

Name/platform-name/account/staging/db-passw
TierStandard
TypeSecureString
KMS Key IDalias/aws/ssm (default)
Valuepassw

Then you would see something like this in the screen:

Search Parameters

This UI has quite limited functionality. However, AWS has a very powerful command-line toolchain to manage parameter store. Before dive into the CLI let’s take a look required policies.

Parameter Store CLI

Out of the box, AWS propose system manager command-line interface to manage the parameter store.

Let’s take a look at how to read the stored parameter:

1
aws ssm get-parameter --with-decryption --name /platform-name/account/staging/db-passw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
    "Parameter": {
        "Name": "/account/staging/db-passw",
        "LastModifiedDate": 1563047637.186,
        "Value": "secure value",
        "Version": 1,
        "Type": "SecureString",
        "ARN": "arn:aws:ssm:AWS-Region:AWS-AccountId:parameter/platform-name/account/staging/db-passw"
    }
}

Full list of commands can be found here: https://docs.aws.amazon.com/cli/latest/reference/ssm/index.html

Chamber CLI

Chamber is an alternative way of how to manipulate the parameter store. It allows to import and export multiple parameters in json format. Details can be found here: https://github.com/segmentio/chamber

Install

For OSX users you can use brew to install it:

1
brew install chamber

Setup environment to let chamber know what KMS key use for decrypt. You can add this to your shell profile file as well:

1
export CHAMBER_KMS_KEY_ALIAS=aws/ssm

Write

Let’s add more params to the parameter store. You could use json to specify the list of parameters:

1
2
3
4
5
6
7
8
9
cat > account-staging-params.json << EOF
{
  "db-passw": "secure value",
  "db-user": "account-db"
} 
EOF

chamber import platform-name/account/staging account-staging-params.json

An alternative way is using STDIN to pass parameters in json:

1
2
3
4
5
6
chamber import platform-name/account/staging - << EOF 
{
  "db-passw": "secure value",
  "db-user": "account-db"
} 
EOF

There are some limitations in json format:

  • Key names can not contain / symbols in the name.
  • Values can not be empty or null.

Read

Then let’s read what we stored in the parameter store. If you don’t have jq you can use brew install jq:

1
chamber export platform-name/account/staging | jq
1
2
3
4
{
  "db-passw": "secure value",
  "db-user": "account-db"
}

If you need to dump multiple parameters you can combine them in one export command:

1
chamber export platform-name/platform-settings/staging platform-name/account/staging | jq

Delete

To delete key you can use:

1
chamber delete platform-name/account/staging db-user

Afterword

AWS parameter store is comprehensive and non-expensive secret storage. Can be hardened via AWS lambda functions to achieve such feature as key rotations. This service recommended as secrets manager for any micro-service platform size.