local-aws-secrets-manager
v0.0.2
Published
> Run AWS Secrets Manager locally without external dependencies.
Readme
Local AWS Secrets Manager
Run AWS Secrets Manager locally without external dependencies.
Install
npm i local-aws-secrets-manager --save-dev
# yarn add -D local-aws-secrets-managerUsage
import { createSecretsManagerServer } from "local-aws-secrets-manager";
// const { createSecretsManagerServer } = require("local-aws-secrets-manager");
const { server, port } = await createSecretsManagerServer();Options
| name | default | description |
| ------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| port | 0 (random) | The port used by Node.js http createServer |
| hostname | localhost | The hostname used by Node.js http createServer |
| region | us-east-1 | (Cosmetic) AWS Region used in the Secret ARN. |
| accountId | 123456789012 | (Cosmetic) AWS Account ID used in Secret ARNs. |
| invokeLambdaForRotation | | A function with the signature (RotationLambdaARN: string, event: RotationEvent) => Promise<any>. You are responsible for invoking the Lambda function using your preferred method. |
| rotationIntervalInSeconds | 10 | See #Notes |
| maxRotationCount | 2 | See #Notes |
| secrets | {} | A record of secrets to create when the server starts. Keys can be Secret Names or valid Secret ARNs. Each config object can include: ClientRequestToken, SecretString, SecretBinary, Description, Tags, OwningService, KmsKeyId, |
Integration
AWS provides a feature called Service-specific endpoints, which allows you to redirect all AWS Secrets Manager API requests to a specific endpoint.
If your app already uses AWS credentials and region settings, you can simply set the AWS_ENDPOINT_URL_SECRETS_MANAGER environment variable to redirect all Secrets Manager requests to your local instance:
AWS_ENDPOINT_URL_SECRETS_MANAGER=http://localhost:5432 node ./myApp.jsSetup based on AWS Profile:
inside ~/.aws/config file
[profile local]
aws_access_key_id=fake
aws_secret_access_key=fake
region=us-east-1
services = local-services
[services local-services]
secrets_manager =
endpoint_url = http://localhost:5432Using with AWS SDK
with AWS_PROFILE=local (or AWS_ENDPOINT_URL_SECRETS_MANAGER) env variable
import { SecretsManagerClient, CreateSecretCommand } from "@aws-sdk/client-secrets-manager";
const client = new SecretsManagerClient({});
const cmd = new CreateSecretCommand({ Name: "db-password", SecretString: "supersecret" });
const res = await client.send(cmd);
console.log(res.VersionId);
// 1258b779-94f9-47ba-a162-f946d06dd9c2without AWS_PROFILE=local
import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
const client = new SecretsManagerClient({
region: "us-east-1",
endpoint: `http://localhost:5432`,
credentials: {
accessKeyId: "fake",
secretAccessKey: "fake",
},
});Using with AWS CLI
with AWS_PROFILE=local or aws --profile local
aws --profile local secretsmanager create-secret --name MyFirstLocalSecret
# output
{
"ARN": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MyFirstLocalSecret-Hi17HX",
"Name": "MyFirstLocalSecret"
}without AWS_PROFILE
AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test aws --region us-east-1 --endpoint-url http://localhost:5432 secretsmanager create-secret --name MyFirstLocalSecret
# output
{
"ARN": "arn:aws:secretsmanager:us-east-1:123456789012:secret:MyFirstLocalSecret-Hi17HX",
"Name": "MyFirstLocalSecret"
}Using with Terraform
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.46.0"
}
}
}
# Without AWS_PROFILE
# provider "aws" {
# region = "us-east-1"
# access_key = "fake"
# secret_key = "fake"
# skip_credentials_validation = true
# skip_requesting_account_id = true
# endpoints {
# secrets_manager = "http://localhost:5432"
# }
# }
# With AWS Profile
provider "aws" {
profile = "local"
skip_credentials_validation = true
skip_requesting_account_id = true
}
resource "aws_secretsmanager_secret" "my_secret" {
name = "MyFirstLocalSecret"
}Using with Jest
jest.config.js
/** @type {import('jest').Config} */
const config = {
globalSetup: "./setup-secretsmanager.js",
globalTeardown: "./teardown-secretsmanager.js",
};
module.exports = config;setup-secretsmanager.js
// @ts-check
const { createSecretsManagerServer } = require("local-aws-secrets-manager");
module.exports = async () => {
const { server } = await createSecretsManagerServer({ port: 5432, secrets: { MyFirstLocalSecret: { StringValue: "supersecret" } } });
global.__SECRETS_MANAGER_SERVER__ = server;
};teardown-secretsmanager.js
module.exports = async () => {
global.__SECRETS_MANAGER_SERVER__.close();
};Using with Vitest
vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globalSetup: ["secretsmanager.config.ts"],
},
});secretsmanager.config.ts
import { createSecretsManagerServer } from "local-aws-secrets-manager";
import type { Server } from "http";
let server: Server;
export const setup = async () => {
server = (await createSecretsManagerServer({ port: 5432, secrets: { MyFirstLocalSecret: { StringValue: "supersecret" } } })).server;
};
export const teardown = () => {
server.close();
};Supported Commands
| Command Name | Supported | | ---------------------------- | --------- | | BatchGetSecretValue | ✅ | | CancelRotateSecret | ✅ | | CreateSecret | ✅ | | DeleteResourcePolicy | ✅ | | DeleteSecret | ✅ | | DescribeSecret | ✅ | | GetRandomPassword | ✅ | | GetResourcePolicy | ✅ | | GetSecretValue | ✅ | | ListSecrets | ✅ | | ListSecretVersionIds | ✅ | | PutResourcePolicy | ✅ | | PutSecretValue | ✅ | | RemoveRegionsFromReplication | ✅ | | ReplicateSecretToRegions | ✅ | | RestoreSecret | ✅ | | RotateSecret | ✅ | | StopReplicationToReplica | ✅ | | TagResource | ✅ | | UntagResource | ✅ | | UpdateSecret | ✅ | | UpdateSecretVersionStage | ✅ | | ValidateResourcePolicy | ✅ |
Creating Secrets from a File
local-aws-secrets-manager also exports getSecretsFromFile which allows you to load secrets from an existing .env or .json file.
Example:
import { createSecretsManagerServer, getSecretsFromFile } from "local-aws-secrets-manager";
const { server, port } = await createSecretsManagerServer({ secrets: getSecretsFromFile("path/to/.env") });Notes
Since this tool is designed for local development, certain behaviors are intentionally simplified or ignored:
- RotationRules's parameters such as
AutomaticallyAfterDays,Duration, andScheduleExpressionare not used duration rotation.
UserotationIntervalInSecondsandmaxRotationCountto control rotation timing. - No permission checks are performed (Access Keys, Policies, KMS, etc.).
- Invalid regions do not throw errors.
