mcp-hub-007: Auth hardening — per-service secrets and env-based config
This commit is contained in:
parent
91f0ce271b
commit
85b3f5b6e2
4 changed files with 36 additions and 6 deletions
|
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
name: 'mcp-hub',
|
||||
script: 'src/index.js',
|
||||
cwd: '/workspace',
|
||||
env: { NODE_ENV: 'production', PORT: 3000 },
|
||||
env: { NODE_ENV: 'development', PORT: 3000, HUB_AUTH: JSON.stringify({"sample-mcp": "changeme"}) },
|
||||
max_restarts: 10,
|
||||
restart_delay: 1000,
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
||||
|
|
@ -14,7 +14,7 @@ module.exports = {
|
|||
name: 'sample-mcp',
|
||||
script: 'sample-mcp/index.js',
|
||||
cwd: '/workspace',
|
||||
env: { NODE_ENV: 'production' },
|
||||
env: { NODE_ENV: 'development', MCP_SECRET: 'changeme' },
|
||||
max_restarts: 10,
|
||||
restart_delay: 2000,
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const WebSocket = require('ws');
|
|||
const HUB_URL = process.env.HUB_URL || 'wss://mcp.arik.work/ws/register';
|
||||
const HUB_URL_FALLBACK = 'ws://mcp.arik.work/ws/register';
|
||||
const SERVICE_ID = 'sample-mcp';
|
||||
const SECRET = 'dev-secret';
|
||||
const SECRET = process.env.MCP_SECRET || 'dev-secret';
|
||||
|
||||
let reconnectDelay = 1000;
|
||||
let ws = null;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,27 @@
|
|||
const DEV_SECRET = 'dev-secret';
|
||||
|
||||
let serviceAuthMap = null;
|
||||
if (process.env.HUB_AUTH) {
|
||||
try {
|
||||
serviceAuthMap = JSON.parse(process.env.HUB_AUTH);
|
||||
} catch (e) {
|
||||
console.error('[config] Failed to parse HUB_AUTH JSON:', e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
} else if (process.env.NODE_ENV === 'production') {
|
||||
console.error('[config] HUB_AUTH must be set in production');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function getServiceSecret(serviceId) {
|
||||
if (serviceAuthMap) {
|
||||
return serviceAuthMap[serviceId] !== undefined ? serviceAuthMap[serviceId] : null;
|
||||
}
|
||||
// Dev fallback: accept dev-secret for any service
|
||||
return DEV_SECRET;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
PORT: parseInt(process.env.PORT, 10) || 3000,
|
||||
HUB_SECRET: process.env.HUB_SECRET || 'dev-secret',
|
||||
getServiceSecret,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ function setupWsServer(httpServer) {
|
|||
});
|
||||
});
|
||||
|
||||
wss.on('connection', (ws) => {
|
||||
wss.on('connection', (ws, req) => {
|
||||
let serviceId = null;
|
||||
let authenticated = false;
|
||||
let missedPongs = 0;
|
||||
|
|
@ -34,7 +34,14 @@ function setupWsServer(httpServer) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (msg.type !== 'register' || !msg.serviceId || msg.secret !== config.HUB_SECRET) {
|
||||
if (msg.type !== 'register' || !msg.serviceId) {
|
||||
ws.close(4001, 'unauthorized');
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedSecret = config.getServiceSecret(msg.serviceId);
|
||||
if (expectedSecret === null || msg.secret !== expectedSecret) {
|
||||
console.log(`[ws] auth failed for serviceId=${msg.serviceId} from ${req.socket.remoteAddress}`);
|
||||
ws.close(4001, 'unauthorized');
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue