Automatically update secrets on an interval with support for seamless secret rotation.
Reference docs: https://electrovir.github.io/updating-secrets
npm i updating-secrets
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:
AwsSecretsManagerAdapter: loads secrets from AWS Secrets Manager.SecretsJsonFileAdapter: loads secrets from a JSON file.StaticSecretsAdapter: allows you to define all secrets values in-place.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';
import {mySecrets} from './define-secrets.example.js';
const updatingSecrets = await createUpdatingSecrets(mySecrets, [
    new AwsSecretsManagerAdapter(
        new SecretsManager({
            region: 'us-east-1',
        }),
    ),
]);
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:
{current: 'latest-value'}legacy property: {current: 'new-value', legacy: 'old-value'}.currentUpdatingSecrets.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);