JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 288
  • Score
    100M100P100Q98677F
  • License (MIT or CC0 1.0)

Automatically update secrets on an interval with support for seamless secret rotation.

Package Exports

  • updating-secrets
  • updating-secrets/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (updating-secrets) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

updating-secrets

Automatically update secrets on an interval with support for seamless secret rotation.

Reference docs: https://electrovir.github.io/updating-secrets

Install

npm i updating-secrets

Usage

Basics

First, define your set of secrets:

import {defineSecrets, rotatableSecretShape} from 'updating-secrets';

// example collection of secrets
export const mySecrets = defineSecrets({
    databaseCredentials: {
        description: 'All credentials and access information needed for accessing the database.',
        whereToFind:
            'These values are automatically generated by RDS and only stored in AWS Secrets Manager.',
        adapterConfig: {
            aws: {
                rootOf: 'prod/DatabaseCredentials',
            },
        },
        shape: {
            password: '',
            dbname: '',
            port: -1,
            host: '',
            username: '',
        },
    },
    stripeSecret: {
        description: 'Keys for accessing and authenticating with Stripe.',
        whereToFind: 'Navigate to Developers > API keys > Standard keys > Secret key.',
        adapterConfig: {
            aws: {
                keyIn: 'prod/BackendSecrets',
            },
        },
    },
    adminPassword: {
        description:
            'Password required by the admin to access sensitive information on the website.',
        whereToFind: 'This is randomly generated and stored in AWS Secrets Manager.',
        adapterConfig: {
            aws: {
                keyIn: 'prod/BackendSecrets',
            },
        },
        shape: rotatableSecretShape,
    },
});

Second, choose your secrets adapters:

Or create your own:

import {BaseSecretsAdapter, type ProcessedSecretDefinitions} from 'updating-secrets';

export class MyCustomSecretsAdapter extends BaseSecretsAdapter {
    constructor() {
        super('MyCustomSecretsAdapter');
    }

    public override loadSecrets(secrets: Readonly<ProcessedSecretDefinitions>) {
        // load secrets here
        return {};
    }
}

Lastly, create an instance of UpdatingSecrets (with createUpdatingSecrets):

import {SecretsManager} from '@aws-sdk/client-secrets-manager';
import {AwsSecretsManagerAdapter, createUpdatingSecrets} from '@updating-secrets/aws-secrets-manager-adapter';
import {mySecrets} from './define-secrets.example.js';

const updatingSecrets = await createUpdatingSecrets(mySecrets, [
    new AwsSecretsManagerAdapter(
        new SecretsManager({
            region: 'us-east-1',
        }),
    ),
]);

Rotatable secrets

To create a seamlessly rotatable secret, use rotatableSecretShape in the secret definition's shape property, either as the root (shape: rotatableSecretShape) or as a sub-property (secret: {id: '', secret: rotatableSecretShape}).

Use this secret in the following way:

  • always store the secret with JSON like {current: 'latest-value'}
  • when rotation is needed, move the old value to the legacy property: {current: 'new-value', legacy: 'old-value'}
  • in your code, always access the secret .current
  • if you need to compare a third party's usage of the secret (for example, if the secret is an API key that you distributed to them), use UpdatingSecrets.compareRotatableSecret() to allow both the current and the legacy secret to pass comparisons:
    // assuming the `apiKey` secret is defined with `shape: rotatableSecretShape`
    updatingSecrets.compareRotatableSecret(request.headers.apiKey, updatingSecrets.get.apiKey);