mirror of
https://github.com/morten-olsen/with-ssm.git
synced 2026-02-08 00:46:23 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef32edcb29 | ||
|
|
e2dfb3491d | ||
|
|
3ec6612167 |
@@ -1 +0,0 @@
|
|||||||
PASSWORD=SSM:/test/hfd/rds/DB_USER
|
|
||||||
49
README.md
49
README.md
@@ -25,7 +25,7 @@ that get resolved at runtime.
|
|||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install -g @0morten-olsen/with-ssm
|
npm install -g @morten-olsen/with-ssm
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
@@ -173,3 +173,50 @@ with-ssm -- docker-compose up
|
|||||||
# Deploy with production secrets
|
# Deploy with production secrets
|
||||||
with-ssm --profile production -- npm run deploy
|
with-ssm --profile production -- npm run deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## How does `with-ssm` compare to...?
|
||||||
|
|
||||||
|
`with-ssm`'s philosophy is to be a lightweight utility that enhances your
|
||||||
|
existing workflow, not a heavy framework that replaces it. Here’s how it
|
||||||
|
compares to other tools.
|
||||||
|
|
||||||
|
### vs. `.env` files & `dotenv`
|
||||||
|
|
||||||
|
`with-ssm` is a security upgrade for the `dotenv` pattern. Instead of storing
|
||||||
|
secrets in plaintext `.env` files, you store secure `SSM:` references that are
|
||||||
|
safe to commit to version control. Your app gets the secrets it needs at
|
||||||
|
runtime, but they never live on your disk, giving you the same simple developer
|
||||||
|
experience with a major security boost.
|
||||||
|
|
||||||
|
### vs. `aws-vault`
|
||||||
|
|
||||||
|
These tools are complementary and solve different problems. `aws-vault` securely
|
||||||
|
manages your local AWS _credentials_, while `with-ssm` uses those credentials to
|
||||||
|
fetch and inject application _secrets_. They work perfectly together—use
|
||||||
|
`aws-vault` to handle authentication and `with-ssm` to handle secret resolution:
|
||||||
|
`aws-vault exec my-profile -- with-ssm -- npm start`.
|
||||||
|
|
||||||
|
### vs. `chamber`
|
||||||
|
|
||||||
|
`chamber` is a more powerful CLI for the full lifecycle of secret management
|
||||||
|
(reading, writing, listing), while `with-ssm` is a lightweight utility focused
|
||||||
|
only on resolving secret references from a file. Choose `with-ssm` for its
|
||||||
|
"drop-in" simplicity and zero-config approach to enhance an existing `.env`
|
||||||
|
workflow; choose `chamber` if you need a more comprehensive command-line tool
|
||||||
|
for advanced SSM tasks.
|
||||||
|
|
||||||
|
### vs. Cloud-Native Integrations (ECS, Lambda)
|
||||||
|
|
||||||
|
`with-ssm` is built for **local development and CI/CD**, allowing your local
|
||||||
|
environment to securely mirror production. When your code is running _inside_ an
|
||||||
|
AWS environment like ECS or Lambda, you should always use the native best
|
||||||
|
practice: grant the service an IAM role to fetch secrets directly via the AWS
|
||||||
|
SDK.
|
||||||
|
|
||||||
|
### vs. Full Secret Management Platforms (HashiCorp Vault, Doppler)
|
||||||
|
|
||||||
|
Platforms like Vault or Doppler are comprehensive, often multi-cloud solutions
|
||||||
|
with their own UIs and infrastructure. `with-ssm` is a focused, AWS-native
|
||||||
|
utility, not a platform. It's the ideal choice for teams already using AWS who
|
||||||
|
want a simple, direct way to leverage SSM Parameter Store without the
|
||||||
|
operational overhead of a separate service.
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
import '../dist/start.js';
|
import '../dist/index.js';
|
||||||
|
|||||||
19
package.json
19
package.json
@@ -6,8 +6,8 @@
|
|||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test:lint": "eslint",
|
"test:lint": "eslint",
|
||||||
"build": "tsc --build",
|
"build": "ncc build src/start.ts -o dist",
|
||||||
"build:dev": "tsc --build --watch",
|
"build:dev": "ncc build src/start.ts -o dist --watch",
|
||||||
"test:unit": "vitest --run --passWithNoTests",
|
"test:unit": "vitest --run --passWithNoTests",
|
||||||
"test": "pnpm run \"/^test:/\""
|
"test": "pnpm run \"/^test:/\""
|
||||||
},
|
},
|
||||||
@@ -16,27 +16,26 @@
|
|||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@aws-sdk/client-ssm": "^3.863.0",
|
||||||
"@eslint/eslintrc": "3.3.1",
|
"@eslint/eslintrc": "3.3.1",
|
||||||
"@eslint/js": "9.32.0",
|
"@eslint/js": "9.32.0",
|
||||||
"@pnpm/find-workspace-packages": "6.0.9",
|
"@pnpm/find-workspace-packages": "6.0.9",
|
||||||
"@types/node": "24.2.0",
|
"@types/node": "24.2.0",
|
||||||
"@types/yargs": "^17.0.33",
|
"@types/yargs": "^17.0.33",
|
||||||
|
"@vercel/ncc": "^0.38.3",
|
||||||
"@vitest/coverage-v8": "3.2.4",
|
"@vitest/coverage-v8": "3.2.4",
|
||||||
|
"dotenv": "^17.2.1",
|
||||||
"eslint": "9.32.0",
|
"eslint": "9.32.0",
|
||||||
"eslint-config-prettier": "10.1.8",
|
"eslint-config-prettier": "10.1.8",
|
||||||
"eslint-plugin-import": "2.32.0",
|
"eslint-plugin-import": "2.32.0",
|
||||||
"eslint-plugin-prettier": "5.5.4",
|
"eslint-plugin-prettier": "5.5.4",
|
||||||
|
"execa": "^9.6.0",
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
"typescript": "5.9.2",
|
"typescript": "5.9.2",
|
||||||
"typescript-eslint": "8.39.0",
|
"typescript-eslint": "8.39.0",
|
||||||
"vitest": "3.2.4"
|
"vitest": "3.2.4",
|
||||||
|
"yargs": "^18.0.0"
|
||||||
},
|
},
|
||||||
"name": "@morten-olsen/with-ssm",
|
"name": "@morten-olsen/with-ssm",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0"
|
||||||
"dependencies": {
|
|
||||||
"@aws-sdk/client-ssm": "^3.859.0",
|
|
||||||
"dotenv": "^17.2.1",
|
|
||||||
"execa": "^9.6.0",
|
|
||||||
"yargs": "^18.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
957
pnpm-lock.yaml
generated
957
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ import { exec } from './utils/exec.js';
|
|||||||
import { getEnv } from './utils/env.js';
|
import { getEnv } from './utils/env.js';
|
||||||
import { replaceParams } from './utils/ssm.js';
|
import { replaceParams } from './utils/ssm.js';
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
const argv = await yargs(hideBin(process.argv))
|
const argv = await yargs(hideBin(process.argv))
|
||||||
.usage('Usage: $0 [options] -- <command>')
|
.usage('Usage: $0 [options] -- <command>')
|
||||||
.option('region', {
|
.option('region', {
|
||||||
@@ -43,3 +44,9 @@ exec({
|
|||||||
env,
|
env,
|
||||||
args: commandArgs,
|
args: commandArgs,
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"noEmit": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user