@winstonsayno/mcp-gateway 1.0.1 → 1.2.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 +96 -0
- package/README.md +46 -10
- package/dashboard/README.md +64 -15
- package/dashboard/index.html +1568 -419
- package/dist/auth/middleware.d.ts +29 -0
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +142 -18
- package/dist/auth/middleware.js.map +1 -1
- package/dist/cli.js +54 -1
- package/dist/cli.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +110 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/gateway/api.d.ts +5 -0
- package/dist/gateway/api.d.ts.map +1 -1
- package/dist/gateway/api.js +86 -4
- package/dist/gateway/api.js.map +1 -1
- package/dist/gateway/index.d.ts +10 -1
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +82 -5
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/live.d.ts +85 -0
- package/dist/gateway/live.d.ts.map +1 -0
- package/dist/gateway/live.js +206 -0
- package/dist/gateway/live.js.map +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/catalog.d.ts +1 -1
- package/dist/mcp/endpoint.d.ts +46 -1
- package/dist/mcp/endpoint.d.ts.map +1 -1
- package/dist/mcp/endpoint.js +312 -10
- package/dist/mcp/endpoint.js.map +1 -1
- package/dist/middleware/error-handler.d.ts +10 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +17 -3
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/monitor/index.d.ts.map +1 -1
- package/dist/monitor/index.js +5 -0
- package/dist/monitor/index.js.map +1 -1
- package/dist/proxy/index.d.ts +15 -0
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +44 -4
- package/dist/proxy/index.js.map +1 -1
- package/dist/security/headers.d.ts +23 -0
- package/dist/security/headers.d.ts.map +1 -0
- package/dist/security/headers.js +71 -0
- package/dist/security/headers.js.map +1 -0
- package/dist/security/lockout.d.ts +41 -0
- package/dist/security/lockout.d.ts.map +1 -0
- package/dist/security/lockout.js +117 -0
- package/dist/security/lockout.js.map +1 -0
- package/dist/security/network.d.ts +31 -0
- package/dist/security/network.d.ts.map +1 -0
- package/dist/security/network.js +147 -0
- package/dist/security/network.js.map +1 -0
- package/dist/security/posture.d.ts +18 -0
- package/dist/security/posture.d.ts.map +1 -0
- package/dist/security/posture.js +73 -0
- package/dist/security/posture.js.map +1 -0
- package/dist/security/redact.d.ts +34 -0
- package/dist/security/redact.d.ts.map +1 -0
- package/dist/security/redact.js +115 -0
- package/dist/security/redact.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +4 -2
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/types.d.ts +81 -2
- package/dist/utils/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -10,8 +10,17 @@
|
|
|
10
10
|
* - The client id attached to a request is a hash fingerprint of the key,
|
|
11
11
|
* never a prefix of the key itself (prefixes were leaking into logs and the
|
|
12
12
|
* /requests endpoint, and keys sharing a prefix shared a rate-limit bucket).
|
|
13
|
+
* - Keys may be stored as SHA-256 digests (`sha256:<hex>`), so the config
|
|
14
|
+
* file never holds a usable key. A digest key and its plain form produce
|
|
15
|
+
* the same client id.
|
|
16
|
+
* - Keys can expire (`expiresAt`) or be switched off (`disabled`).
|
|
17
|
+
* - JWTs: HMAC secret, PEM public key or JWKS URL; algorithm allowlist that
|
|
18
|
+
* never mixes HMAC and asymmetric algorithms; optional issuer / audience /
|
|
19
|
+
* exp / max-age checks and clock tolerance.
|
|
13
20
|
*/
|
|
21
|
+
import { type KeyObject } from 'crypto';
|
|
14
22
|
import type { Request, RequestHandler } from 'express';
|
|
23
|
+
import { type JWTVerifyGetKey, type JWTVerifyOptions } from 'jose';
|
|
15
24
|
import type { ApiKeyConfig, AuthConfig } from '../utils/types.js';
|
|
16
25
|
import { type AccessScope } from './scopes.js';
|
|
17
26
|
export type AuthedRequest = Request & {
|
|
@@ -34,10 +43,30 @@ export type AuthMiddleware = RequestHandler & {
|
|
|
34
43
|
};
|
|
35
44
|
/** Normalise `auth.apiKeys` entries (plain strings or objects). */
|
|
36
45
|
export declare function normalizeApiKeys(keys: AuthConfig['apiKeys']): ApiKeyConfig[];
|
|
46
|
+
export declare const HMAC_ALGORITHMS: string[];
|
|
47
|
+
export declare const ASYMMETRIC_ALGORITHMS: string[];
|
|
48
|
+
/** Whether a configured key is a `sha256:<hex>` digest rather than the key itself. */
|
|
49
|
+
export declare function isHashedKey(key: string): boolean;
|
|
50
|
+
/** `sha256:<hex>` digest of a key, the form to store in the config file. */
|
|
51
|
+
export declare function hashApiKey(key: string): string;
|
|
52
|
+
/** Expiry of a key entry as epoch ms (undefined = never; NaN for an unparsable date). */
|
|
53
|
+
export declare function keyExpiry(entry: ApiKeyConfig): number | undefined;
|
|
54
|
+
/** Why a key is currently unusable, or undefined when it is active. */
|
|
55
|
+
export declare function keyInactiveReason(entry: ApiKeyConfig, now?: number): 'disabled' | 'expired' | undefined;
|
|
37
56
|
export declare function createAuthMiddleware(config?: AuthConfig): AuthMiddleware;
|
|
38
57
|
export declare function fingerprint(key: string): string;
|
|
39
58
|
/** Constant-time membership check against a pre-hashed key list. */
|
|
40
59
|
export declare function matchesAnyKey(candidate: string, keyDigests: Buffer[]): boolean;
|
|
41
60
|
/** Constant-time lookup: index of the matching key digest, or -1. */
|
|
42
61
|
export declare function matchKeyIndex(candidate: string, keyDigests: Buffer[]): number;
|
|
62
|
+
export interface JwtVerifier {
|
|
63
|
+
key: Uint8Array | KeyObject | JWTVerifyGetKey;
|
|
64
|
+
options: JWTVerifyOptions;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Key source + verification options for the `jwt` strategy. Throws on
|
|
68
|
+
* misconfiguration (missing / conflicting key sources, algorithms that do not
|
|
69
|
+
* fit the key type, non-HTTPS JWKS URL).
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildJwtVerifier(config: AuthConfig): JwtVerifier;
|
|
43
72
|
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAgD,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAA0B,cAAc,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAiC,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yFAAyF;IACzF,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,kGAAkG;AAClG,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG;IAC5C;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;CAC3F,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,YAAY,EAAE,CAI5E;AAWD,eAAO,MAAM,eAAe,UAA8B,CAAC;AAC3D,eAAO,MAAM,qBAAqB,UAKjC,CAAC;AAIF,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAGjE;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,SAAa,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAK3G;AAED,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,cAAc,CA4BxE;AAYD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAE9E;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ7E;AAsDD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,UAAU,GAAG,SAAS,GAAG,eAAe,CAAC;IAC9C,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,CAyDhE"}
|
package/dist/auth/middleware.js
CHANGED
|
@@ -10,9 +10,16 @@
|
|
|
10
10
|
* - The client id attached to a request is a hash fingerprint of the key,
|
|
11
11
|
* never a prefix of the key itself (prefixes were leaking into logs and the
|
|
12
12
|
* /requests endpoint, and keys sharing a prefix shared a rate-limit bucket).
|
|
13
|
+
* - Keys may be stored as SHA-256 digests (`sha256:<hex>`), so the config
|
|
14
|
+
* file never holds a usable key. A digest key and its plain form produce
|
|
15
|
+
* the same client id.
|
|
16
|
+
* - Keys can expire (`expiresAt`) or be switched off (`disabled`).
|
|
17
|
+
* - JWTs: HMAC secret, PEM public key or JWKS URL; algorithm allowlist that
|
|
18
|
+
* never mixes HMAC and asymmetric algorithms; optional issuer / audience /
|
|
19
|
+
* exp / max-age checks and clock tolerance.
|
|
13
20
|
*/
|
|
14
|
-
import { createHash, timingSafeEqual } from 'crypto';
|
|
15
|
-
import { jwtVerify } from 'jose';
|
|
21
|
+
import { createHash, createPublicKey, timingSafeEqual } from 'crypto';
|
|
22
|
+
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
|
16
23
|
import { logger } from '../utils/logger.js';
|
|
17
24
|
import { scopeFromJwt } from './scopes.js';
|
|
18
25
|
/** Normalise `auth.apiKeys` entries (plain strings or objects). */
|
|
@@ -33,7 +40,37 @@ function scopeOf(entry) {
|
|
|
33
40
|
scope.rateLimit = { ...entry.rateLimit, perKey: true };
|
|
34
41
|
return Object.keys(scope).length > 0 ? scope : undefined;
|
|
35
42
|
}
|
|
36
|
-
const
|
|
43
|
+
export const HMAC_ALGORITHMS = ['HS256', 'HS384', 'HS512'];
|
|
44
|
+
export const ASYMMETRIC_ALGORITHMS = [
|
|
45
|
+
'RS256', 'RS384', 'RS512',
|
|
46
|
+
'PS256', 'PS384', 'PS512',
|
|
47
|
+
'ES256', 'ES384', 'ES512',
|
|
48
|
+
'EdDSA',
|
|
49
|
+
];
|
|
50
|
+
const HASHED_KEY_RE = /^sha256:([0-9a-f]{64})$/i;
|
|
51
|
+
/** Whether a configured key is a `sha256:<hex>` digest rather than the key itself. */
|
|
52
|
+
export function isHashedKey(key) {
|
|
53
|
+
return HASHED_KEY_RE.test(key);
|
|
54
|
+
}
|
|
55
|
+
/** `sha256:<hex>` digest of a key, the form to store in the config file. */
|
|
56
|
+
export function hashApiKey(key) {
|
|
57
|
+
return `sha256:${createHash('sha256').update(key, 'utf8').digest('hex')}`;
|
|
58
|
+
}
|
|
59
|
+
/** Expiry of a key entry as epoch ms (undefined = never; NaN for an unparsable date). */
|
|
60
|
+
export function keyExpiry(entry) {
|
|
61
|
+
if (entry.expiresAt === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
return Date.parse(entry.expiresAt);
|
|
64
|
+
}
|
|
65
|
+
/** Why a key is currently unusable, or undefined when it is active. */
|
|
66
|
+
export function keyInactiveReason(entry, now = Date.now()) {
|
|
67
|
+
if (entry.disabled)
|
|
68
|
+
return 'disabled';
|
|
69
|
+
const exp = keyExpiry(entry);
|
|
70
|
+
if (exp !== undefined && !(exp > now))
|
|
71
|
+
return 'expired';
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
37
74
|
export function createAuthMiddleware(config) {
|
|
38
75
|
if (!config || config.strategy === 'none') {
|
|
39
76
|
const none = (_req, _res, next) => next();
|
|
@@ -56,15 +93,8 @@ export function createAuthMiddleware(config) {
|
|
|
56
93
|
}
|
|
57
94
|
return apiKeyMiddleware(keys);
|
|
58
95
|
}
|
|
59
|
-
case 'jwt':
|
|
60
|
-
|
|
61
|
-
throw new Error('auth.strategy is "jwt" but auth.jwtSecret is not configured');
|
|
62
|
-
}
|
|
63
|
-
if (config.jwtSecret.length < 32) {
|
|
64
|
-
logger.warn('auth.jwtSecret is shorter than 32 characters; use a longer random secret');
|
|
65
|
-
}
|
|
66
|
-
return jwtMiddleware(config.jwtSecret);
|
|
67
|
-
}
|
|
96
|
+
case 'jwt':
|
|
97
|
+
return jwtMiddleware(buildJwtVerifier(config));
|
|
68
98
|
default:
|
|
69
99
|
// Fail closed. Previously this fell back to *no auth*, so configuring the
|
|
70
100
|
// advertised-but-unimplemented "oauth2" strategy exposed every endpoint.
|
|
@@ -74,7 +104,15 @@ export function createAuthMiddleware(config) {
|
|
|
74
104
|
function digest(value) {
|
|
75
105
|
return createHash('sha256').update(value, 'utf8').digest();
|
|
76
106
|
}
|
|
107
|
+
/** Digest of a configured key: the stored digest for `sha256:` keys, else SHA-256 of the key. */
|
|
108
|
+
function configuredDigest(key) {
|
|
109
|
+
const m = HASHED_KEY_RE.exec(key);
|
|
110
|
+
return m ? Buffer.from(m[1], 'hex') : digest(key);
|
|
111
|
+
}
|
|
77
112
|
export function fingerprint(key) {
|
|
113
|
+
const m = HASHED_KEY_RE.exec(key);
|
|
114
|
+
if (m)
|
|
115
|
+
return m[1].toLowerCase().slice(0, 12);
|
|
78
116
|
return createHash('sha256').update(key, 'utf8').digest('hex').slice(0, 12);
|
|
79
117
|
}
|
|
80
118
|
/** Constant-time membership check against a pre-hashed key list. */
|
|
@@ -103,7 +141,12 @@ function extractKey(req) {
|
|
|
103
141
|
return undefined;
|
|
104
142
|
}
|
|
105
143
|
function apiKeyMiddleware(entries) {
|
|
106
|
-
const
|
|
144
|
+
for (const e of entries) {
|
|
145
|
+
if (e.expiresAt !== undefined && Number.isNaN(keyExpiry(e))) {
|
|
146
|
+
throw new Error(`auth.apiKeys: invalid expiresAt "${e.expiresAt}"${e.name ? ` (key "${e.name}")` : ''}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const keyDigests = entries.map((e) => configuredDigest(e.key));
|
|
107
150
|
const clients = entries.map((e) => ({
|
|
108
151
|
clientId: e.name ? `key:${e.name}` : `key:${fingerprint(e.key)}`,
|
|
109
152
|
scope: scopeOf(e),
|
|
@@ -118,6 +161,12 @@ function apiKeyMiddleware(entries) {
|
|
|
118
161
|
return;
|
|
119
162
|
}
|
|
120
163
|
const client = clients[index];
|
|
164
|
+
const inactive = keyInactiveReason(entries[index]);
|
|
165
|
+
if (inactive) {
|
|
166
|
+
logger.warn(`Unauthorized request from ${req.ip}: API key ${client.clientId} is ${inactive}`);
|
|
167
|
+
res.status(401).json({ error: 'Unauthorized', message: 'Valid API key required' });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
121
170
|
req.clientId = client.clientId;
|
|
122
171
|
if (client.scope)
|
|
123
172
|
req.scope = client.scope;
|
|
@@ -125,12 +174,87 @@ function apiKeyMiddleware(entries) {
|
|
|
125
174
|
};
|
|
126
175
|
mw.resolveClient = (clientId) => {
|
|
127
176
|
const c = clientId ? byClientId.get(clientId) : undefined;
|
|
128
|
-
|
|
177
|
+
if (!c || keyInactiveReason(entries[clients.indexOf(c)]))
|
|
178
|
+
return { known: false };
|
|
179
|
+
return { known: true, scope: c.scope };
|
|
129
180
|
};
|
|
130
181
|
return mw;
|
|
131
182
|
}
|
|
132
|
-
|
|
133
|
-
|
|
183
|
+
const asList = (v) => (v === undefined ? undefined : Array.isArray(v) ? v : [v]);
|
|
184
|
+
/**
|
|
185
|
+
* Key source + verification options for the `jwt` strategy. Throws on
|
|
186
|
+
* misconfiguration (missing / conflicting key sources, algorithms that do not
|
|
187
|
+
* fit the key type, non-HTTPS JWKS URL).
|
|
188
|
+
*/
|
|
189
|
+
export function buildJwtVerifier(config) {
|
|
190
|
+
const jwt = config.jwt ?? {};
|
|
191
|
+
const sources = [config.jwtSecret ? 'jwtSecret' : '', jwt.publicKey ? 'jwt.publicKey' : '', jwt.jwksUrl ? 'jwt.jwksUrl' : ''].filter(Boolean);
|
|
192
|
+
if (sources.length === 0) {
|
|
193
|
+
throw new Error('auth.strategy is "jwt" but none of auth.jwtSecret, auth.jwt.publicKey or auth.jwt.jwksUrl is configured');
|
|
194
|
+
}
|
|
195
|
+
if (sources.length > 1)
|
|
196
|
+
throw new Error(`auth: configure only one of ${sources.join(', ')}`);
|
|
197
|
+
const hmac = !!config.jwtSecret;
|
|
198
|
+
const allowed = hmac ? HMAC_ALGORITHMS : ASYMMETRIC_ALGORITHMS;
|
|
199
|
+
const algorithms = jwt.algorithms ?? allowed;
|
|
200
|
+
if (algorithms.length === 0)
|
|
201
|
+
throw new Error('auth.jwt.algorithms must not be empty');
|
|
202
|
+
const bad = algorithms.filter((a) => !allowed.includes(a));
|
|
203
|
+
if (bad.length > 0) {
|
|
204
|
+
throw new Error(`auth.jwt.algorithms: ${bad.join(', ')} cannot be used with ${sources[0]} (allowed: ${allowed.join(', ')})`);
|
|
205
|
+
}
|
|
206
|
+
let key;
|
|
207
|
+
if (config.jwtSecret) {
|
|
208
|
+
if (config.jwtSecret.length < 32) {
|
|
209
|
+
logger.warn('auth.jwtSecret is shorter than 32 characters; use a longer random secret');
|
|
210
|
+
}
|
|
211
|
+
key = new TextEncoder().encode(config.jwtSecret);
|
|
212
|
+
}
|
|
213
|
+
else if (jwt.publicKey) {
|
|
214
|
+
try {
|
|
215
|
+
key = createPublicKey(jwt.publicKey);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
throw new Error(`auth.jwt.publicKey is not a valid PEM public key: ${err instanceof Error ? err.message : String(err)}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
let url;
|
|
223
|
+
try {
|
|
224
|
+
url = new URL(jwt.jwksUrl);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
throw new Error(`auth.jwt.jwksUrl is not a valid URL: ${jwt.jwksUrl}`);
|
|
228
|
+
}
|
|
229
|
+
const local = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
|
|
230
|
+
if (url.protocol !== 'https:' && !(url.protocol === 'http:' && local)) {
|
|
231
|
+
throw new Error('auth.jwt.jwksUrl must use https:// (http:// is only allowed for localhost)');
|
|
232
|
+
}
|
|
233
|
+
key = createRemoteJWKSet(url, {
|
|
234
|
+
cacheMaxAge: (jwt.jwksCacheSeconds ?? 600) * 1000,
|
|
235
|
+
cooldownDuration: 30_000,
|
|
236
|
+
timeoutDuration: 5_000,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
const options = { algorithms };
|
|
240
|
+
const issuer = asList(jwt.issuer);
|
|
241
|
+
const audience = asList(jwt.audience);
|
|
242
|
+
if (issuer)
|
|
243
|
+
options.issuer = issuer;
|
|
244
|
+
if (audience)
|
|
245
|
+
options.audience = audience;
|
|
246
|
+
if (jwt.clockToleranceSeconds)
|
|
247
|
+
options.clockTolerance = jwt.clockToleranceSeconds;
|
|
248
|
+
if (jwt.requireExp)
|
|
249
|
+
options.requiredClaims = ['exp'];
|
|
250
|
+
if (jwt.maxTokenAgeSeconds)
|
|
251
|
+
options.maxTokenAge = jwt.maxTokenAgeSeconds;
|
|
252
|
+
return { key, options };
|
|
253
|
+
}
|
|
254
|
+
function jwtMiddleware(verifier) {
|
|
255
|
+
const verify = (token) => typeof verifier.key === 'function'
|
|
256
|
+
? jwtVerify(token, verifier.key, verifier.options)
|
|
257
|
+
: jwtVerify(token, verifier.key, verifier.options);
|
|
134
258
|
return (req, res, next) => {
|
|
135
259
|
const authHeader = req.headers.authorization;
|
|
136
260
|
if (!authHeader || !/^Bearer /i.test(authHeader)) {
|
|
@@ -140,7 +264,7 @@ function jwtMiddleware(secret) {
|
|
|
140
264
|
const token = authHeader.slice(7).trim();
|
|
141
265
|
// Two-argument then(): an error thrown downstream of next() must not be
|
|
142
266
|
// misreported as an auth failure.
|
|
143
|
-
|
|
267
|
+
verify(token).then(({ payload }) => {
|
|
144
268
|
req.jwtPayload = payload;
|
|
145
269
|
req.clientId = `jwt:${String(payload.sub ?? 'unknown')}`;
|
|
146
270
|
const scope = scopeFromJwt(payload);
|
|
@@ -148,7 +272,7 @@ function jwtMiddleware(secret) {
|
|
|
148
272
|
req.scope = scope;
|
|
149
273
|
next();
|
|
150
274
|
}, (err) => {
|
|
151
|
-
logger.warn(`JWT verification failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
275
|
+
logger.warn(`JWT verification failed from ${req.ip}: ${err instanceof Error ? err.message : String(err)}`);
|
|
152
276
|
if (!res.headersSent) {
|
|
153
277
|
res.status(401).json({ error: 'Unauthorized', message: 'Invalid or expired token' });
|
|
154
278
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,9 @@ import { ConfigWatcher } from './config/watcher.js';
|
|
|
11
11
|
import { Gateway } from './gateway/index.js';
|
|
12
12
|
import { logger } from './utils/logger.js';
|
|
13
13
|
import { VERSION } from './utils/version.js';
|
|
14
|
+
import { randomBytes } from 'crypto';
|
|
15
|
+
import { hashApiKey } from './auth/middleware.js';
|
|
16
|
+
import { securityWarnings } from './security/posture.js';
|
|
14
17
|
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
15
18
|
const program = new Command();
|
|
16
19
|
program
|
|
@@ -107,8 +110,9 @@ program
|
|
|
107
110
|
// ─── validate ─────────────────────────────────────────────────────────────────
|
|
108
111
|
program
|
|
109
112
|
.command('validate')
|
|
110
|
-
.description('Validate a configuration file')
|
|
113
|
+
.description('Validate a configuration file and report security warnings')
|
|
111
114
|
.option('-c, --config <path>', 'Path to config file')
|
|
115
|
+
.option('--strict', 'Exit with code 2 when there are security warnings')
|
|
112
116
|
.action(async (options) => {
|
|
113
117
|
try {
|
|
114
118
|
const config = await loadConfig(options.config);
|
|
@@ -116,12 +120,61 @@ program
|
|
|
116
120
|
console.log(` Port: ${config.port}`);
|
|
117
121
|
console.log(` Servers: ${config.servers.length}`);
|
|
118
122
|
console.log(` Auth: ${config.auth?.strategy ?? 'none'}`);
|
|
123
|
+
const warnings = securityWarnings(config);
|
|
124
|
+
if (warnings.length > 0) {
|
|
125
|
+
console.log('\nSecurity:');
|
|
126
|
+
for (const w of warnings)
|
|
127
|
+
console.log(` ${w.level === 'warn' ? '!' : '-'} ${w.message}`);
|
|
128
|
+
if (options.strict && warnings.some((w) => w.level === 'warn'))
|
|
129
|
+
process.exit(2);
|
|
130
|
+
}
|
|
119
131
|
}
|
|
120
132
|
catch (err) {
|
|
121
133
|
logger.error(`Invalid configuration: ${err instanceof Error ? err.message : String(err)}`);
|
|
122
134
|
process.exit(1);
|
|
123
135
|
}
|
|
124
136
|
});
|
|
137
|
+
// ─── keys ─────────────────────────────────────────────────────────────────────
|
|
138
|
+
async function readStdin() {
|
|
139
|
+
const chunks = [];
|
|
140
|
+
for await (const c of process.stdin)
|
|
141
|
+
chunks.push(c);
|
|
142
|
+
return Buffer.concat(chunks).toString('utf8').replace(/\r?\n$/, '');
|
|
143
|
+
}
|
|
144
|
+
program
|
|
145
|
+
.command('hash-key')
|
|
146
|
+
.description('Print the sha256:<hex> digest of an API key, for auth.apiKeys (reads stdin when no key is given)')
|
|
147
|
+
.argument('[key]', 'The key (prefer stdin so it stays out of your shell history)')
|
|
148
|
+
.action(async (key) => {
|
|
149
|
+
const value = key ?? (process.stdin.isTTY ? '' : await readStdin());
|
|
150
|
+
if (!value) {
|
|
151
|
+
logger.error('No key given. Usage: echo -n "$KEY" | mcp-gateway hash-key');
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
console.log(hashApiKey(value));
|
|
155
|
+
});
|
|
156
|
+
program
|
|
157
|
+
.command('gen-key')
|
|
158
|
+
.description('Generate a random API key and print it with its sha256 digest')
|
|
159
|
+
.option('-b, --bytes <n>', 'Random bytes (16-128)', '32')
|
|
160
|
+
.option('--prefix <prefix>', 'Key prefix (helps secret scanners and redaction)', 'mgw_')
|
|
161
|
+
.option('--json', 'Print JSON')
|
|
162
|
+
.action((options) => {
|
|
163
|
+
const bytes = Number(options.bytes);
|
|
164
|
+
if (!Number.isInteger(bytes) || bytes < 16 || bytes > 128) {
|
|
165
|
+
logger.error(`Invalid --bytes "${options.bytes}" (16-128)`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
const key = `${options.prefix}${randomBytes(bytes).toString('base64url')}`;
|
|
169
|
+
const hash = hashApiKey(key);
|
|
170
|
+
if (options.json) {
|
|
171
|
+
console.log(JSON.stringify({ key, hash }));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
console.log(`key: ${key}`);
|
|
175
|
+
console.log(`hash: ${hash}`);
|
|
176
|
+
console.log('\nGive the key to the client; put the hash in auth.apiKeys. The key is not shown again.');
|
|
177
|
+
});
|
|
125
178
|
program.parse(process.argv);
|
|
126
179
|
if (!process.argv.slice(2).length) {
|
|
127
180
|
program.outputHelp();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAuSvD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMzE;AAED,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAsB5E;AAkCD,wBAAgB,qBAAqB,IAAI,MAAM,CAiH9C"}
|
package/dist/config/loader.js
CHANGED
|
@@ -8,6 +8,9 @@ import { resolve } from 'path';
|
|
|
8
8
|
import { parse as parseYaml } from 'yaml';
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
import { expandEnv } from '../transport/channel.js';
|
|
11
|
+
import { invalidCidr } from '../security/network.js';
|
|
12
|
+
import { invalidRedactPattern } from '../security/redact.js';
|
|
13
|
+
import { ASYMMETRIC_ALGORITHMS, HMAC_ALGORITHMS } from '../auth/middleware.js';
|
|
11
14
|
// ─── Zod Schema ───────────────────────────────────────────────────────────────
|
|
12
15
|
const ReconnectSchema = z.object({
|
|
13
16
|
enabled: z.boolean().optional(),
|
|
@@ -93,6 +96,11 @@ const ApiKeySchema = z.union([
|
|
|
93
96
|
.optional(),
|
|
94
97
|
servers: PatternList.optional(),
|
|
95
98
|
tools: PatternList.optional(),
|
|
99
|
+
expiresAt: z
|
|
100
|
+
.string()
|
|
101
|
+
.refine((v) => !Number.isNaN(Date.parse(v)), 'must be an ISO 8601 date or date-time')
|
|
102
|
+
.optional(),
|
|
103
|
+
disabled: z.boolean().optional(),
|
|
96
104
|
rateLimit: z
|
|
97
105
|
.object({ limit: z.number().int().positive(), windowSeconds: z.number().positive() })
|
|
98
106
|
.strict()
|
|
@@ -100,6 +108,61 @@ const ApiKeySchema = z.union([
|
|
|
100
108
|
})
|
|
101
109
|
.strict(),
|
|
102
110
|
]);
|
|
111
|
+
const StringOrList = z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]);
|
|
112
|
+
const JwtSchema = z
|
|
113
|
+
.object({
|
|
114
|
+
issuer: StringOrList.optional(),
|
|
115
|
+
audience: StringOrList.optional(),
|
|
116
|
+
algorithms: z.array(z.enum([...HMAC_ALGORITHMS, ...ASYMMETRIC_ALGORITHMS])).min(1).optional(),
|
|
117
|
+
clockToleranceSeconds: z.number().min(0).max(3600).optional(),
|
|
118
|
+
jwksUrl: z.string().url().optional(),
|
|
119
|
+
jwksCacheSeconds: z.number().int().positive().optional(),
|
|
120
|
+
publicKey: z.string().min(1).optional(),
|
|
121
|
+
requireExp: z.boolean().optional(),
|
|
122
|
+
maxTokenAgeSeconds: z.number().int().positive().optional(),
|
|
123
|
+
})
|
|
124
|
+
.strict();
|
|
125
|
+
const LockoutSchema = z
|
|
126
|
+
.object({
|
|
127
|
+
maxFailures: z.number().int().min(1).optional(),
|
|
128
|
+
windowSeconds: z.number().int().positive().optional(),
|
|
129
|
+
lockoutSeconds: z.number().int().positive().optional(),
|
|
130
|
+
})
|
|
131
|
+
.strict();
|
|
132
|
+
const SecuritySchema = z
|
|
133
|
+
.object({
|
|
134
|
+
headers: z.boolean().default(true),
|
|
135
|
+
hsts: z
|
|
136
|
+
.union([
|
|
137
|
+
z.boolean(),
|
|
138
|
+
z.object({ maxAgeSeconds: z.number().int().min(0).optional(), includeSubDomains: z.boolean().optional() }).strict(),
|
|
139
|
+
])
|
|
140
|
+
.optional(),
|
|
141
|
+
trustProxy: z.union([z.boolean(), z.number().int().min(0), z.string().min(1), z.array(z.string().min(1))]).optional(),
|
|
142
|
+
ipAllowlist: z
|
|
143
|
+
.array(z.string().min(1))
|
|
144
|
+
.superRefine((list, ctx) => {
|
|
145
|
+
const err = invalidCidr(list);
|
|
146
|
+
if (err)
|
|
147
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: err });
|
|
148
|
+
})
|
|
149
|
+
.optional(),
|
|
150
|
+
allowedHosts: z.array(z.string().min(1)).optional(),
|
|
151
|
+
dnsRebindingProtection: z.boolean().default(false),
|
|
152
|
+
maxBodyBytes: z.number().int().min(1024).default(10 * 1024 * 1024),
|
|
153
|
+
maxToolArgumentsBytes: z.number().int().min(0).default(0),
|
|
154
|
+
authLockout: z.union([z.boolean(), LockoutSchema]).optional(),
|
|
155
|
+
redactPatterns: z
|
|
156
|
+
.array(z.string().min(1))
|
|
157
|
+
.superRefine((list, ctx) => {
|
|
158
|
+
const err = invalidRedactPattern(list);
|
|
159
|
+
if (err)
|
|
160
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: `invalid regular expression ${err}` });
|
|
161
|
+
})
|
|
162
|
+
.optional(),
|
|
163
|
+
exposeErrorDetails: z.boolean().default(false),
|
|
164
|
+
})
|
|
165
|
+
.strict();
|
|
103
166
|
const GatewayConfigSchema = z.object({
|
|
104
167
|
port: z.number().int().min(1).max(65535).default(4000),
|
|
105
168
|
host: z.string().default('0.0.0.0'),
|
|
@@ -108,6 +171,7 @@ const GatewayConfigSchema = z.object({
|
|
|
108
171
|
strategy: z.enum(['none', 'api-key', 'jwt', 'oauth2']).default('none'),
|
|
109
172
|
apiKeys: z.array(ApiKeySchema).optional(),
|
|
110
173
|
jwtSecret: z.string().optional(),
|
|
174
|
+
jwt: JwtSchema.optional(),
|
|
111
175
|
protect: z
|
|
112
176
|
.object({
|
|
113
177
|
health: z.boolean().default(false),
|
|
@@ -127,6 +191,14 @@ const GatewayConfigSchema = z.object({
|
|
|
127
191
|
names.add(k.name);
|
|
128
192
|
});
|
|
129
193
|
(a.apiKeys ?? []).forEach((k, i) => {
|
|
194
|
+
const key = keyOf(k);
|
|
195
|
+
if (/^sha256:/i.test(key) && !/^sha256:[0-9a-f]{64}$/i.test(key)) {
|
|
196
|
+
ctx.addIssue({
|
|
197
|
+
code: z.ZodIssueCode.custom,
|
|
198
|
+
path: typeof k === 'string' ? ['apiKeys', i] : ['apiKeys', i, 'key'],
|
|
199
|
+
message: '"sha256:" keys must be followed by 64 hex characters (mcp-gateway hash-key)',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
130
202
|
if (typeof k !== 'string' && k.key.length === 0) {
|
|
131
203
|
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['apiKeys', i, 'key'], message: 'is empty (unset environment variable?)' });
|
|
132
204
|
}
|
|
@@ -134,8 +206,26 @@ const GatewayConfigSchema = z.object({
|
|
|
134
206
|
if (a.strategy === 'api-key' && !(a.apiKeys ?? []).some((k) => keyOf(k).length > 0)) {
|
|
135
207
|
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['apiKeys'], message: 'at least one key is required for api-key strategy' });
|
|
136
208
|
}
|
|
137
|
-
if (a.strategy === 'jwt'
|
|
138
|
-
|
|
209
|
+
if (a.strategy === 'jwt') {
|
|
210
|
+
const sources = [a.jwtSecret, a.jwt?.publicKey, a.jwt?.jwksUrl].filter(Boolean).length;
|
|
211
|
+
if (sources === 0) {
|
|
212
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['jwtSecret'], message: 'jwt strategy needs jwtSecret, jwt.publicKey or jwt.jwksUrl' });
|
|
213
|
+
}
|
|
214
|
+
else if (sources > 1) {
|
|
215
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['jwt'], message: 'configure only one of jwtSecret, jwt.publicKey, jwt.jwksUrl' });
|
|
216
|
+
}
|
|
217
|
+
const algs = a.jwt?.algorithms;
|
|
218
|
+
if (algs && sources === 1) {
|
|
219
|
+
const allowed = a.jwtSecret ? HMAC_ALGORITHMS : ASYMMETRIC_ALGORITHMS;
|
|
220
|
+
const bad = algs.filter((x) => !allowed.includes(x));
|
|
221
|
+
if (bad.length > 0) {
|
|
222
|
+
ctx.addIssue({
|
|
223
|
+
code: z.ZodIssueCode.custom,
|
|
224
|
+
path: ['jwt', 'algorithms'],
|
|
225
|
+
message: `${bad.join(', ')} cannot be used with ${a.jwtSecret ? 'an HMAC secret' : 'a public key / JWKS'} (algorithm confusion)`,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
139
229
|
}
|
|
140
230
|
if (a.strategy === 'oauth2') {
|
|
141
231
|
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['strategy'], message: 'oauth2 is not implemented yet (refusing to start without auth)' });
|
|
@@ -181,6 +271,7 @@ const GatewayConfigSchema = z.object({
|
|
|
181
271
|
})
|
|
182
272
|
.strict()
|
|
183
273
|
.optional(),
|
|
274
|
+
security: SecuritySchema.optional(),
|
|
184
275
|
}).superRefine((c, ctx) => {
|
|
185
276
|
const seen = new Set();
|
|
186
277
|
c.servers.forEach((s, i) => {
|
|
@@ -275,10 +366,27 @@ logLevel: info
|
|
|
275
366
|
# servers: ["github", "fs-*"]
|
|
276
367
|
# tools: ["read_*", "github/create_issue"]
|
|
277
368
|
# rateLimit: { limit: 30, windowSeconds: 60 }
|
|
369
|
+
# - sha256:<64-hex-digest> # a key stored as its digest: run mcp-gateway hash-key
|
|
370
|
+
# - key: \${CI_GATEWAY_KEY}
|
|
371
|
+
# name: ci
|
|
372
|
+
# expiresAt: 2027-01-01 # rejected from this date on; "disabled: true" switches a key off
|
|
278
373
|
# protect:
|
|
279
374
|
# health: false # true = /api/v1/health requires a key (/health/live stays public)
|
|
280
375
|
# metrics: false # true = /api/v1/metrics requires a key (configure your scraper)
|
|
281
376
|
|
|
377
|
+
# Hardening (all optional; defaults shown where they exist)
|
|
378
|
+
# security:
|
|
379
|
+
# headers: true # nosniff, frame-ancestors, Referrer-Policy, CSP (dashboard: hashed inline script)
|
|
380
|
+
# hsts: false # true behind HTTPS
|
|
381
|
+
# trustProxy: false # e.g. 1 or ["10.0.0.0/8"] behind a reverse proxy (affects req.ip)
|
|
382
|
+
# ipAllowlist: ["10.0.0.0/8", "127.0.0.1"]
|
|
383
|
+
# dnsRebindingProtection: false # true: Host must be localhost / allowedHosts, /mcp only same-origin + loopback origins
|
|
384
|
+
# allowedHosts: ["gateway.example.com"]
|
|
385
|
+
# maxBodyBytes: 10485760
|
|
386
|
+
# maxToolArgumentsBytes: 0 # 0 = no limit
|
|
387
|
+
# authLockout: true # or { maxFailures: 10, windowSeconds: 300, lockoutSeconds: 900 }
|
|
388
|
+
# redactPatterns: ["internal-[0-9a-f]{32}"]
|
|
389
|
+
|
|
282
390
|
# Automatic reconnect of crashed / disconnected servers (defaults shown)
|
|
283
391
|
# reconnect:
|
|
284
392
|
# enabled: true
|