@parachutehome/parachute-secrets

Purpose

Utility for accessing shared secrets from AWS. Once a secret is loaded, it is added to process.env. For convenience, this also loads in all environment variables from .env and from process.env directly, in case it is preferred to access secrets from secrets rather than process.env.

This client fetches secrets from AWS Systems Manager's Parameter Store. Some secrets differ depending on the environment, so we maintain environment-specific maps of secret names.

For example, in our code we want to refer to DATABASE_HOST, without having to worry about the environment. However, in Parameter Store each secret must have a unique name, e.g. PROD_DATABASE_HOST and DEV_DATABASE_HOST. This utility takes care of that mapping, by assuming a naming convention in Parameter Store. It will first check for an environment-spaced name and will fallback to the given name.

Note: Any environment variable already defined on process.env will take precedence. This allows us to override environment variables as desired.

How to Use

Create client

const { SecretsManager } = require('@parachutehome/parachute-secrets');
const secretsManager = new SecretsManager();

Dynamically load secret(s)

const secrets = await secretsManager.loadSecrets([
'REDSHIFT_HOST',
'REDSHIFT_PORT',
]);

Those values are then available on process.env as well as in the returned secrets object.

Synchronously access a secret already loaded

If we've already fetched secret(s), they are cached. We can synchronously access those secrets via the client.

For example:

const { SecretsManager } = require('@parachutehome/parachute-secrets');
const secretsManager = new SecretsManager();
await secretsManager.loadSecrets([
'REDSHIFT_HOST',
'REDSHIFT_PORT',
'DATABASE_HOST',
]);
const databaseHost = secretsManager.get('DATABASE_HOST');

If we specify that we want to load secrets into process.env, we can also access them there.

const { SecretsManager } = require('@parachutehome/parachute-secrets');
const secretsManager = new SecretsManager();
await secretsManager.loadSecrets(
['REDSHIFT_HOST', 'REDSHIFT_PORT', 'DATABASE_HOST'],
{
saveToProcessEnv: true,
},
);

const { DATABASE_HOST, DATABASE_USER } = process.env;

TokenManager

This is a utility for managing API keys or tokens that can be safely rotated without downtime.

Prerequisites

Two variables stored in AWS Parameter Store:

  • refresh rate (in seconds)
  • array of active tokens

Precomposed Utilities

This package exports a related utilities:

  • Express API middleware for validating Parachute API keys

It can be used like:

const router = require('express').Router();
const { validateParachuteApiKey } = require('@parachutehome/parachute-secrets');

router.use(validateParachuteApiKey);

Tests

We use Jest in this repo for testing. To run tests:

npm run test

Docs

Docs generated via typedoc live at Vercel here.

Generated using TypeDoc