this works, to the extent that i tested it
This commit is contained in:
63
routes/exec.js
Normal file
63
routes/exec.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import express from 'express';
|
||||
import { enqueueCmd } from '../services/natQueue.js';
|
||||
import { runRouterCmds } from '../services/sshExec.js';
|
||||
import { error, info } from '../util/Console.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const SAFE_CMD_REGX = /^\s*(show|ping|traceroute|terminal length|show ip|show interfaces|show version|show running-config|show ip nat)\b/i;
|
||||
|
||||
function checkAdminToken(req) {
|
||||
const token = req.headers['x-admin-token'] || req.body.token || req.query.token;
|
||||
const saved = req.app.get('adminToken');
|
||||
const expiry = req.app.get('adminTokenExpory') || 0;
|
||||
if (!token || !saved) return false;
|
||||
if (Date.now() > expiry) return false;
|
||||
return token === saved;
|
||||
}
|
||||
|
||||
router.post('/', async (req, res) => {
|
||||
const cmd = (req.body && req.body.cmd) || '';
|
||||
if (!cmd) return res.status(400).json({ error: 'no command' });
|
||||
const isAdmin = checkAdminToken(req);
|
||||
if (!isAdmin && !SAFE_CMD_REGX.test(cmd)) return res.status(403).json({ error: 'not allowed' });
|
||||
|
||||
info(`Exec requested${isAdmin ? ' [admin]' : ''}: ${cmd}`);
|
||||
|
||||
try {
|
||||
enqueueCmd(() => runRouterCmds([cmd]));
|
||||
res.json({ success: true });
|
||||
} catch (err) {
|
||||
error(err);
|
||||
res.status(500).json({ error: 'exec failed' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/stream', (req, res) => {
|
||||
const cmd = req.query.cmd || '';
|
||||
if (!cmd) return res.status(400).send('no command');
|
||||
const isAdmin = checkAdminToken(req);
|
||||
if (!isAdmin && !SAFE_CMD_REGX.test(cmd)) return res.status(400).send('not allowed');
|
||||
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.flushHeaders && res.flushHeaders();
|
||||
|
||||
enqueueCmd(() => new Promise(async (resolve) => {
|
||||
try {
|
||||
await runRouterCmds([cmd], chunk => {
|
||||
res.write(`data: ${chunk.replace(/\n/g, '\\n')}\n\n`);
|
||||
});
|
||||
res.write('data: [[EOF]]\n\n');
|
||||
res.end();
|
||||
resolve()
|
||||
} catch (err) {
|
||||
res.write(`data: [ERROR] ${String(err)}\n\n`);
|
||||
res.end();
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user