@mcp-guardian/server 1.0.1 → 1.3.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 +63 -7
- package/dist/auth/dashboard-auth.d.ts +97 -0
- package/dist/auth/dashboard-auth.d.ts.map +1 -0
- package/dist/auth/dashboard-auth.js +319 -0
- package/dist/auth/dashboard-auth.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/policy/policy-engine.d.ts +10 -0
- package/dist/policy/policy-engine.d.ts.map +1 -1
- package/dist/policy/policy-engine.js +57 -6
- package/dist/policy/policy-engine.js.map +1 -1
- package/dist/policy/shell-tokenizer.d.ts +92 -0
- package/dist/policy/shell-tokenizer.d.ts.map +1 -0
- package/dist/policy/shell-tokenizer.js +300 -0
- package/dist/policy/shell-tokenizer.js.map +1 -0
- package/dist/proxy/http-proxy-server.d.ts +3 -1
- package/dist/proxy/http-proxy-server.d.ts.map +1 -1
- package/dist/proxy/http-proxy-server.js +14 -3
- package/dist/proxy/http-proxy-server.js.map +1 -1
- package/dist/utils/dashboard-server.d.ts +14 -5
- package/dist/utils/dashboard-server.d.ts.map +1 -1
- package/dist/utils/dashboard-server.js +213 -41
- package/dist/utils/dashboard-server.js.map +1 -1
- package/dist/utils/mtls-config.d.ts +27 -0
- package/dist/utils/mtls-config.d.ts.map +1 -0
- package/dist/utils/mtls-config.js +82 -0
- package/dist/utils/mtls-config.js.map +1 -0
- package/dist/utils/payload-normalizer.d.ts +62 -0
- package/dist/utils/payload-normalizer.d.ts.map +1 -0
- package/dist/utils/payload-normalizer.js +240 -0
- package/dist/utils/payload-normalizer.js.map +1 -0
- package/package.json +9 -3
|
@@ -7,6 +7,7 @@ import { HistoryDatabase } from '../database/history-db.js';
|
|
|
7
7
|
import { OAuthValidator } from '../auth/oauth.js';
|
|
8
8
|
import { SessionCache } from '../auth/session-cache.js';
|
|
9
9
|
import { CircuitBreaker } from '../utils/circuit-breaker.js';
|
|
10
|
+
import { createMtlsAgent } from '../utils/mtls-config.js';
|
|
10
11
|
import * as Metrics from '../utils/metrics.js';
|
|
11
12
|
import { Logger } from '../utils/logger.js';
|
|
12
13
|
/**
|
|
@@ -24,7 +25,8 @@ export class HttpProxyServer {
|
|
|
24
25
|
db;
|
|
25
26
|
port;
|
|
26
27
|
server = null;
|
|
27
|
-
|
|
28
|
+
httpsAgent;
|
|
29
|
+
constructor(targetUrl, serverName, policyEngine, authValidator, db, port = 4000, mtlsConfig) {
|
|
28
30
|
this.serverName = serverName;
|
|
29
31
|
this.targetUrl = targetUrl.replace(/\/$/, '');
|
|
30
32
|
this.policyEngine = policyEngine || null;
|
|
@@ -34,7 +36,11 @@ export class HttpProxyServer {
|
|
|
34
36
|
this.tokenCounter = new TokenCounter();
|
|
35
37
|
this.db = db || new HistoryDatabase(':memory:');
|
|
36
38
|
this.port = port;
|
|
39
|
+
this.httpsAgent = createMtlsAgent(mtlsConfig || { enabled: false, rejectUnauthorized: true });
|
|
37
40
|
Metrics.circuitBreakerState.set({ server_name: this.serverName }, 0);
|
|
41
|
+
if (this.httpsAgent) {
|
|
42
|
+
Logger.info(`[http-proxy:${this.serverName}] mTLS enabled for upstream connection`);
|
|
43
|
+
}
|
|
38
44
|
}
|
|
39
45
|
async start() {
|
|
40
46
|
this.server = createServer((req, res) => this.handleRequest(req, res));
|
|
@@ -118,13 +124,18 @@ export class HttpProxyServer {
|
|
|
118
124
|
try {
|
|
119
125
|
const upstreamUrl = new URL(this.targetUrl + (req.url || '/'));
|
|
120
126
|
const isHttps = upstreamUrl.protocol === 'https:';
|
|
121
|
-
const
|
|
127
|
+
const reqOpts = {
|
|
122
128
|
hostname: upstreamUrl.hostname,
|
|
123
129
|
port: upstreamUrl.port || (isHttps ? 443 : 80),
|
|
124
130
|
path: upstreamUrl.pathname + upstreamUrl.search,
|
|
125
131
|
method: req.method,
|
|
126
132
|
headers: { ...req.headers, host: upstreamUrl.hostname },
|
|
127
|
-
}
|
|
133
|
+
};
|
|
134
|
+
// Attach mTLS agent for HTTPS connections
|
|
135
|
+
if (isHttps && this.httpsAgent) {
|
|
136
|
+
reqOpts.agent = this.httpsAgent;
|
|
137
|
+
}
|
|
138
|
+
const proxyReq = (isHttps ? httpsReq : httpReq)(reqOpts, (upstreamRes) => {
|
|
128
139
|
res.writeHead(upstreamRes.statusCode || 200, upstreamRes.headers);
|
|
129
140
|
upstreamRes.pipe(res);
|
|
130
141
|
this.circuitBreaker.recordSuccess();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-proxy-server.js","sourceRoot":"","sources":["../../src/proxy/http-proxy-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmC,MAAM,MAAM,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"http-proxy-server.js","sourceRoot":"","sources":["../../src/proxy/http-proxy-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
+
import { createServer } from 'http';
|
|
1
2
|
import { PolicyWatcher } from '../policy/policy-watcher.js';
|
|
3
|
+
import { DashboardAuth } from '../auth/dashboard-auth.js';
|
|
2
4
|
/**
|
|
3
5
|
* Lightweight dashboard server that serves:
|
|
4
|
-
* - / — the dashboard HTML
|
|
5
|
-
* - /
|
|
6
|
-
* - /api/
|
|
7
|
-
* - /
|
|
6
|
+
* - / — the dashboard HTML (requires auth if enabled)
|
|
7
|
+
* - /login — login page (when JWT auth is enabled)
|
|
8
|
+
* - /api/login — POST login endpoint
|
|
9
|
+
* - /api/policy — current policy (JSON, requires auth)
|
|
10
|
+
* - /api/policy/reload — trigger policy reload (requires auth)
|
|
11
|
+
* - /metrics — Prometheus metrics (can be auth-gated or public via DASHBOARD_METRICS_PUBLIC=true)
|
|
12
|
+
*
|
|
13
|
+
* v1.2: Integrated DashboardAuth for JWT/API key authentication, CSRF protection.
|
|
8
14
|
*/
|
|
9
|
-
export declare function startDashboardServer(port?: number, policyWatcher?: PolicyWatcher): Promise<
|
|
15
|
+
export declare function startDashboardServer(port?: number, policyWatcher?: PolicyWatcher, dashboardAuth?: DashboardAuth): Promise<{
|
|
16
|
+
auth: DashboardAuth;
|
|
17
|
+
server: ReturnType<typeof createServer>;
|
|
18
|
+
}>;
|
|
10
19
|
//# sourceMappingURL=dashboard-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-server.d.ts","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dashboard-server.d.ts","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAmC,MAAM,MAAM,CAAC;AAKrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM1D;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,GAAE,MAAa,EACnB,aAAa,CAAC,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;CAAE,CAAC,CA2P3E"}
|
|
@@ -3,84 +3,256 @@ import { readFileSync } from 'fs';
|
|
|
3
3
|
import { resolve, dirname } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { Logger } from './logger.js';
|
|
6
|
+
import { DashboardAuth } from '../auth/dashboard-auth.js';
|
|
6
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
8
|
const __dirname = dirname(__filename);
|
|
8
9
|
/**
|
|
9
10
|
* Lightweight dashboard server that serves:
|
|
10
|
-
* - / — the dashboard HTML
|
|
11
|
-
* - /
|
|
12
|
-
* - /api/
|
|
13
|
-
* - /
|
|
11
|
+
* - / — the dashboard HTML (requires auth if enabled)
|
|
12
|
+
* - /login — login page (when JWT auth is enabled)
|
|
13
|
+
* - /api/login — POST login endpoint
|
|
14
|
+
* - /api/policy — current policy (JSON, requires auth)
|
|
15
|
+
* - /api/policy/reload — trigger policy reload (requires auth)
|
|
16
|
+
* - /metrics — Prometheus metrics (can be auth-gated or public via DASHBOARD_METRICS_PUBLIC=true)
|
|
17
|
+
*
|
|
18
|
+
* v1.2: Integrated DashboardAuth for JWT/API key authentication, CSRF protection.
|
|
14
19
|
*/
|
|
15
|
-
export async function startDashboardServer(port = 4000, policyWatcher) {
|
|
20
|
+
export async function startDashboardServer(port = 4000, policyWatcher, dashboardAuth) {
|
|
16
21
|
if (process.env['DASHBOARD_ENABLED'] !== 'true') {
|
|
17
22
|
Logger.debug('[dashboard] Dashboard server not enabled (set DASHBOARD_ENABLED=true)');
|
|
18
|
-
return
|
|
23
|
+
return { auth: dashboardAuth || new DashboardAuth({ enabled: false }), server: createServer((_req, res) => {
|
|
24
|
+
res.writeHead(200);
|
|
25
|
+
res.end();
|
|
26
|
+
}) };
|
|
27
|
+
}
|
|
28
|
+
const auth = dashboardAuth || new DashboardAuth();
|
|
29
|
+
const authEnabled = auth.isEnabled();
|
|
30
|
+
if (authEnabled) {
|
|
31
|
+
Logger.info('[dashboard] Dashboard authentication enabled');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
Logger.info('[dashboard] Dashboard running without authentication (set DASHBOARD_AUTH_ENABLED=true)');
|
|
19
35
|
}
|
|
20
36
|
const dashboardHtml = readFileSync(resolve(__dirname, '..', '..', 'deploy', 'dashboard.html'), 'utf-8');
|
|
37
|
+
/** Read JSON body from request */
|
|
38
|
+
async function readBody(req) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
let data = '';
|
|
41
|
+
req.on('data', (chunk) => { data += chunk.toString(); });
|
|
42
|
+
req.on('end', () => {
|
|
43
|
+
try {
|
|
44
|
+
resolve(data ? JSON.parse(data) : {});
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
resolve({});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
req.on('error', reject);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Parse form-encoded body from request */
|
|
54
|
+
async function readFormBody(req) {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
let data = '';
|
|
57
|
+
req.on('data', (chunk) => { data += chunk.toString(); });
|
|
58
|
+
req.on('end', () => {
|
|
59
|
+
const result = {};
|
|
60
|
+
if (data) {
|
|
61
|
+
try {
|
|
62
|
+
const params = new URLSearchParams(data);
|
|
63
|
+
for (const [key, value] of params) {
|
|
64
|
+
result[key] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignore parse errors
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
resolve(result);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/** Get client IP for rate limiting */
|
|
76
|
+
function getClientIp(req) {
|
|
77
|
+
const forwarded = req.headers['x-forwarded-for'];
|
|
78
|
+
if (forwarded) {
|
|
79
|
+
const first = Array.isArray(forwarded) ? forwarded[0] : forwarded.split(',')[0];
|
|
80
|
+
return (first || '').trim();
|
|
81
|
+
}
|
|
82
|
+
return req.socket?.remoteAddress || 'unknown';
|
|
83
|
+
}
|
|
84
|
+
/** Write JSON response */
|
|
85
|
+
function writeJson(res, status, data) {
|
|
86
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
87
|
+
res.end(JSON.stringify(data));
|
|
88
|
+
}
|
|
21
89
|
const server = createServer(async (req, res) => {
|
|
22
90
|
const url = req.url || '/';
|
|
91
|
+
const method = req.method || 'GET';
|
|
92
|
+
// ── CORS preflight ─────────────────────────────────────
|
|
93
|
+
if (method === 'OPTIONS') {
|
|
94
|
+
res.writeHead(204, {
|
|
95
|
+
'Access-Control-Allow-Origin': '*',
|
|
96
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
97
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-API-Key',
|
|
98
|
+
});
|
|
99
|
+
res.end();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// ── CORS headers on all responses ─────────────────────
|
|
103
|
+
const setCors = () => {
|
|
104
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
105
|
+
};
|
|
23
106
|
try {
|
|
24
|
-
// ──
|
|
107
|
+
// ── Login page (only when JWT auth is enabled, no API key set) ──
|
|
108
|
+
if (url === '/login' && method === 'GET') {
|
|
109
|
+
setCors();
|
|
110
|
+
if (auth.isEnabled() && auth.hasJwtSessionAuth()) {
|
|
111
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
112
|
+
res.end(auth.getLoginPageHtml());
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
res.writeHead(302, { 'Location': '/' });
|
|
116
|
+
res.end();
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// ── Login API endpoint ──────────────────────────────
|
|
121
|
+
if (url === '/api/login' && method === 'POST') {
|
|
122
|
+
setCors();
|
|
123
|
+
const ip = getClientIp(req);
|
|
124
|
+
const contentType = req.headers['content-type'] || '';
|
|
125
|
+
let body;
|
|
126
|
+
if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
127
|
+
body = await readFormBody(req);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
body = await readBody(req);
|
|
131
|
+
}
|
|
132
|
+
const result = auth.login({
|
|
133
|
+
url,
|
|
134
|
+
headers: req.headers,
|
|
135
|
+
body: {
|
|
136
|
+
username: body.username,
|
|
137
|
+
password: body.password,
|
|
138
|
+
api_key: body.api_key,
|
|
139
|
+
},
|
|
140
|
+
ip,
|
|
141
|
+
});
|
|
142
|
+
if (result.success && req.headers['content-type']?.includes('form')) {
|
|
143
|
+
// Form submission — redirect to dashboard with token
|
|
144
|
+
res.writeHead(302, {
|
|
145
|
+
'Location': `/?api_key=${encodeURIComponent(result.token)}`,
|
|
146
|
+
'Set-Cookie': `mcp_guardian_session=${result.token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=3600`,
|
|
147
|
+
});
|
|
148
|
+
res.end();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (result.success) {
|
|
152
|
+
writeJson(res, 200, { success: true, token: result.token });
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
writeJson(res, 401, { success: false, error: result.error });
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// ── Auth check for all other routes ─────────────────
|
|
160
|
+
const authResult = auth.authenticate({ url, headers: req.headers, method });
|
|
161
|
+
if (!authResult.authenticated) {
|
|
162
|
+
setCors();
|
|
163
|
+
if (req.headers['accept']?.includes('text/html')) {
|
|
164
|
+
// Browser request — redirect to login
|
|
165
|
+
res.writeHead(302, { 'Location': '/login' });
|
|
166
|
+
res.end();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
writeJson(res, 401, { error: 'Authentication required', reason: authResult.reason });
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// ── Dashboard HTML ──────────────────────────────────
|
|
25
174
|
if (url === '/' || url === '/dashboard.html') {
|
|
175
|
+
setCors();
|
|
26
176
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
27
177
|
res.end(dashboardHtml);
|
|
28
178
|
return;
|
|
29
179
|
}
|
|
30
|
-
// ── Policy API
|
|
31
|
-
if (url === '/api/policy' &&
|
|
180
|
+
// ── Policy API ──────────────────────────────────────
|
|
181
|
+
if (url === '/api/policy' && method === 'GET') {
|
|
182
|
+
setCors();
|
|
32
183
|
if (!policyWatcher || !policyWatcher.get()) {
|
|
33
|
-
res
|
|
34
|
-
res.end(JSON.stringify({ error: 'No active policy. Start proxy with --policy flag.' }));
|
|
184
|
+
writeJson(res, 404, { error: 'No active policy. Start proxy with --policy flag.' });
|
|
35
185
|
return;
|
|
36
186
|
}
|
|
37
|
-
res
|
|
38
|
-
res.end(JSON.stringify({ mode: policyWatcher.get().getMode(), rules: 'Policy engine active (YAML view available on filesystem)' }));
|
|
187
|
+
writeJson(res, 200, { mode: policyWatcher.get().getMode(), rules: 'Policy engine active (YAML view available on filesystem)' });
|
|
39
188
|
return;
|
|
40
189
|
}
|
|
41
|
-
if (url === '/api/policy/reload' &&
|
|
190
|
+
if (url === '/api/policy/reload' && method === 'POST') {
|
|
191
|
+
setCors();
|
|
42
192
|
if (!policyWatcher) {
|
|
43
|
-
res
|
|
44
|
-
res.end(JSON.stringify({ error: 'Policy watcher not configured' }));
|
|
193
|
+
writeJson(res, 404, { error: 'Policy watcher not configured' });
|
|
45
194
|
return;
|
|
46
195
|
}
|
|
47
|
-
|
|
48
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
49
|
-
res.end(JSON.stringify({ status: 'ok', message: 'Policy watcher is active. File changes are auto-detected.' }));
|
|
196
|
+
writeJson(res, 200, { status: 'ok', message: 'Policy watcher is active. File changes are auto-detected.' });
|
|
50
197
|
return;
|
|
51
198
|
}
|
|
52
|
-
// ── Prometheus /metrics proxy
|
|
199
|
+
// ── Prometheus /metrics proxy ──────────────────────
|
|
53
200
|
if (url === '/metrics') {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
201
|
+
setCors();
|
|
202
|
+
const metricsPublic = process.env['DASHBOARD_METRICS_PUBLIC'] === 'true';
|
|
203
|
+
// Re-check auth for metrics unless public
|
|
204
|
+
if (metricsPublic || authResult.authenticated) {
|
|
205
|
+
try {
|
|
206
|
+
const metricsPort = process.env['METRICS_PORT'] || '9090';
|
|
207
|
+
const metricsRes = await fetch(`http://localhost:${metricsPort}/metrics`);
|
|
208
|
+
if (!metricsRes.ok)
|
|
209
|
+
throw new Error(`Metrics server returned ${metricsRes.status}`);
|
|
210
|
+
const text = await metricsRes.text();
|
|
211
|
+
res.writeHead(200, {
|
|
212
|
+
'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',
|
|
213
|
+
'Access-Control-Allow-Origin': '*',
|
|
214
|
+
});
|
|
215
|
+
res.end(text);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
writeJson(res, 200, { error: 'Metrics not available. Ensure METRICS_ENABLED=true and proxy is running.' });
|
|
219
|
+
}
|
|
66
220
|
}
|
|
67
|
-
|
|
68
|
-
res
|
|
69
|
-
|
|
221
|
+
else {
|
|
222
|
+
writeJson(res, 401, { error: 'Authentication required for metrics' });
|
|
223
|
+
}
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// ── Auth status check ───────────────────────────────
|
|
227
|
+
if (url === '/api/auth/status' && method === 'GET') {
|
|
228
|
+
setCors();
|
|
229
|
+
writeJson(res, 200, { authenticated: true, identity: authResult.identity, authEnabled });
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// ── Logout ──────────────────────────────────────────
|
|
233
|
+
if (url === '/api/logout' && method === 'POST') {
|
|
234
|
+
setCors();
|
|
235
|
+
const authHeader = req.headers['authorization'];
|
|
236
|
+
if (authHeader) {
|
|
237
|
+
const match = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
238
|
+
if (match)
|
|
239
|
+
auth.logout(match[1]);
|
|
70
240
|
}
|
|
241
|
+
writeJson(res, 200, { status: 'ok', message: 'Logged out' });
|
|
71
242
|
return;
|
|
72
243
|
}
|
|
73
|
-
// ── 404
|
|
74
|
-
|
|
75
|
-
res
|
|
244
|
+
// ── 404 ──────────────────────────────────────────────
|
|
245
|
+
setCors();
|
|
246
|
+
writeJson(res, 404, { error: 'Not found' });
|
|
76
247
|
}
|
|
77
248
|
catch (err) {
|
|
78
|
-
|
|
79
|
-
res
|
|
249
|
+
setCors();
|
|
250
|
+
writeJson(res, 500, { error: err?.message || 'Internal error' });
|
|
80
251
|
}
|
|
81
252
|
});
|
|
82
253
|
server.listen(port, () => {
|
|
83
|
-
Logger.info(`[dashboard] Dashboard available at http://localhost:${port}`);
|
|
254
|
+
Logger.info(`[dashboard] Dashboard available at http://localhost:${port}${authEnabled ? ' (auth enabled)' : ''}`);
|
|
84
255
|
});
|
|
256
|
+
return { auth, server };
|
|
85
257
|
}
|
|
86
258
|
//# sourceMappingURL=dashboard-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-server.js","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"dashboard-server.js","sourceRoot":"","sources":["../../src/utils/dashboard-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Agent as HttpsAgent } from 'https';
|
|
2
|
+
export interface MtlsConfig {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
ca?: Buffer;
|
|
5
|
+
cert?: Buffer;
|
|
6
|
+
key?: Buffer;
|
|
7
|
+
rejectUnauthorized: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Load mTLS configuration from environment variables.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadMtlsConfig(): MtlsConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Create an HTTPS Agent configured with mTLS client certificate and CA.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createMtlsAgent(config: MtlsConfig): HttpsAgent | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* CLI flag names for mTLS configuration.
|
|
19
|
+
*/
|
|
20
|
+
export declare const MTL_CLI_FLAGS: {
|
|
21
|
+
readonly tlsEnabled: "--mtls";
|
|
22
|
+
readonly tlsCa: "--mtls-ca <path>";
|
|
23
|
+
readonly tlsCert: "--mtls-cert <path>";
|
|
24
|
+
readonly tlsKey: "--mtls-key <path>";
|
|
25
|
+
readonly tlsInsecure: "--mtls-insecure";
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=mtls-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mtls-config.d.ts","sourceRoot":"","sources":["../../src/utils/mtls-config.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,OAAO,CAAC;AAG5C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAsC3C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAW1E;AAED;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mTLS Configuration for Zero-Trust Proxy ↔ Upstream Communication.
|
|
3
|
+
*
|
|
4
|
+
* When MCP_TLS_ENABLED=true, the HTTP/SSE proxy validates the upstream
|
|
5
|
+
* server's certificate AND presents a client certificate for mutual
|
|
6
|
+
* authentication. This prevents MITM attacks and ensures only authorized
|
|
7
|
+
* proxies can connect to upstream MCP servers.
|
|
8
|
+
*
|
|
9
|
+
* Configuration via environment variables:
|
|
10
|
+
* MCP_TLS_ENABLED=true|false
|
|
11
|
+
* MCP_TLS_CA=/path/to/ca-cert.pem (required — trusted CA bundle)
|
|
12
|
+
* MCP_TLS_CERT=/path/to/client-cert.pem (required — proxy's client cert)
|
|
13
|
+
* MCP_TLS_KEY=/path/to/client-key.pem (required — proxy's client key)
|
|
14
|
+
* MCP_TLS_REJECT_UNAUTHORIZED=true|false (default: true — strict mode)
|
|
15
|
+
*/
|
|
16
|
+
import { readFileSync } from 'fs';
|
|
17
|
+
import { Agent as HttpsAgent } from 'https';
|
|
18
|
+
import { Logger } from './logger.js';
|
|
19
|
+
/**
|
|
20
|
+
* Load mTLS configuration from environment variables.
|
|
21
|
+
*/
|
|
22
|
+
export function loadMtlsConfig() {
|
|
23
|
+
const enabled = process.env['MCP_TLS_ENABLED'] === 'true';
|
|
24
|
+
if (!enabled) {
|
|
25
|
+
return { enabled: false, rejectUnauthorized: true };
|
|
26
|
+
}
|
|
27
|
+
const caPath = process.env['MCP_TLS_CA'];
|
|
28
|
+
const certPath = process.env['MCP_TLS_CERT'];
|
|
29
|
+
const keyPath = process.env['MCP_TLS_KEY'];
|
|
30
|
+
const rejectUnauthorized = process.env['MCP_TLS_REJECT_UNAUTHORIZED'] !== 'false';
|
|
31
|
+
const missing = [];
|
|
32
|
+
if (!caPath)
|
|
33
|
+
missing.push('MCP_TLS_CA');
|
|
34
|
+
if (!certPath)
|
|
35
|
+
missing.push('MCP_TLS_CERT');
|
|
36
|
+
if (!keyPath)
|
|
37
|
+
missing.push('MCP_TLS_KEY');
|
|
38
|
+
if (missing.length > 0) {
|
|
39
|
+
Logger.error(`[mtls] mTLS enabled but missing env vars: ${missing.join(', ')}`);
|
|
40
|
+
throw new Error(`mTLS misconfigured: missing ${missing.join(', ')}`);
|
|
41
|
+
}
|
|
42
|
+
let ca;
|
|
43
|
+
let cert;
|
|
44
|
+
let key;
|
|
45
|
+
try {
|
|
46
|
+
ca = readFileSync(caPath);
|
|
47
|
+
cert = readFileSync(certPath);
|
|
48
|
+
key = readFileSync(keyPath);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
Logger.error(`[mtls] Failed to read TLS files: ${err?.message}`);
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
Logger.info(`[mtls] mTLS enabled (CA: ${caPath}, cert: ${certPath}, rejectUnauthorized: ${rejectUnauthorized})`);
|
|
55
|
+
return { enabled: true, ca, cert, key, rejectUnauthorized };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create an HTTPS Agent configured with mTLS client certificate and CA.
|
|
59
|
+
*/
|
|
60
|
+
export function createMtlsAgent(config) {
|
|
61
|
+
if (!config.enabled)
|
|
62
|
+
return undefined;
|
|
63
|
+
return new HttpsAgent({
|
|
64
|
+
ca: config.ca,
|
|
65
|
+
cert: config.cert,
|
|
66
|
+
key: config.key,
|
|
67
|
+
rejectUnauthorized: config.rejectUnauthorized,
|
|
68
|
+
keepAlive: true,
|
|
69
|
+
keepAliveMsecs: 30000,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* CLI flag names for mTLS configuration.
|
|
74
|
+
*/
|
|
75
|
+
export const MTL_CLI_FLAGS = {
|
|
76
|
+
tlsEnabled: '--mtls',
|
|
77
|
+
tlsCa: '--mtls-ca <path>',
|
|
78
|
+
tlsCert: '--mtls-cert <path>',
|
|
79
|
+
tlsKey: '--mtls-key <path>',
|
|
80
|
+
tlsInsecure: '--mtls-insecure',
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=mtls-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mtls-config.js","sourceRoot":"","sources":["../../src/utils/mtls-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface NormalizationResult {
|
|
2
|
+
/** The fully normalized string ready for policy evaluation */
|
|
3
|
+
normalized: string;
|
|
4
|
+
/** Whether any normalization was applied */
|
|
5
|
+
wasModified: boolean;
|
|
6
|
+
/** What transformations were applied */
|
|
7
|
+
transformations: string[];
|
|
8
|
+
/** The original raw input */
|
|
9
|
+
original: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* PayloadNormalizer applies multi-stage normalization to defeat
|
|
13
|
+
* common evasion techniques targeting regex-based policy engines.
|
|
14
|
+
*/
|
|
15
|
+
export declare class PayloadNormalizer {
|
|
16
|
+
private readonly maxDepth;
|
|
17
|
+
private readonly maxLength;
|
|
18
|
+
constructor(maxDepth?: number, maxLength?: number);
|
|
19
|
+
/**
|
|
20
|
+
* Full normalization pipeline for policy evaluation input.
|
|
21
|
+
*/
|
|
22
|
+
normalize(input: string): NormalizationResult;
|
|
23
|
+
/**
|
|
24
|
+
* URL decode: %XX → character, handles malformed sequences.
|
|
25
|
+
*/
|
|
26
|
+
private urlDecode;
|
|
27
|
+
/**
|
|
28
|
+
* Decode hex escapes: \x41 → 'A', \x00 → null byte detection.
|
|
29
|
+
*/
|
|
30
|
+
private decodeHexEscapes;
|
|
31
|
+
/**
|
|
32
|
+
* Decode unicode escapes: \u0041 → 'A', \U00000041 → 'A'.
|
|
33
|
+
*/
|
|
34
|
+
private decodeUnicodeEscapes;
|
|
35
|
+
/**
|
|
36
|
+
* Decode HTML entities: < -> <, < -> <, < -> <.
|
|
37
|
+
* Entity map built at runtime to avoid source-level entity decoding issues.
|
|
38
|
+
*/
|
|
39
|
+
private static htmlEntityMap;
|
|
40
|
+
private static getHtmlEntityMap;
|
|
41
|
+
private decodeHtmlEntities;
|
|
42
|
+
/**
|
|
43
|
+
* Unwrap double escapes: \\. → literal character.
|
|
44
|
+
*/
|
|
45
|
+
private unwrapDoubleEscapes;
|
|
46
|
+
/**
|
|
47
|
+
* Shell normalize: collapse common shell obfuscation patterns.
|
|
48
|
+
*
|
|
49
|
+
* - $'cmd' → cmd (ANSI-C quoting)
|
|
50
|
+
* - "c"m"d" → cmd (quote splitting)
|
|
51
|
+
* - ''cmd'' → cmd (empty quote pairs)
|
|
52
|
+
* - c\md → cmd (backslash escapes)
|
|
53
|
+
*/
|
|
54
|
+
private shellNormalize;
|
|
55
|
+
/**
|
|
56
|
+
* Specifically normalize a JSON string value (tool argument).
|
|
57
|
+
* Handles nested JSON structures recursively.
|
|
58
|
+
*/
|
|
59
|
+
normalizeJsonValue(value: unknown, depth?: number): unknown;
|
|
60
|
+
}
|
|
61
|
+
export declare function getNormalizer(): PayloadNormalizer;
|
|
62
|
+
//# sourceMappingURL=payload-normalizer.d.ts.map
|