Using Parameter Store With Node

Joris Verbogt
Joris Verbogt
Feb 12 2021
Posted in Engineering & Technology

Configure your runtime environment from within AWS

Using Parameter Store With Node

As soon as the size and complexity of your cloud-hosted software grows beyond even the simplest setup, the need for a centralized, secure store of configuration parameters and secrets becomes inevitable.

If you are using Amazon Web Services as your cloud infrastructure provider, this centralized Parameter Store is part of the AWS Systems Manager (SSM).

SSM Parameter Store

In SSM, the Parameter Store is basically a key-value mapping that is accessible by EC2 instances, Lambda functions and Cloud Formation templates.

The Parameter Store can contain plain-text values as well as secure strings. These are encrypted by keys that are managed by AWS Key Management Services.

This allows for a fine-grained control of access to these values that might contain sensitive information.

In a real-life cloud setup, a Parameter Store like this would be used for various tasks, like configuring your setup in Cloud Formation templates, and if you are using container technologies like ECS and EKS/Kubernetes, these parameters would then be exposed as environment variables to specific containers.

Accessing Parameter Store in NodeJS

But what if your application setup requires your code to have access to one or more of these parameters during runtime?

The Parameter Store is accessible to any process on an EC2 instance that has a suitable access role.

A simple CLI command like:

aws ssm get-parameter --name "/example/production/dbpass"

would already give you the value of the string from the example screenshot above.

{
    "Parameter": {
        "Name": "/example/production/dbpass",
        "Type": "SecureString",
        "Value": "s3cr3t!"
    }
}

Your application could use these shell commands to retrieve data, but your code base probably is not written in shell scripts.

Luckily, the nice folks at AWS have provided us with an extensive JavaScript SDK for all things AWS, so our NodeJS application can easily access the Parameter Store too!

const AWS = require('aws-sdk')

const ssmClient = new AWS.SSM({
  apiVersion: '2014-11-06',
  region: 'eu-west-1'
});

ssmClient.getParameter({
  Name: `/example/production/dbpass`,
  WithDecryption: true,
}, (err, data) => {
  if (data?.Parameter) {
    console.log(data.Parameter)
  }
});

Running this script on an EC2 instance with an Instance Role that grants access to this Parameter Store results in:

{
  Name: '/example/production/dbpass',
  Type: 'SecureString',
  Value: 's3cr3t!'
}

Example: Using a tree structure

Although the Parameter Store is a simple key-value mapping, it is possible to query the keys via a tree-like approach.

This gives us the possibility to use slash-delimited paths to separate various parts of our set of parameters.

It is even possible to limit access to a specific sub-tree for different access roles, thereby preventing different environments from accessing each other's data.

In this example, we use the Parameter Store to configure database access for test and production environments:

Let's say our application running in the test environment wants to access this data.

It could request data for individual keys, like the code example above, but it can also recursively query all data in the /example/test subtree:

const AWS = require('aws-sdk')

const ssmClient = new AWS.SSM({
  apiVersion: '2014-11-06',
  region: 'eu-west-1'
});

const environment = 'test'

ssmClient.getParametersByPath({
  Path: `/example/${environment}/`,
  Recursive: true,
  WithDecryption: true
}, (err, data) => {
  if (data?.Parameters) {
    console.log(data.Parameters)
  }
});

Running this script will show all parameters in the sub-tree /example/test/:

[
  {
    Name: '/example/test/dbname',
    Type: 'String',
    Value: 'example_test_db'
  },
  {
    Name: '/example/test/dbuser',
    Type: 'String',
    Value: 'test_user'
  },
  {
    Name: '/example/test/dbpass',
    Type: 'SecureString',
    Value: 's3cre3t!'
  }
]

The use of path-like key names allows you to build a hierarchical set of parameters, grouped by environment and service, easily storable as a config object to be used by your application.

By querying the Parameter Store directly from code, you will be able to change configuration settings that can then be re-read by parts of your application without the need for a redeployment of containers or provisioning of new instances.

Using a single Parameter Store allows you to pick and mix both these approaches to centralized configuration management.

Conclusion

This is of course just a simple example and lacking details on configuring the appropriate access limits to these parameters from your EC2 instances.

As always, if you have any question, correction or suggestion just send us a message via our Support Channel.

Keep up-to-date with the latest news