@winstonsayno/mcp-gateway 3.3.0 → 3.5.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/CHANGELOG.md +30 -0
- package/README.md +20 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +129 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/gateway/api.d.ts +10 -0
- package/dist/gateway/api.d.ts.map +1 -1
- package/dist/gateway/api.js +40 -0
- package/dist/gateway/api.js.map +1 -1
- package/dist/gateway/balancer.d.ts +8 -0
- package/dist/gateway/balancer.d.ts.map +1 -1
- package/dist/gateway/balancer.js +32 -0
- package/dist/gateway/balancer.js.map +1 -1
- package/dist/gateway/index.d.ts +6 -0
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +43 -1
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/invoker.d.ts +17 -1
- package/dist/gateway/invoker.d.ts.map +1 -1
- package/dist/gateway/invoker.js +50 -2
- package/dist/gateway/invoker.js.map +1 -1
- package/dist/gateway/routing.d.ts +68 -0
- package/dist/gateway/routing.d.ts.map +1 -0
- package/dist/gateway/routing.js +137 -0
- package/dist/gateway/routing.js.map +1 -0
- package/dist/gateway/supervisor.d.ts +3 -0
- package/dist/gateway/supervisor.d.ts.map +1 -1
- package/dist/gateway/supervisor.js +3 -1
- package/dist/gateway/supervisor.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/proxy/index.d.ts +2 -0
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +1 -1
- package/dist/proxy/index.js.map +1 -1
- package/dist/secrets/index.d.ts +167 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +410 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/utils/types.d.ts +93 -2
- package/dist/utils/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets management (3.5): upstream credentials resolved from Vault / KMS / env / files, rotated, and injected
|
|
3
|
+
* per tenant.
|
|
4
|
+
*
|
|
5
|
+
* Any server `env`, `headers`, `url` or `args` value may contain `secret://<provider>/<path>[#field]` references.
|
|
6
|
+
* They are resolved when the server connects — the registry, `GET /servers`, the audit log and config diffs only ever
|
|
7
|
+
* see the reference — and re-resolved every `secrets.rotation.intervalSeconds`; a server whose resolved credentials
|
|
8
|
+
* changed is reconnected with the new ones (token rotation without a restart).
|
|
9
|
+
*
|
|
10
|
+
* `servers[].inject` adds per-tenant / per-client credentials to each call, after plugins, policy and capture (so
|
|
11
|
+
* they never reach the request log or the replay debugger): into a tool argument or into `_meta`. `{tenant}` and
|
|
12
|
+
* `{client}` in the reference are replaced with the caller's first tenant / client id.
|
|
13
|
+
*
|
|
14
|
+
* Providers:
|
|
15
|
+
* - `vault`: HashiCorp Vault KV v2 (`GET {address}/v1/{mount}/data/{path}`), token or AppRole auth.
|
|
16
|
+
* - `aws-kms`: AWS KMS `Decrypt` (SigV4) of a base64 ciphertext; the reference path is the ciphertext.
|
|
17
|
+
* - `gcp-kms`: Google Cloud KMS `decrypt` with an access token; path is `<cryptoKey>:<base64 ciphertext>`.
|
|
18
|
+
* - `env`: environment variable; `file`: a file (trimmed), relative to the config directory.
|
|
19
|
+
*
|
|
20
|
+
* @module secrets
|
|
21
|
+
*/
|
|
22
|
+
import { createHash, createHmac } from 'crypto';
|
|
23
|
+
import { readFile } from 'fs/promises';
|
|
24
|
+
import { isAbsolute, resolve as resolvePath } from 'path';
|
|
25
|
+
import { logger } from '../utils/logger.js';
|
|
26
|
+
export const SECRET_REF = /secret:\/\/([A-Za-z0-9_-]+)\/([^\s"'#]+)(?:#([A-Za-z0-9_.-]+))?/g;
|
|
27
|
+
export function parseSecretRef(s) {
|
|
28
|
+
const m = /^secret:\/\/([A-Za-z0-9_-]+)\/([^\s"'#]+)(?:#([A-Za-z0-9_.-]+))?$/.exec(s);
|
|
29
|
+
return m ? { provider: m[1], path: m[2], ...(m[3] ? { field: m[3] } : {}) } : undefined;
|
|
30
|
+
}
|
|
31
|
+
export const hasSecretRef = (s) => new RegExp(SECRET_REF.source).test(s);
|
|
32
|
+
/** HashiCorp Vault KV v2. */
|
|
33
|
+
export class VaultProvider {
|
|
34
|
+
id;
|
|
35
|
+
cfg;
|
|
36
|
+
fetchFn;
|
|
37
|
+
type = 'vault';
|
|
38
|
+
token;
|
|
39
|
+
constructor(id, cfg, fetchFn = fetch) {
|
|
40
|
+
this.id = id;
|
|
41
|
+
this.cfg = cfg;
|
|
42
|
+
this.fetchFn = fetchFn;
|
|
43
|
+
this.token = cfg.token;
|
|
44
|
+
}
|
|
45
|
+
base() {
|
|
46
|
+
return (this.cfg.address ?? '').replace(/\/+$/, '');
|
|
47
|
+
}
|
|
48
|
+
async login() {
|
|
49
|
+
if (this.token)
|
|
50
|
+
return this.token;
|
|
51
|
+
if (!this.cfg.roleId || !this.cfg.secretId)
|
|
52
|
+
throw new Error(`Vault provider "${this.id}" needs token or roleId + secretId`);
|
|
53
|
+
const r = await this.fetchFn(`${this.base()}/v1/auth/approle/login`, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: { 'content-type': 'application/json', ...(this.cfg.namespace ? { 'X-Vault-Namespace': this.cfg.namespace } : {}) },
|
|
56
|
+
body: JSON.stringify({ role_id: this.cfg.roleId, secret_id: this.cfg.secretId }),
|
|
57
|
+
});
|
|
58
|
+
if (!r.ok)
|
|
59
|
+
throw new Error(`Vault AppRole login failed: HTTP ${r.status}`);
|
|
60
|
+
const body = (await r.json());
|
|
61
|
+
if (!body.auth?.client_token)
|
|
62
|
+
throw new Error('Vault AppRole login returned no token');
|
|
63
|
+
this.token = body.auth.client_token;
|
|
64
|
+
return this.token;
|
|
65
|
+
}
|
|
66
|
+
async read(path) {
|
|
67
|
+
const mount = this.cfg.mount ?? 'secret';
|
|
68
|
+
const get = async () => this.fetchFn(`${this.base()}/v1/${mount}/data/${path.replace(/^\/+/, '')}`, {
|
|
69
|
+
headers: { 'X-Vault-Token': await this.login(), ...(this.cfg.namespace ? { 'X-Vault-Namespace': this.cfg.namespace } : {}) },
|
|
70
|
+
});
|
|
71
|
+
let r = await get();
|
|
72
|
+
if (r.status === 403 && !this.cfg.token && this.cfg.roleId) {
|
|
73
|
+
this.token = undefined; // expired AppRole token: log in again once
|
|
74
|
+
r = await get();
|
|
75
|
+
}
|
|
76
|
+
if (r.status === 404)
|
|
77
|
+
throw new Error(`Vault: no secret at ${mount}/${path}`);
|
|
78
|
+
if (!r.ok)
|
|
79
|
+
throw new Error(`Vault read ${mount}/${path} failed: HTTP ${r.status}`);
|
|
80
|
+
const body = (await r.json());
|
|
81
|
+
return body.data?.data ?? {};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const sha256hex = (s) => createHash('sha256').update(s).digest('hex');
|
|
85
|
+
const hmac = (k, s) => createHmac('sha256', k).update(s).digest();
|
|
86
|
+
/** AWS Signature V4 headers for a JSON POST (exported for tests). */
|
|
87
|
+
export function sigv4(opts) {
|
|
88
|
+
const u = new URL(opts.url);
|
|
89
|
+
const now = opts.now ?? new Date();
|
|
90
|
+
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
|
|
91
|
+
const date = amzDate.slice(0, 8);
|
|
92
|
+
const headers = { ...opts.headers, host: u.host, 'x-amz-date': amzDate, ...(opts.sessionToken ? { 'x-amz-security-token': opts.sessionToken } : {}) };
|
|
93
|
+
const names = Object.keys(headers).map((h) => h.toLowerCase()).sort();
|
|
94
|
+
const lower = Object.fromEntries(Object.entries(headers).map(([k, v]) => [k.toLowerCase(), String(v).trim()]));
|
|
95
|
+
const canonical = [opts.method, u.pathname || '/', u.search.slice(1), names.map((n) => `${n}:${lower[n]}\n`).join(''), names.join(';'), sha256hex(opts.body)].join('\n');
|
|
96
|
+
const scope = `${date}/${opts.region}/${opts.service}/aws4_request`;
|
|
97
|
+
const toSign = ['AWS4-HMAC-SHA256', amzDate, scope, sha256hex(canonical)].join('\n');
|
|
98
|
+
const kDate = hmac(`AWS4${opts.secretAccessKey}`, date);
|
|
99
|
+
const kSigning = hmac(hmac(hmac(kDate, opts.region), opts.service), 'aws4_request');
|
|
100
|
+
const signature = createHmac('sha256', kSigning).update(toSign).digest('hex');
|
|
101
|
+
return { ...headers, authorization: `AWS4-HMAC-SHA256 Credential=${opts.accessKeyId}/${scope}, SignedHeaders=${names.join(';')}, Signature=${signature}` };
|
|
102
|
+
}
|
|
103
|
+
/** AWS KMS Decrypt; the reference path is the base64 ciphertext blob (URL-safe base64 accepted). */
|
|
104
|
+
export class AwsKmsProvider {
|
|
105
|
+
id;
|
|
106
|
+
cfg;
|
|
107
|
+
fetchFn;
|
|
108
|
+
type = 'aws-kms';
|
|
109
|
+
constructor(id, cfg, fetchFn = fetch) {
|
|
110
|
+
this.id = id;
|
|
111
|
+
this.cfg = cfg;
|
|
112
|
+
this.fetchFn = fetchFn;
|
|
113
|
+
}
|
|
114
|
+
async read(path) {
|
|
115
|
+
const region = this.cfg.region ?? process.env.AWS_REGION ?? 'us-east-1';
|
|
116
|
+
const accessKeyId = this.cfg.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID;
|
|
117
|
+
const secretAccessKey = this.cfg.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY;
|
|
118
|
+
if (!accessKeyId || !secretAccessKey)
|
|
119
|
+
throw new Error(`aws-kms provider "${this.id}" has no credentials`);
|
|
120
|
+
const url = this.cfg.endpoint ?? `https://kms.${region}.amazonaws.com/`;
|
|
121
|
+
const body = JSON.stringify({ CiphertextBlob: path.replace(/-/g, '+').replace(/_/g, '/'), ...(this.cfg.keyId ? { KeyId: this.cfg.keyId } : {}) });
|
|
122
|
+
const headers = sigv4({
|
|
123
|
+
method: 'POST', url, body, region, service: 'kms', accessKeyId, secretAccessKey,
|
|
124
|
+
sessionToken: this.cfg.sessionToken ?? process.env.AWS_SESSION_TOKEN,
|
|
125
|
+
headers: { 'content-type': 'application/x-amz-json-1.1', 'x-amz-target': 'TrentService.Decrypt' },
|
|
126
|
+
});
|
|
127
|
+
const r = await this.fetchFn(url, { method: 'POST', headers, body });
|
|
128
|
+
if (!r.ok)
|
|
129
|
+
throw new Error(`KMS Decrypt failed: HTTP ${r.status}`);
|
|
130
|
+
const out = (await r.json());
|
|
131
|
+
if (typeof out.Plaintext !== 'string')
|
|
132
|
+
throw new Error('KMS Decrypt returned no plaintext');
|
|
133
|
+
return Buffer.from(out.Plaintext, 'base64').toString('utf8');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Google Cloud KMS decrypt; path `<projects/…/cryptoKeys/key>:<base64 ciphertext>`. */
|
|
137
|
+
export class GcpKmsProvider {
|
|
138
|
+
id;
|
|
139
|
+
cfg;
|
|
140
|
+
fetchFn;
|
|
141
|
+
type = 'gcp-kms';
|
|
142
|
+
constructor(id, cfg, fetchFn = fetch) {
|
|
143
|
+
this.id = id;
|
|
144
|
+
this.cfg = cfg;
|
|
145
|
+
this.fetchFn = fetchFn;
|
|
146
|
+
}
|
|
147
|
+
async read(path) {
|
|
148
|
+
const i = path.lastIndexOf(':');
|
|
149
|
+
if (i <= 0)
|
|
150
|
+
throw new Error('gcp-kms reference must be <cryptoKey>:<ciphertext>');
|
|
151
|
+
const key = path.slice(0, i);
|
|
152
|
+
const ciphertext = path.slice(i + 1).replace(/-/g, '+').replace(/_/g, '/');
|
|
153
|
+
const token = this.cfg.token ?? process.env.GOOGLE_OAUTH_ACCESS_TOKEN;
|
|
154
|
+
if (!token)
|
|
155
|
+
throw new Error(`gcp-kms provider "${this.id}" needs token (or GOOGLE_OAUTH_ACCESS_TOKEN)`);
|
|
156
|
+
const base = (this.cfg.endpoint ?? 'https://cloudkms.googleapis.com').replace(/\/+$/, '');
|
|
157
|
+
const r = await this.fetchFn(`${base}/v1/${key}:decrypt`, {
|
|
158
|
+
method: 'POST',
|
|
159
|
+
headers: { authorization: `Bearer ${token}`, 'content-type': 'application/json' },
|
|
160
|
+
body: JSON.stringify({ ciphertext }),
|
|
161
|
+
});
|
|
162
|
+
if (!r.ok)
|
|
163
|
+
throw new Error(`Cloud KMS decrypt failed: HTTP ${r.status}`);
|
|
164
|
+
const out = (await r.json());
|
|
165
|
+
if (typeof out.plaintext !== 'string')
|
|
166
|
+
throw new Error('Cloud KMS returned no plaintext');
|
|
167
|
+
return Buffer.from(out.plaintext, 'base64').toString('utf8');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export class EnvProvider {
|
|
171
|
+
id;
|
|
172
|
+
type = 'env';
|
|
173
|
+
constructor(id) {
|
|
174
|
+
this.id = id;
|
|
175
|
+
}
|
|
176
|
+
async read(path) {
|
|
177
|
+
const v = process.env[path];
|
|
178
|
+
if (v === undefined)
|
|
179
|
+
throw new Error(`Environment variable ${path} is not set`);
|
|
180
|
+
return v;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export class FileProvider {
|
|
184
|
+
id;
|
|
185
|
+
baseDir;
|
|
186
|
+
type = 'file';
|
|
187
|
+
constructor(id, baseDir) {
|
|
188
|
+
this.id = id;
|
|
189
|
+
this.baseDir = baseDir;
|
|
190
|
+
}
|
|
191
|
+
async read(path) {
|
|
192
|
+
return (await readFile(isAbsolute(path) ? path : resolvePath(this.baseDir, path), 'utf8')).trim();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export function createProvider(cfg, baseDir = process.cwd(), fetchFn) {
|
|
196
|
+
switch (cfg.type) {
|
|
197
|
+
case 'vault':
|
|
198
|
+
return new VaultProvider(cfg.id, cfg, fetchFn);
|
|
199
|
+
case 'aws-kms':
|
|
200
|
+
return new AwsKmsProvider(cfg.id, cfg, fetchFn);
|
|
201
|
+
case 'gcp-kms':
|
|
202
|
+
return new GcpKmsProvider(cfg.id, cfg, fetchFn);
|
|
203
|
+
case 'env':
|
|
204
|
+
return new EnvProvider(cfg.id);
|
|
205
|
+
case 'file':
|
|
206
|
+
return new FileProvider(cfg.id, cfg.baseDir ?? baseDir);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** Resolves, caches and rotates secret references. Values never leave this class except into upstream configs. */
|
|
210
|
+
export class SecretManager {
|
|
211
|
+
config;
|
|
212
|
+
opts;
|
|
213
|
+
providers = new Map();
|
|
214
|
+
cache = new Map();
|
|
215
|
+
rotated = new Map();
|
|
216
|
+
errors = new Map();
|
|
217
|
+
usedBy = new Map();
|
|
218
|
+
timer;
|
|
219
|
+
/** Hash of the resolved credentials per server id (rotation detection). */
|
|
220
|
+
fingerprints = new Map();
|
|
221
|
+
constructor(config, opts = {}) {
|
|
222
|
+
this.config = config;
|
|
223
|
+
this.opts = opts;
|
|
224
|
+
this.configure();
|
|
225
|
+
}
|
|
226
|
+
/** (Re)build providers from config (hot reload). */
|
|
227
|
+
configure() {
|
|
228
|
+
const next = new Map();
|
|
229
|
+
for (const p of this.config()?.providers ?? [])
|
|
230
|
+
next.set(p.id, createProvider(p, this.opts.baseDir?.() ?? process.cwd(), this.opts.fetch));
|
|
231
|
+
if (!next.has('env'))
|
|
232
|
+
next.set('env', new EnvProvider('env'));
|
|
233
|
+
this.providers = next;
|
|
234
|
+
}
|
|
235
|
+
get enabled() {
|
|
236
|
+
return (this.config()?.providers?.length ?? 0) > 0;
|
|
237
|
+
}
|
|
238
|
+
now() {
|
|
239
|
+
return this.opts.now?.() ?? Date.now();
|
|
240
|
+
}
|
|
241
|
+
ttlMs() {
|
|
242
|
+
return (this.config()?.cacheSeconds ?? 300) * 1000;
|
|
243
|
+
}
|
|
244
|
+
/** Resolve one reference (cached for `cacheSeconds`). */
|
|
245
|
+
async get(ref, opts = {}) {
|
|
246
|
+
const parsed = parseSecretRef(ref);
|
|
247
|
+
if (!parsed)
|
|
248
|
+
throw new Error(`Not a secret reference: ${ref}`);
|
|
249
|
+
if (opts.user) {
|
|
250
|
+
let s = this.usedBy.get(ref);
|
|
251
|
+
if (!s)
|
|
252
|
+
this.usedBy.set(ref, (s = new Set()));
|
|
253
|
+
s.add(opts.user);
|
|
254
|
+
}
|
|
255
|
+
const hit = this.cache.get(ref);
|
|
256
|
+
if (hit && !opts.fresh && this.now() - hit.fetchedAt < this.ttlMs())
|
|
257
|
+
return hit.value;
|
|
258
|
+
const provider = this.providers.get(parsed.provider);
|
|
259
|
+
if (!provider)
|
|
260
|
+
throw new Error(`Unknown secret provider "${parsed.provider}" in ${ref}`);
|
|
261
|
+
try {
|
|
262
|
+
const raw = await provider.read(parsed.path);
|
|
263
|
+
let value;
|
|
264
|
+
if (typeof raw === 'string') {
|
|
265
|
+
if (parsed.field) {
|
|
266
|
+
const obj = JSON.parse(raw);
|
|
267
|
+
value = String(obj[parsed.field] ?? '');
|
|
268
|
+
}
|
|
269
|
+
else
|
|
270
|
+
value = raw;
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
const v = parsed.field ? raw[parsed.field] : Object.keys(raw).length === 1 ? Object.values(raw)[0] : undefined;
|
|
274
|
+
if (v === undefined)
|
|
275
|
+
throw new Error(`${ref}: field ${parsed.field ? `"${parsed.field}" not found` : 'required (the secret has several keys)'}`);
|
|
276
|
+
value = String(v);
|
|
277
|
+
}
|
|
278
|
+
const version = hit ? (hit.value === value ? hit.version : hit.version + 1) : 1;
|
|
279
|
+
if (hit && hit.value !== value)
|
|
280
|
+
this.rotated.set(ref, this.now());
|
|
281
|
+
this.cache.set(ref, { value, fetchedAt: this.now(), version });
|
|
282
|
+
this.errors.delete(ref);
|
|
283
|
+
return value;
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
287
|
+
this.errors.set(ref, msg);
|
|
288
|
+
// Keep serving the last good value while the provider is down.
|
|
289
|
+
if (hit) {
|
|
290
|
+
logger.warn(`Secret ${ref} could not be refreshed (${msg}); keeping the cached value`);
|
|
291
|
+
return hit.value;
|
|
292
|
+
}
|
|
293
|
+
throw err;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/** Replace every `secret://` reference inside a string. */
|
|
297
|
+
async interpolate(s, opts = {}) {
|
|
298
|
+
let src = s;
|
|
299
|
+
for (const [k, v] of Object.entries(opts.vars ?? {}))
|
|
300
|
+
src = src.split(`{${k}}`).join(v);
|
|
301
|
+
const refs = [...src.matchAll(new RegExp(SECRET_REF.source, 'g'))].map((m) => m[0]);
|
|
302
|
+
let out = src;
|
|
303
|
+
for (const ref of refs)
|
|
304
|
+
out = out.split(ref).join(await this.get(ref, opts));
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
/** A copy of a server config with every reference resolved (env, headers, url, args). */
|
|
308
|
+
async resolveServer(s, fresh = false) {
|
|
309
|
+
const user = `server:${s.replicaOf ?? s.id}`;
|
|
310
|
+
const map = async (rec) => rec ? Object.fromEntries(await Promise.all(Object.entries(rec).map(async ([k, v]) => [k, hasSecretRef(v) ? await this.interpolate(v, { fresh, user }) : v]))) : rec;
|
|
311
|
+
const out = {
|
|
312
|
+
...s,
|
|
313
|
+
env: await map(s.env),
|
|
314
|
+
headers: await map(s.headers),
|
|
315
|
+
...(s.url && hasSecretRef(s.url) ? { url: await this.interpolate(s.url, { fresh, user }) } : {}),
|
|
316
|
+
...(s.args ? { args: await Promise.all(s.args.map((a) => (hasSecretRef(a) ? this.interpolate(a, { fresh, user }) : a))) } : {}),
|
|
317
|
+
};
|
|
318
|
+
this.fingerprints.set(s.id, fingerprint(out));
|
|
319
|
+
return out;
|
|
320
|
+
}
|
|
321
|
+
/** Whether a server config references any secret. */
|
|
322
|
+
static usesSecrets(s) {
|
|
323
|
+
const vals = [...Object.values(s.env ?? {}), ...Object.values(s.headers ?? {}), s.url ?? '', ...(s.args ?? [])];
|
|
324
|
+
return vals.some((v) => hasSecretRef(v));
|
|
325
|
+
}
|
|
326
|
+
/** Re-resolve a server's references bypassing the cache; returns the new config when its credentials changed. */
|
|
327
|
+
async rotateServer(s) {
|
|
328
|
+
const before = this.fingerprints.get(s.id);
|
|
329
|
+
const next = await this.resolveServer(s, true);
|
|
330
|
+
return before !== undefined && before !== this.fingerprints.get(s.id) ? next : undefined;
|
|
331
|
+
}
|
|
332
|
+
/** Per-call injection values for a server (`inject:`), with `{tenant}` / `{client}` filled in. */
|
|
333
|
+
async injections(s, ctx) {
|
|
334
|
+
const out = [];
|
|
335
|
+
for (const inj of s?.inject ?? []) {
|
|
336
|
+
if (inj.ref.includes('{tenant}') && !ctx.tenant) {
|
|
337
|
+
if (inj.required !== false)
|
|
338
|
+
throw new Error(`Server "${s.id}" needs a tenant to inject ${inj.argument ?? inj.meta}`);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const vars = { tenant: ctx.tenant ?? '', client: (ctx.clientId ?? 'anonymous').replace(/[^A-Za-z0-9_.-]/g, '_') };
|
|
342
|
+
const value = await this.interpolate(inj.ref, { vars, user: `server:${s.id}` });
|
|
343
|
+
out.push({ ...(inj.argument ? { argument: inj.argument } : {}), ...(inj.meta ? { meta: inj.meta } : {}), value: inj.format ? inj.format.split('{value}').join(value) : value });
|
|
344
|
+
}
|
|
345
|
+
return out;
|
|
346
|
+
}
|
|
347
|
+
/** Start periodic rotation; `onRotated` reconnects a server whose credentials changed. */
|
|
348
|
+
startRotation(servers, onRotated) {
|
|
349
|
+
this.stopRotation();
|
|
350
|
+
const sec = this.config()?.rotation?.intervalSeconds;
|
|
351
|
+
if (!sec)
|
|
352
|
+
return;
|
|
353
|
+
this.timer = setInterval(() => void this.rotateAll(servers(), onRotated), sec * 1000);
|
|
354
|
+
this.timer.unref();
|
|
355
|
+
}
|
|
356
|
+
async rotateAll(servers, onRotated) {
|
|
357
|
+
const changed = [];
|
|
358
|
+
for (const s of servers) {
|
|
359
|
+
if (s.enabled === false || !SecretManager.usesSecrets(s))
|
|
360
|
+
continue;
|
|
361
|
+
try {
|
|
362
|
+
const next = await this.rotateServer(s);
|
|
363
|
+
if (next) {
|
|
364
|
+
changed.push(s.id);
|
|
365
|
+
logger.info(`Credentials of "${s.id}" rotated; reconnecting`);
|
|
366
|
+
await onRotated(next);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
catch (err) {
|
|
370
|
+
logger.warn(`Secret rotation for "${s.id}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return changed;
|
|
374
|
+
}
|
|
375
|
+
stopRotation() {
|
|
376
|
+
if (this.timer)
|
|
377
|
+
clearInterval(this.timer);
|
|
378
|
+
this.timer = undefined;
|
|
379
|
+
}
|
|
380
|
+
/** Status of every reference seen so far — never the values. */
|
|
381
|
+
status() {
|
|
382
|
+
const refs = new Set([...this.cache.keys(), ...this.errors.keys(), ...this.usedBy.keys()]);
|
|
383
|
+
return [...refs].sort().map((ref) => {
|
|
384
|
+
const p = parseSecretRef(ref);
|
|
385
|
+
const c = this.cache.get(ref);
|
|
386
|
+
const r = this.rotated.get(ref);
|
|
387
|
+
return {
|
|
388
|
+
ref,
|
|
389
|
+
provider: p.provider,
|
|
390
|
+
type: this.providers.get(p.provider)?.type ?? 'unknown',
|
|
391
|
+
version: c?.version ?? 0,
|
|
392
|
+
...(c ? { fetchedAt: new Date(c.fetchedAt).toISOString() } : {}),
|
|
393
|
+
...(r ? { rotatedAt: new Date(r).toISOString() } : {}),
|
|
394
|
+
...(this.errors.has(ref) ? { error: this.errors.get(ref) } : {}),
|
|
395
|
+
usedBy: [...(this.usedBy.get(ref) ?? [])].sort(),
|
|
396
|
+
};
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
providerList() {
|
|
400
|
+
return [...this.providers.values()].map((p) => ({ id: p.id, type: p.type }));
|
|
401
|
+
}
|
|
402
|
+
/** Every resolved value (for log redaction). */
|
|
403
|
+
values() {
|
|
404
|
+
return [...this.cache.values()].map((c) => c.value).filter((v) => v.length >= 4);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function fingerprint(s) {
|
|
408
|
+
return sha256hex(JSON.stringify([s.env ?? {}, s.headers ?? {}, s.url ?? '', s.args ?? []]));
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/secrets/index.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -78,6 +78,10 @@ export interface McpServerConfig {
|
|
|
78
78
|
loadBalancing?: LoadBalancingConfig;
|
|
79
79
|
/** Relative weight for `strategy: weighted` (default 1). */
|
|
80
80
|
weight?: number;
|
|
81
|
+
/** Relative cost per call, for `strategy: smart` (3.4). */
|
|
82
|
+
cost?: number;
|
|
83
|
+
/** Per-call credentials from `secrets:` providers, per tenant / client (3.5). */
|
|
84
|
+
inject?: SecretInjection[];
|
|
81
85
|
/** Set on the internal replica servers (`<id>~<n>`): id of the logical server. */
|
|
82
86
|
replicaOf?: string;
|
|
83
87
|
}
|
|
@@ -91,11 +95,19 @@ export interface ReplicaConfig {
|
|
|
91
95
|
env?: Record<string, string>;
|
|
92
96
|
headers?: Record<string, string>;
|
|
93
97
|
weight?: number;
|
|
98
|
+
/** Relative cost per call, for `strategy: smart` (3.4). */
|
|
99
|
+
cost?: number;
|
|
94
100
|
enabled?: boolean;
|
|
95
101
|
}
|
|
96
102
|
export interface LoadBalancingConfig {
|
|
97
|
-
/** `round-robin` (default), `random`, `weighted`, `least-latency
|
|
98
|
-
strategy?: 'round-robin' | 'random' | 'weighted' | 'least-latency' | 'failover';
|
|
103
|
+
/** `round-robin` (default), `random`, `weighted`, `least-latency`, `failover` (primary first) or `smart` (3.4). */
|
|
104
|
+
strategy?: 'round-robin' | 'random' | 'weighted' | 'least-latency' | 'failover' | 'smart';
|
|
105
|
+
/** `smart` only: weights of the score terms (defaults latency 1, errorRate 1, cost 0). */
|
|
106
|
+
score?: {
|
|
107
|
+
latency?: number;
|
|
108
|
+
errorRate?: number;
|
|
109
|
+
cost?: number;
|
|
110
|
+
};
|
|
99
111
|
/** Failure kinds retried on the next member (default `[not-connected]`; `timeout` / `error` may re-run a tool). */
|
|
100
112
|
failoverOn?: Array<'not-connected' | 'timeout' | 'error'>;
|
|
101
113
|
/** Extra attempts per call (default: members - 1). */
|
|
@@ -180,6 +192,10 @@ export interface GatewayConfig {
|
|
|
180
192
|
cache?: CacheConfig;
|
|
181
193
|
/** Request capture + replay / debugger (3.2). Off by default. */
|
|
182
194
|
replay?: ReplayConfig;
|
|
195
|
+
/** Secret providers (Vault / KMS / env / file) and rotation (3.5). */
|
|
196
|
+
secrets?: SecretsConfig;
|
|
197
|
+
/** Traffic splits: canary / A-B across servers (3.4). */
|
|
198
|
+
routing?: RoutingConfig;
|
|
183
199
|
/** Plugins (hooks: onRequest, onToolCall before policy, onResponse after the output filter). */
|
|
184
200
|
plugins?: PluginConfig[];
|
|
185
201
|
/** OpenAI-compatible tools proxy (`/openai/v1/tools`, `/tool_calls`, `/chat/completions`). */
|
|
@@ -435,6 +451,81 @@ export interface McpEndpointConfig {
|
|
|
435
451
|
passthrough?: McpPassthroughConfig;
|
|
436
452
|
}
|
|
437
453
|
/** Which upstream→client requests are relayed to the downstream client that made the call (3.1). */
|
|
454
|
+
/** Secrets management (3.5). */
|
|
455
|
+
export interface SecretsConfig {
|
|
456
|
+
providers?: SecretProviderConfig[];
|
|
457
|
+
/** How long a resolved value is cached (default 300 s). */
|
|
458
|
+
cacheSeconds?: number;
|
|
459
|
+
/** Re-resolve server credentials periodically and reconnect servers whose credentials changed. */
|
|
460
|
+
rotation?: {
|
|
461
|
+
intervalSeconds?: number;
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
export interface SecretProviderConfig {
|
|
465
|
+
/** Referenced as `secret://<id>/...`. */
|
|
466
|
+
id: string;
|
|
467
|
+
type: 'vault' | 'aws-kms' | 'gcp-kms' | 'env' | 'file';
|
|
468
|
+
/** vault: server address. */
|
|
469
|
+
address?: string;
|
|
470
|
+
/** vault: token; gcp-kms: OAuth access token. */
|
|
471
|
+
token?: string;
|
|
472
|
+
/** vault: AppRole login (instead of token). */
|
|
473
|
+
roleId?: string;
|
|
474
|
+
secretId?: string;
|
|
475
|
+
/** vault: KV v2 mount (default `secret`). */
|
|
476
|
+
mount?: string;
|
|
477
|
+
namespace?: string;
|
|
478
|
+
/** aws-kms. */
|
|
479
|
+
region?: string;
|
|
480
|
+
keyId?: string;
|
|
481
|
+
accessKeyId?: string;
|
|
482
|
+
secretAccessKey?: string;
|
|
483
|
+
sessionToken?: string;
|
|
484
|
+
/** aws-kms / gcp-kms: API endpoint override. */
|
|
485
|
+
endpoint?: string;
|
|
486
|
+
/** file: base directory (default: the config directory). */
|
|
487
|
+
baseDir?: string;
|
|
488
|
+
}
|
|
489
|
+
/** One per-call credential injected into a server's calls (3.5). */
|
|
490
|
+
export interface SecretInjection {
|
|
491
|
+
/** `secret://…` reference; `{tenant}` / `{client}` are replaced per call. */
|
|
492
|
+
ref: string;
|
|
493
|
+
/** Tool argument to set (tools only). */
|
|
494
|
+
argument?: string;
|
|
495
|
+
/** `_meta` key to set. */
|
|
496
|
+
meta?: string;
|
|
497
|
+
/** e.g. `Bearer {value}`. */
|
|
498
|
+
format?: string;
|
|
499
|
+
/** Refuse the call when `{tenant}` is used and the caller has no tenant (default true). */
|
|
500
|
+
required?: boolean;
|
|
501
|
+
}
|
|
502
|
+
/** Smart routing (3.4). */
|
|
503
|
+
export interface RoutingConfig {
|
|
504
|
+
splits?: TrafficSplitConfig[];
|
|
505
|
+
}
|
|
506
|
+
/** One traffic split: calls for `server` (optionally only `tools`) spread over `variants` by weight. */
|
|
507
|
+
export interface TrafficSplitConfig {
|
|
508
|
+
name: string;
|
|
509
|
+
/** Server id the clients call. */
|
|
510
|
+
server: string;
|
|
511
|
+
/** Tool globs the split applies to (default: every tool). */
|
|
512
|
+
tools?: string[];
|
|
513
|
+
/** `client` (default): a client always gets the same variant; `none`: per call. */
|
|
514
|
+
sticky?: 'client' | 'none';
|
|
515
|
+
enabled?: boolean;
|
|
516
|
+
variants: Array<{
|
|
517
|
+
/** Server id that serves this share (the baseline is usually `server` itself). */
|
|
518
|
+
server: string;
|
|
519
|
+
weight: number;
|
|
520
|
+
label?: string;
|
|
521
|
+
/** Automatic rollback of this variant (weight 0) when a limit is crossed after `minCalls` (default 20). */
|
|
522
|
+
guard?: {
|
|
523
|
+
maxErrorRate?: number;
|
|
524
|
+
maxLatencyMs?: number;
|
|
525
|
+
minCalls?: number;
|
|
526
|
+
};
|
|
527
|
+
}>;
|
|
528
|
+
}
|
|
438
529
|
/** Request capture for the replay debugger (3.2). */
|
|
439
530
|
export interface ReplayConfig {
|
|
440
531
|
/** Keep redacted arguments / results of recent calls in memory and allow replays (default false). */
|