195 lines
6.1 KiB
JavaScript
195 lines
6.1 KiB
JavaScript
// proxy/routes.js
|
|
// ─── REST API Routes for BackOne Proxy Server ───────────────────────────────
|
|
const express = require('express');
|
|
const router = express.Router();
|
|
const mongoose = require('mongoose');
|
|
const scheduler = require('./scheduler');
|
|
|
|
/**
|
|
* GET /health
|
|
* Liveness check
|
|
*/
|
|
router.get('/health', (req, res) => {
|
|
const dbState = mongoose.connection.readyState;
|
|
const dbLabel = ['disconnected', 'connected', 'connecting', 'disconnecting'][dbState] || 'unknown';
|
|
res.json({
|
|
ok: dbState === 1,
|
|
service: 'BackOne Proxy Server',
|
|
db: dbLabel,
|
|
mode: process.env.PROXY_COLLECT_MODE || 'all',
|
|
time: new Date().toISOString(),
|
|
});
|
|
});
|
|
|
|
/**
|
|
* GET /status
|
|
* Full scheduler + DB status
|
|
*/
|
|
router.get('/status', (req, res) => {
|
|
const dbState = mongoose.connection.readyState;
|
|
res.json({
|
|
ok: true,
|
|
db_state: ['disconnected', 'connected', 'connecting', 'disconnecting'][dbState] || 'unknown',
|
|
...scheduler.getStatus(),
|
|
time: new Date().toISOString(),
|
|
});
|
|
});
|
|
|
|
/**
|
|
* POST /collect/all
|
|
* Manual trigger — collect ALL agents sekarang
|
|
*/
|
|
router.post('/collect/all', async (req, res) => {
|
|
if (mongoose.connection.readyState !== 1) {
|
|
return res.status(503).json({ ok: false, error: 'MongoDB not connected. Cannot collect.' });
|
|
}
|
|
const { collectAllAgents } = require('./collector');
|
|
console.log('[Proxy API] Manual trigger: collect ALL agents');
|
|
try {
|
|
const result = await collectAllAgents();
|
|
res.json({ ok: result.success, ...result });
|
|
} catch (err) {
|
|
res.status(500).json({ ok: false, error: err.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* POST /collect/:agentUuid
|
|
* Manual trigger — collect ONE specific agent
|
|
*/
|
|
router.post('/collect/:agentUuid', async (req, res) => {
|
|
if (mongoose.connection.readyState !== 1) {
|
|
return res.status(503).json({ ok: false, error: 'MongoDB not connected. Cannot collect.' });
|
|
}
|
|
const { agentUuid } = req.params;
|
|
const { collectSpecificAgent } = require('./collector');
|
|
console.log(`[Proxy API] Manual trigger: collect agent ${agentUuid}`);
|
|
try {
|
|
const result = await collectSpecificAgent(agentUuid);
|
|
res.json({ ok: result.success, ...result });
|
|
} catch (err) {
|
|
res.status(500).json({ ok: false, error: err.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* POST /collect/agents
|
|
* Manual trigger — collect multiple specific agents
|
|
* Body: { "uuids": ["uuid1", "uuid2", ...], "delay_ms": 5000 }
|
|
*/
|
|
router.post('/collect/agents', async (req, res) => {
|
|
if (mongoose.connection.readyState !== 1) {
|
|
return res.status(503).json({ ok: false, error: 'MongoDB not connected. Cannot collect.' });
|
|
}
|
|
const { uuids, delay_ms } = req.body;
|
|
if (!uuids || !Array.isArray(uuids) || uuids.length === 0) {
|
|
return res.status(400).json({ ok: false, error: 'Body must include "uuids" as a non-empty array of agent UUIDs.' });
|
|
}
|
|
const { collectSpecificAgents } = require('./collector');
|
|
console.log(`[Proxy API] Manual trigger: collect agents ${uuids.join(', ')}`);
|
|
try {
|
|
const result = await collectSpecificAgents(uuids, delay_ms || 5000);
|
|
res.json({ ok: result.success, ...result });
|
|
} catch (err) {
|
|
res.status(500).json({ ok: false, error: err.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /agents
|
|
* List all agent UUIDs yang sudah tersimpan di MongoDB
|
|
*/
|
|
router.get('/agents', async (req, res) => {
|
|
try {
|
|
if (mongoose.connection.readyState !== 1) {
|
|
return res.status(503).json({ ok: false, error: 'MongoDB not connected.' });
|
|
}
|
|
const { Summary } = require('./models/Schemas');
|
|
const agents = await Summary.distinct('agent_uuid');
|
|
res.json({ ok: true, data: agents });
|
|
} catch (err) {
|
|
res.status(500).json({ ok: false, error: err.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /domain-details
|
|
* Fetch live IP/MAC details for a specific domain from MongoDB
|
|
*/
|
|
router.get('/domain-details', async (req, res) => {
|
|
const { domain, agentUuid } = req.query;
|
|
if (!domain) return res.status(400).json({ ok: false, error: 'domain is required' });
|
|
|
|
try {
|
|
const { Flow, DeviceStat } = require('./models/Schemas');
|
|
|
|
const filter = { domain: domain };
|
|
if (agentUuid) {
|
|
filter.agent_uuid = agentUuid;
|
|
}
|
|
|
|
const raw = await Flow.find(filter).sort({ timestamp: -1 }).limit(100).lean();
|
|
if (!raw || !Array.isArray(raw)) {
|
|
return res.json({ ok: true, data: [] });
|
|
}
|
|
|
|
const results = [];
|
|
const seen = new Set();
|
|
|
|
for (const r of raw) {
|
|
const ip = r.src_ip;
|
|
const mac = r.src_mac;
|
|
if (!ip || !mac) continue;
|
|
|
|
const key = `${ip}-${mac}`;
|
|
if (seen.has(key)) continue;
|
|
seen.add(key);
|
|
|
|
let deviceName = 'Unknown Device';
|
|
try {
|
|
const dev = await DeviceStat.findOne({ mac_address: mac }).sort({ timestamp: -1 });
|
|
if (dev && dev.name && dev.name !== 'Unknown Device') {
|
|
deviceName = dev.name;
|
|
}
|
|
} catch (e) {
|
|
// ignore timeout errors
|
|
}
|
|
|
|
results.push({
|
|
ip,
|
|
mac,
|
|
deviceName,
|
|
lastSeen: r.timestamp || r.last_seen || r.first_seen,
|
|
});
|
|
}
|
|
|
|
res.json({ ok: true, data: results });
|
|
} catch (err) {
|
|
res.status(500).json({ ok: false, error: err.message });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /latest
|
|
* Tampilkan data terbaru dari semua collection (untuk debug)
|
|
*/
|
|
router.get('/latest', async (req, res) => {
|
|
try {
|
|
const { Summary, AppStat, DeviceStat, Flow, Threat, Event, AppCategoryStat } = require('./models/Schemas');
|
|
const [summary, apps, devices, flows, threats, events, categories] = await Promise.all([
|
|
Summary.findOne().sort({ timestamp: -1 }).lean(),
|
|
AppStat.find().sort({ timestamp: -1 }).limit(5).lean(),
|
|
DeviceStat.find().sort({ timestamp: -1 }).limit(5).lean(),
|
|
Flow.find().sort({ timestamp: -1 }).limit(5).lean(),
|
|
Threat.find().sort({ timestamp: -1 }).limit(5).lean(),
|
|
Event.find().sort({ timestamp: -1 }).limit(5).lean(),
|
|
AppCategoryStat.find().sort({ timestamp: -1 }).limit(5).lean(),
|
|
]);
|
|
res.json({ ok: true, data: { summary, apps, devices, flows, threats, events, categories } });
|
|
} catch (err) {
|
|
res.status(500).json({ ok: false, error: err.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|