secretless-ai 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -5
- package/dist/backends/aws-sm.d.ts +23 -0
- package/dist/backends/aws-sm.d.ts.map +1 -0
- package/dist/backends/aws-sm.js +179 -0
- package/dist/backends/aws-sm.js.map +1 -0
- package/dist/backends/env.d.ts +11 -0
- package/dist/backends/env.d.ts.map +1 -0
- package/dist/backends/env.js +26 -0
- package/dist/backends/env.js.map +1 -0
- package/dist/backends/index.d.ts +38 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +195 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/local.d.ts +20 -0
- package/dist/backends/local.d.ts.map +1 -0
- package/dist/backends/local.js +165 -0
- package/dist/backends/local.js.map +1 -0
- package/dist/backends/onepassword.d.ts +26 -0
- package/dist/backends/onepassword.d.ts.map +1 -0
- package/dist/backends/onepassword.js +182 -0
- package/dist/backends/onepassword.js.map +1 -0
- package/dist/backends/types.d.ts +40 -0
- package/dist/backends/types.d.ts.map +1 -0
- package/dist/backends/types.js +3 -0
- package/dist/backends/types.js.map +1 -0
- package/dist/backends/vault.d.ts +28 -0
- package/dist/backends/vault.d.ts.map +1 -0
- package/dist/backends/vault.js +157 -0
- package/dist/backends/vault.js.map +1 -0
- package/dist/cli.js +103 -0
- package/dist/cli.js.map +1 -1
- package/dist/connections/http-session.d.ts +23 -0
- package/dist/connections/http-session.d.ts.map +1 -0
- package/dist/connections/http-session.js +172 -0
- package/dist/connections/http-session.js.map +1 -0
- package/dist/connections/index.d.ts +4 -0
- package/dist/connections/index.d.ts.map +1 -0
- package/dist/connections/index.js +8 -0
- package/dist/connections/index.js.map +1 -0
- package/dist/connections/postgres.d.ts +25 -0
- package/dist/connections/postgres.d.ts.map +1 -0
- package/dist/connections/postgres.js +96 -0
- package/dist/connections/postgres.js.map +1 -0
- package/dist/connections/types.d.ts +50 -0
- package/dist/connections/types.d.ts.map +1 -0
- package/dist/connections/types.js +8 -0
- package/dist/connections/types.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +26 -0
- package/dist/init.js.map +1 -1
- package/dist/mcp/classify.d.ts +17 -0
- package/dist/mcp/classify.d.ts.map +1 -0
- package/dist/mcp/classify.js +139 -0
- package/dist/mcp/classify.js.map +1 -0
- package/dist/mcp/discover.d.ts +32 -0
- package/dist/mcp/discover.d.ts.map +1 -0
- package/dist/mcp/discover.js +179 -0
- package/dist/mcp/discover.js.map +1 -0
- package/dist/mcp/index.d.ts +7 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +18 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/install-wrapper.d.ts +33 -0
- package/dist/mcp/install-wrapper.d.ts.map +1 -0
- package/dist/mcp/install-wrapper.js +153 -0
- package/dist/mcp/install-wrapper.js.map +1 -0
- package/dist/mcp/protect.d.ts +40 -0
- package/dist/mcp/protect.d.ts.map +1 -0
- package/dist/mcp/protect.js +121 -0
- package/dist/mcp/protect.js.map +1 -0
- package/dist/mcp/rewrite.d.ts +43 -0
- package/dist/mcp/rewrite.d.ts.map +1 -0
- package/dist/mcp/rewrite.js +212 -0
- package/dist/mcp/rewrite.js.map +1 -0
- package/dist/mcp/vault.d.ts +34 -0
- package/dist/mcp/vault.d.ts.map +1 -0
- package/dist/mcp/vault.js +91 -0
- package/dist/mcp/vault.js.map +1 -0
- package/dist/mcp-wrapper.d.ts +12 -0
- package/dist/mcp-wrapper.d.ts.map +1 -0
- package/dist/mcp-wrapper.js +142 -0
- package/dist/mcp-wrapper.js.map +1 -0
- package/dist/patterns.d.ts +10 -0
- package/dist/patterns.d.ts.map +1 -1
- package/dist/patterns.js +93 -13
- package/dist/patterns.js.map +1 -1
- package/dist/scan.js +2 -2
- package/dist/scan.js.map +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -11,7 +11,82 @@ Part of the [OpenA2A](https://opena2a.org) ecosystem — open-source security fo
|
|
|
11
11
|
npx secretless-ai init
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## MCP Secret Protection
|
|
15
|
+
|
|
16
|
+
Every MCP server config has plaintext API keys sitting in JSON files on your laptop. The LLM sees them. Secretless encrypts them.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx secretless-ai protect-mcp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
Secretless MCP Protection
|
|
24
|
+
|
|
25
|
+
Scanned 1 client(s)
|
|
26
|
+
|
|
27
|
+
+ claude-desktop/browserbase
|
|
28
|
+
BROWSERBASE_API_KEY (encrypted)
|
|
29
|
+
+ claude-desktop/github
|
|
30
|
+
GITHUB_PERSONAL_ACCESS_TOKEN (encrypted)
|
|
31
|
+
+ claude-desktop/stripe
|
|
32
|
+
STRIPE_SECRET_KEY (encrypted)
|
|
33
|
+
|
|
34
|
+
3 secret(s) encrypted across 3 server(s).
|
|
35
|
+
|
|
36
|
+
MCP servers will start normally — no workflow changes needed.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**What happens:**
|
|
40
|
+
|
|
41
|
+
1. Scans MCP configs across Claude Desktop, Cursor, Claude Code, VS Code, and Windsurf
|
|
42
|
+
2. Identifies which env vars are secrets (key name patterns + value regex matching)
|
|
43
|
+
3. Encrypts secrets into a local AES-256-GCM vault (`~/.secretless-ai/mcp-vault/`)
|
|
44
|
+
4. Rewrites configs to use the `secretless-mcp` wrapper — decrypts at runtime, injects as env vars
|
|
45
|
+
5. Non-secret env vars (URLs, org names, regions) stay in the config untouched
|
|
46
|
+
|
|
47
|
+
**Before:**
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"github": {
|
|
52
|
+
"command": "npx",
|
|
53
|
+
"args": ["@github/mcp-server"],
|
|
54
|
+
"env": {
|
|
55
|
+
"GITHUB_TOKEN": "ghp_plaintext_visible_to_LLM",
|
|
56
|
+
"GITHUB_ORG": "my-org"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**After:**
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"mcpServers": {
|
|
67
|
+
"github": {
|
|
68
|
+
"command": "secretless-mcp",
|
|
69
|
+
"args": ["--server", "github", "--client", "claude-desktop", "--", "npx", "@github/mcp-server"],
|
|
70
|
+
"env": {
|
|
71
|
+
"GITHUB_ORG": "my-org"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The secret moves to the encrypted vault. The wrapper decrypts it at startup (<10ms overhead) and passes it to the MCP server as an env var. The LLM never sees it.
|
|
79
|
+
|
|
80
|
+
**Other MCP commands:**
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx secretless-ai mcp-status # Show which servers are protected/exposed
|
|
84
|
+
npx secretless-ai mcp-unprotect # Restore original configs from backup
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## AI Context Protection
|
|
15
90
|
|
|
16
91
|
AI coding tools read your files to provide context. That includes `.env` files, API keys in config, SSH keys, and cloud credentials. Once a secret enters an AI context window, it's sent to a remote API — and you can't take it back.
|
|
17
92
|
|
|
@@ -40,7 +115,7 @@ npx secretless-ai init
|
|
|
40
115
|
Output:
|
|
41
116
|
|
|
42
117
|
```
|
|
43
|
-
Secretless v0.
|
|
118
|
+
Secretless v0.6.0
|
|
44
119
|
Keeping secrets out of AI
|
|
45
120
|
|
|
46
121
|
Detected:
|
|
@@ -114,7 +189,7 @@ Detects AI tools in your project and installs protections. If API keys are set a
|
|
|
114
189
|
|
|
115
190
|
### `npx secretless-ai scan`
|
|
116
191
|
|
|
117
|
-
Scans config files for hardcoded credentials — both project-level and global (`~/.claude/CLAUDE.md`). Detects
|
|
192
|
+
Scans config files for hardcoded credentials — both project-level and global (`~/.claude/CLAUDE.md`). Detects 49 credential patterns including Anthropic, OpenAI, AWS, GitHub, Slack, Google, Stripe, SendGrid, Supabase, Azure, GitLab, Twilio, Mailgun, and more.
|
|
118
193
|
|
|
119
194
|
```
|
|
120
195
|
Found 2 credential(s):
|
|
@@ -136,6 +211,18 @@ Confirms keys are usable but hidden from AI. Checks that env vars are set AND th
|
|
|
136
211
|
PASS: Secrets are accessible via env vars but hidden from AI context.
|
|
137
212
|
```
|
|
138
213
|
|
|
214
|
+
### `npx secretless-ai protect-mcp`
|
|
215
|
+
|
|
216
|
+
Scans all MCP configs on your machine, encrypts plaintext secrets into a local vault, and rewrites configs to use the `secretless-mcp` wrapper. Safe to run multiple times — skips already-protected servers.
|
|
217
|
+
|
|
218
|
+
### `npx secretless-ai mcp-status`
|
|
219
|
+
|
|
220
|
+
Shows protection status for every MCP server across all clients. Tells you which servers have exposed secrets and which are protected.
|
|
221
|
+
|
|
222
|
+
### `npx secretless-ai mcp-unprotect`
|
|
223
|
+
|
|
224
|
+
Restores all MCP configs to their original state from backups. One command to undo everything.
|
|
225
|
+
|
|
139
226
|
### `npx secretless-ai status`
|
|
140
227
|
|
|
141
228
|
Shows current protection status.
|
|
@@ -154,9 +241,9 @@ Shows current protection status.
|
|
|
154
241
|
|
|
155
242
|
`.env`, `.env.*`, `*.key`, `*.pem`, `*.p12`, `*.pfx`, `*.crt`, `.aws/credentials`, `.ssh/*`, `.docker/config.json`, `.git-credentials`, `.npmrc`, `.pypirc`, `*.tfstate`, `*.tfvars`, `secrets/`, `credentials/`
|
|
156
243
|
|
|
157
|
-
### Credential patterns (
|
|
244
|
+
### Credential patterns (49)
|
|
158
245
|
|
|
159
|
-
Anthropic API keys, OpenAI keys
|
|
246
|
+
Anthropic API keys, OpenAI keys, AWS access keys, GitHub PATs, Slack tokens, Google API keys, Stripe keys, SendGrid keys, Supabase keys, Azure keys, GitLab tokens, Twilio keys, Mailgun keys, MongoDB URIs, JWTs, and 34 more
|
|
160
247
|
|
|
161
248
|
### Bash commands
|
|
162
249
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SecretBackend, BackendHealth } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* AWS Secrets Manager backend — IAM/IRSA auth.
|
|
4
|
+
* Zero dependencies. Uses raw HTTP with AWS Signature V4.
|
|
5
|
+
*
|
|
6
|
+
* Config:
|
|
7
|
+
* region: AWS region (default: AWS_REGION or us-east-1)
|
|
8
|
+
* accessKeyId: (default: AWS_ACCESS_KEY_ID env)
|
|
9
|
+
* secretAccessKey: (default: AWS_SECRET_ACCESS_KEY env)
|
|
10
|
+
* sessionToken: (default: AWS_SESSION_TOKEN env — for IRSA/AssumeRole)
|
|
11
|
+
*/
|
|
12
|
+
export declare class AWSSecretsManagerBackend implements SecretBackend {
|
|
13
|
+
readonly name = "aws-sm";
|
|
14
|
+
private readonly region;
|
|
15
|
+
private readonly accessKeyId;
|
|
16
|
+
private readonly secretAccessKey;
|
|
17
|
+
private readonly sessionToken;
|
|
18
|
+
constructor(config?: Record<string, unknown>);
|
|
19
|
+
resolve(secretPath: string): Promise<Record<string, string>>;
|
|
20
|
+
healthCheck(): Promise<BackendHealth>;
|
|
21
|
+
private signedRequest;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=aws-sm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-sm.d.ts","sourceRoot":"","sources":["../../src/backends/aws-sm.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;GASG;AACH,qBAAa,wBAAyB,YAAW,aAAa;IAC5D,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAOtC,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAqB5D,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAoB3C,OAAO,CAAC,aAAa;CAoFtB"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.AWSSecretsManagerBackend = void 0;
|
|
37
|
+
const https = __importStar(require("https"));
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
/**
|
|
40
|
+
* AWS Secrets Manager backend — IAM/IRSA auth.
|
|
41
|
+
* Zero dependencies. Uses raw HTTP with AWS Signature V4.
|
|
42
|
+
*
|
|
43
|
+
* Config:
|
|
44
|
+
* region: AWS region (default: AWS_REGION or us-east-1)
|
|
45
|
+
* accessKeyId: (default: AWS_ACCESS_KEY_ID env)
|
|
46
|
+
* secretAccessKey: (default: AWS_SECRET_ACCESS_KEY env)
|
|
47
|
+
* sessionToken: (default: AWS_SESSION_TOKEN env — for IRSA/AssumeRole)
|
|
48
|
+
*/
|
|
49
|
+
class AWSSecretsManagerBackend {
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.name = 'aws-sm';
|
|
52
|
+
this.region = config?.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? 'us-east-1';
|
|
53
|
+
this.accessKeyId = config?.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID ?? '';
|
|
54
|
+
this.secretAccessKey = config?.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY ?? '';
|
|
55
|
+
this.sessionToken = config?.sessionToken ?? process.env.AWS_SESSION_TOKEN ?? '';
|
|
56
|
+
}
|
|
57
|
+
async resolve(secretPath) {
|
|
58
|
+
try {
|
|
59
|
+
const body = JSON.stringify({ SecretId: secretPath });
|
|
60
|
+
const response = await this.signedRequest('GetSecretValue', body);
|
|
61
|
+
const data = JSON.parse(response);
|
|
62
|
+
if (data.SecretString) {
|
|
63
|
+
// Try to parse as JSON (common pattern)
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(data.SecretString);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Not JSON — return as single key-value
|
|
69
|
+
return { [secretPath]: data.SecretString };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async healthCheck() {
|
|
79
|
+
const start = Date.now();
|
|
80
|
+
try {
|
|
81
|
+
// List secrets (limited to 1) to verify auth
|
|
82
|
+
const body = JSON.stringify({ MaxResults: 1 });
|
|
83
|
+
await this.signedRequest('ListSecrets', body);
|
|
84
|
+
return {
|
|
85
|
+
healthy: true,
|
|
86
|
+
latencyMs: Date.now() - start,
|
|
87
|
+
message: `AWS Secrets Manager (${this.region})`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return {
|
|
92
|
+
healthy: false,
|
|
93
|
+
latencyMs: Date.now() - start,
|
|
94
|
+
message: `AWS SM error: ${err instanceof Error ? err.message : String(err)}`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
signedRequest(action, body) {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
const host = `secretsmanager.${this.region}.amazonaws.com`;
|
|
101
|
+
const now = new Date();
|
|
102
|
+
const dateStamp = now.toISOString().replace(/[:-]|\.\d{3}/g, '').slice(0, 8);
|
|
103
|
+
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
|
|
104
|
+
const headers = {
|
|
105
|
+
'Content-Type': 'application/x-amz-json-1.1',
|
|
106
|
+
'X-Amz-Target': `secretsmanager.${action}`,
|
|
107
|
+
'X-Amz-Date': amzDate,
|
|
108
|
+
Host: host,
|
|
109
|
+
};
|
|
110
|
+
if (this.sessionToken) {
|
|
111
|
+
headers['X-Amz-Security-Token'] = this.sessionToken;
|
|
112
|
+
}
|
|
113
|
+
// AWS Signature V4
|
|
114
|
+
const canonicalHeaders = Object.entries(headers)
|
|
115
|
+
.sort(([a], [b]) => a.toLowerCase().localeCompare(b.toLowerCase()))
|
|
116
|
+
.map(([k, v]) => `${k.toLowerCase()}:${v}`)
|
|
117
|
+
.join('\n') + '\n';
|
|
118
|
+
const signedHeaders = Object.keys(headers)
|
|
119
|
+
.map((k) => k.toLowerCase())
|
|
120
|
+
.sort()
|
|
121
|
+
.join(';');
|
|
122
|
+
const payloadHash = crypto.createHash('sha256').update(body).digest('hex');
|
|
123
|
+
const canonicalRequest = [
|
|
124
|
+
'POST',
|
|
125
|
+
'/',
|
|
126
|
+
'',
|
|
127
|
+
canonicalHeaders,
|
|
128
|
+
signedHeaders,
|
|
129
|
+
payloadHash,
|
|
130
|
+
].join('\n');
|
|
131
|
+
const credentialScope = `${dateStamp}/${this.region}/secretsmanager/aws4_request`;
|
|
132
|
+
const stringToSign = [
|
|
133
|
+
'AWS4-HMAC-SHA256',
|
|
134
|
+
amzDate,
|
|
135
|
+
credentialScope,
|
|
136
|
+
crypto.createHash('sha256').update(canonicalRequest).digest('hex'),
|
|
137
|
+
].join('\n');
|
|
138
|
+
const signingKey = getSignatureKey(this.secretAccessKey, dateStamp, this.region, 'secretsmanager');
|
|
139
|
+
const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex');
|
|
140
|
+
headers['Authorization'] = [
|
|
141
|
+
`AWS4-HMAC-SHA256 Credential=${this.accessKeyId}/${credentialScope}`,
|
|
142
|
+
`SignedHeaders=${signedHeaders}`,
|
|
143
|
+
`Signature=${signature}`,
|
|
144
|
+
].join(', ');
|
|
145
|
+
const options = {
|
|
146
|
+
hostname: host,
|
|
147
|
+
port: 443,
|
|
148
|
+
path: '/',
|
|
149
|
+
method: 'POST',
|
|
150
|
+
headers: { ...headers, 'Content-Length': String(Buffer.byteLength(body)) },
|
|
151
|
+
timeout: 10000,
|
|
152
|
+
};
|
|
153
|
+
const req = https.request(options, (res) => {
|
|
154
|
+
let data = '';
|
|
155
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
156
|
+
res.on('end', () => {
|
|
157
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
158
|
+
reject(new Error(`AWS SM ${res.statusCode}: ${data.slice(0, 200)}`));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
resolve(data);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
req.on('error', reject);
|
|
166
|
+
req.on('timeout', () => { req.destroy(); reject(new Error('AWS SM request timeout')); });
|
|
167
|
+
req.write(body);
|
|
168
|
+
req.end();
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
exports.AWSSecretsManagerBackend = AWSSecretsManagerBackend;
|
|
173
|
+
function getSignatureKey(key, dateStamp, region, service) {
|
|
174
|
+
const kDate = crypto.createHmac('sha256', `AWS4${key}`).update(dateStamp).digest();
|
|
175
|
+
const kRegion = crypto.createHmac('sha256', kDate).update(region).digest();
|
|
176
|
+
const kService = crypto.createHmac('sha256', kRegion).update(service).digest();
|
|
177
|
+
return crypto.createHmac('sha256', kService).update('aws4_request').digest();
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=aws-sm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-sm.js","sourceRoot":"","sources":["../../src/backends/aws-sm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SecretBackend, BackendHealth } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Environment variable backend — resolves secrets from process.env.
|
|
4
|
+
* The simplest backend. Zero dependencies. Always available.
|
|
5
|
+
*/
|
|
6
|
+
export declare class EnvBackend implements SecretBackend {
|
|
7
|
+
readonly name = "env";
|
|
8
|
+
resolve(path: string): Promise<Record<string, string>>;
|
|
9
|
+
healthCheck(): Promise<BackendHealth>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/backends/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE5D;;;GAGG;AACH,qBAAa,UAAW,YAAW,aAAa;IAC9C,QAAQ,CAAC,IAAI,SAAS;IAEhB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAYtD,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;CAG5C"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EnvBackend = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Environment variable backend — resolves secrets from process.env.
|
|
6
|
+
* The simplest backend. Zero dependencies. Always available.
|
|
7
|
+
*/
|
|
8
|
+
class EnvBackend {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.name = 'env';
|
|
11
|
+
}
|
|
12
|
+
async resolve(path) {
|
|
13
|
+
// Path format: "ENV_VAR_NAME" or "prefix/ENV_VAR_NAME"
|
|
14
|
+
const varName = path.includes('/') ? path.split('/').pop() : path;
|
|
15
|
+
const value = process.env[varName];
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
return { [varName]: value };
|
|
20
|
+
}
|
|
21
|
+
async healthCheck() {
|
|
22
|
+
return { healthy: true, latencyMs: 0, message: 'Environment variables always available' };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.EnvBackend = EnvBackend;
|
|
26
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/backends/env.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,MAAa,UAAU;IAAvB;QACW,SAAI,GAAG,KAAK,CAAC;IAiBxB,CAAC;IAfC,KAAK,CAAC,OAAO,CAAC,IAAY;QACxB,uDAAuD;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QACnE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;IAC5F,CAAC;CACF;AAlBD,gCAkBC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SecretBackend, BackendConfig, BackendType, BackendHealth } from './types';
|
|
2
|
+
export type { SecretBackend, BackendConfig, BackendType, BackendHealth, AccessAuditEntry } from './types';
|
|
3
|
+
export { EnvBackend } from './env';
|
|
4
|
+
export { LocalBackend } from './local';
|
|
5
|
+
export { VaultBackend } from './vault';
|
|
6
|
+
export { AWSSecretsManagerBackend } from './aws-sm';
|
|
7
|
+
export { OnePasswordBackend } from './onepassword';
|
|
8
|
+
/** Create a backend instance from config */
|
|
9
|
+
export declare function createBackend(type: BackendType, config?: Record<string, unknown>): SecretBackend;
|
|
10
|
+
/**
|
|
11
|
+
* Backend registry — routes secret resolution to the right backend.
|
|
12
|
+
* Supports prefix-based routing and priority ordering.
|
|
13
|
+
*/
|
|
14
|
+
export declare class BackendRegistry {
|
|
15
|
+
private readonly backends;
|
|
16
|
+
private readonly auditDir?;
|
|
17
|
+
constructor(configs?: BackendConfig[], auditDir?: string);
|
|
18
|
+
/** Resolve a secret, trying backends in priority order */
|
|
19
|
+
resolve(secretPath: string): Promise<Record<string, string>>;
|
|
20
|
+
/** Health check all backends */
|
|
21
|
+
healthCheckAll(): Promise<Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
health: BackendHealth;
|
|
24
|
+
}>>;
|
|
25
|
+
/** List configured backends */
|
|
26
|
+
list(): Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
prefix: string;
|
|
29
|
+
priority: number;
|
|
30
|
+
}>;
|
|
31
|
+
/** Migrate secrets from one backend to another */
|
|
32
|
+
migrate(fromBackend: SecretBackend, toBackend: SecretBackend, paths: string[]): Promise<{
|
|
33
|
+
migrated: number;
|
|
34
|
+
failed: number;
|
|
35
|
+
}>;
|
|
36
|
+
private audit;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAoB,MAAM,SAAS,CAAC;AAS1G,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC1G,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAInD,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAUhG;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2E;IACpG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;gBAEvB,OAAO,CAAC,EAAE,aAAa,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM;IAqBxD,0DAA0D;IACpD,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA0ClE,gCAAgC;IAC1B,cAAc,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAoB/E,+BAA+B;IAC/B,IAAI,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAQjE,kDAAkD;IAC5C,OAAO,CACX,WAAW,EAAE,aAAa,EAC1B,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IA4BhD,OAAO,CAAC,KAAK;CAad"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BackendRegistry = exports.OnePasswordBackend = exports.AWSSecretsManagerBackend = exports.VaultBackend = exports.LocalBackend = exports.EnvBackend = void 0;
|
|
37
|
+
exports.createBackend = createBackend;
|
|
38
|
+
const env_1 = require("./env");
|
|
39
|
+
const local_1 = require("./local");
|
|
40
|
+
const vault_1 = require("./vault");
|
|
41
|
+
const aws_sm_1 = require("./aws-sm");
|
|
42
|
+
const onepassword_1 = require("./onepassword");
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
var env_2 = require("./env");
|
|
46
|
+
Object.defineProperty(exports, "EnvBackend", { enumerable: true, get: function () { return env_2.EnvBackend; } });
|
|
47
|
+
var local_2 = require("./local");
|
|
48
|
+
Object.defineProperty(exports, "LocalBackend", { enumerable: true, get: function () { return local_2.LocalBackend; } });
|
|
49
|
+
var vault_2 = require("./vault");
|
|
50
|
+
Object.defineProperty(exports, "VaultBackend", { enumerable: true, get: function () { return vault_2.VaultBackend; } });
|
|
51
|
+
var aws_sm_2 = require("./aws-sm");
|
|
52
|
+
Object.defineProperty(exports, "AWSSecretsManagerBackend", { enumerable: true, get: function () { return aws_sm_2.AWSSecretsManagerBackend; } });
|
|
53
|
+
var onepassword_2 = require("./onepassword");
|
|
54
|
+
Object.defineProperty(exports, "OnePasswordBackend", { enumerable: true, get: function () { return onepassword_2.OnePasswordBackend; } });
|
|
55
|
+
const AUDIT_FILE = 'access-audit.jsonl';
|
|
56
|
+
/** Create a backend instance from config */
|
|
57
|
+
function createBackend(type, config) {
|
|
58
|
+
switch (type) {
|
|
59
|
+
case 'env': return new env_1.EnvBackend();
|
|
60
|
+
case 'local': return new local_1.LocalBackend(config);
|
|
61
|
+
case 'vault': return new vault_1.VaultBackend(config);
|
|
62
|
+
case 'aws-sm': return new aws_sm_1.AWSSecretsManagerBackend(config);
|
|
63
|
+
case '1password': return new onepassword_1.OnePasswordBackend(config);
|
|
64
|
+
default:
|
|
65
|
+
throw new Error(`Unknown backend type: ${type}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Backend registry — routes secret resolution to the right backend.
|
|
70
|
+
* Supports prefix-based routing and priority ordering.
|
|
71
|
+
*/
|
|
72
|
+
class BackendRegistry {
|
|
73
|
+
constructor(configs, auditDir) {
|
|
74
|
+
this.backends = [];
|
|
75
|
+
this.auditDir = auditDir;
|
|
76
|
+
if (configs && configs.length > 0) {
|
|
77
|
+
for (const cfg of configs) {
|
|
78
|
+
const backend = createBackend(cfg.type, cfg.config);
|
|
79
|
+
this.backends.push({
|
|
80
|
+
backend,
|
|
81
|
+
prefix: cfg.prefix ?? '',
|
|
82
|
+
priority: cfg.priority ?? 100,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Default: env backend
|
|
88
|
+
this.backends.push({ backend: new env_1.EnvBackend(), prefix: '', priority: 100 });
|
|
89
|
+
}
|
|
90
|
+
// Sort by priority (lower = preferred)
|
|
91
|
+
this.backends.sort((a, b) => a.priority - b.priority);
|
|
92
|
+
}
|
|
93
|
+
/** Resolve a secret, trying backends in priority order */
|
|
94
|
+
async resolve(secretPath) {
|
|
95
|
+
const start = Date.now();
|
|
96
|
+
for (const entry of this.backends) {
|
|
97
|
+
// Check prefix match
|
|
98
|
+
if (entry.prefix && !secretPath.startsWith(entry.prefix))
|
|
99
|
+
continue;
|
|
100
|
+
// Strip prefix before resolving
|
|
101
|
+
const resolvedPath = entry.prefix
|
|
102
|
+
? secretPath.slice(entry.prefix.length).replace(/^\//, '')
|
|
103
|
+
: secretPath;
|
|
104
|
+
try {
|
|
105
|
+
const result = await entry.backend.resolve(resolvedPath);
|
|
106
|
+
if (Object.keys(result).length > 0) {
|
|
107
|
+
this.audit({
|
|
108
|
+
timestamp: new Date().toISOString(),
|
|
109
|
+
backend: entry.backend.name,
|
|
110
|
+
path: secretPath,
|
|
111
|
+
action: 'resolve',
|
|
112
|
+
success: true,
|
|
113
|
+
latencyMs: Date.now() - start,
|
|
114
|
+
});
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Try next backend
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
this.audit({
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
backend: 'none',
|
|
125
|
+
path: secretPath,
|
|
126
|
+
action: 'resolve',
|
|
127
|
+
success: false,
|
|
128
|
+
latencyMs: Date.now() - start,
|
|
129
|
+
});
|
|
130
|
+
return {};
|
|
131
|
+
}
|
|
132
|
+
/** Health check all backends */
|
|
133
|
+
async healthCheckAll() {
|
|
134
|
+
const results = [];
|
|
135
|
+
for (const entry of this.backends) {
|
|
136
|
+
const health = await entry.backend.healthCheck();
|
|
137
|
+
results.push({ name: entry.backend.name, health });
|
|
138
|
+
this.audit({
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
backend: entry.backend.name,
|
|
141
|
+
path: '',
|
|
142
|
+
action: 'healthCheck',
|
|
143
|
+
success: health.healthy,
|
|
144
|
+
latencyMs: health.latencyMs,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return results;
|
|
148
|
+
}
|
|
149
|
+
/** List configured backends */
|
|
150
|
+
list() {
|
|
151
|
+
return this.backends.map((e) => ({
|
|
152
|
+
name: e.backend.name,
|
|
153
|
+
prefix: e.prefix,
|
|
154
|
+
priority: e.priority,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
/** Migrate secrets from one backend to another */
|
|
158
|
+
async migrate(fromBackend, toBackend, paths) {
|
|
159
|
+
let migrated = 0;
|
|
160
|
+
let failed = 0;
|
|
161
|
+
for (const secretPath of paths) {
|
|
162
|
+
try {
|
|
163
|
+
const secrets = await fromBackend.resolve(secretPath);
|
|
164
|
+
if (Object.keys(secrets).length === 0) {
|
|
165
|
+
failed++;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// Store in target backend (if it supports store)
|
|
169
|
+
if ('store' in toBackend && typeof toBackend.store === 'function') {
|
|
170
|
+
for (const [key, value] of Object.entries(secrets)) {
|
|
171
|
+
await toBackend.store(key, value);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
migrated++;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
failed++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { migrated, failed };
|
|
181
|
+
}
|
|
182
|
+
audit(entry) {
|
|
183
|
+
if (!this.auditDir)
|
|
184
|
+
return;
|
|
185
|
+
try {
|
|
186
|
+
fs.mkdirSync(this.auditDir, { recursive: true });
|
|
187
|
+
fs.appendFileSync(path.join(this.auditDir, AUDIT_FILE), JSON.stringify(entry) + '\n', 'utf-8');
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Audit logging is best-effort
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
exports.BackendRegistry = BackendRegistry;
|
|
195
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"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"}
|