const express = require("express"); const puppeteer = require("puppeteer"); const fs = require("fs"); const path = require("path"); const app = express(); const fetch = require("node-fetch"); app.use(express.json()); app.use(express.static("public")); // ========== Global token store ========== let globalAuth = { csrfToken: null, cookieHeader: null }; const OPENSENCE_DOMAIN = "http://192.168.1.1/" // ========== Auto login with Puppeteer ========== async function refreshLoginSession() { console.log("🔐 Refreshing login session..."); const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"] }); const page = await browser.newPage(); const opnUrl = OPENSENCE_DOMAIN; const username = "root"; const password = "opnsense"; try { await page.goto(opnUrl, { waitUntil: "networkidle2" }); const csrf = await page.$eval('form input[type="hidden"]', input => ({ name: input.name, value: input.value })); await page.type("#usernamefld", username); await page.type("#passwordfld", password); await page.click(".btn"); setTimeout(async()=>{ const cookies = await page.cookies(); const cookieHeader = cookies.map(c => `${c.name}=${c.value}`).join("; "); globalAuth.csrfToken = csrf.value; globalAuth.cookieHeader = cookieHeader; await browser.close(); console.log("✅ Login refreshed!"); }, 2000) } catch (err) { console.error("❌ Login failed:", err.message); } } // Run once immediately, then every 5 minutes refreshLoginSession(); setInterval(refreshLoginSession, 5 * 60 * 1000); // ========== API Routes ========== app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "public", "index.html")); }); // GET /api/getListApp app.get("/api/getListApp", async (req, res) => { const filePath = path.join(__dirname, "listApp.txt"); try { const content = fs.readFileSync(filePath, "utf-8"); const apps = JSON.parse(content); // Gọi API để lấy init từ policy detail const policyRes = await fetch(OPENSENCE_DOMAIN+"api/zenarmor/policy/detail?id=0", { headers: { "Accept": "application/json", "Cookie": globalAuth.cookieHeader, "X-CSRFTOKEN": globalAuth.csrfToken } }); const policyJson = await policyRes.json(); const init = policyJson.app_controls || []; res.json({ data: apps, init }); } catch (err) { console.error("❌ Error in /api/getListApp:", JSON.stringify(err)); res.status(500).json({ error: "Failed to load apps" }); } }); // POST /update app.post("/update", async (req, res) => { const { app_ids } = req.body; if (!Array.isArray(app_ids)) { return res.status(400).json({ error: "app_ids must be an array" }); } try { const response = await fetch(OPENSENCE_DOMAIN+"api/zenarmor/policy/apply", { method: "POST", headers: { "Accept": "*/*", "Content-Type": "application/json", "X-CSRFTOKEN": globalAuth.csrfToken, "Cookie": globalAuth.cookieHeader }, body: JSON.stringify({ id: "0", checksum: 0, cloud_id: 0, is_active: true, is_centralized: false, is_default: false, name: "Default", decision_is_block: false, block_untrusted_devices: false, groups: [], usernames: [], interfaces: [], vlans: [], devices: [], device_categories: [], mac_addresses: [], networks: [], directions: { inbound: false, outbound: false }, webcategory_type: "permissive", sort_number: 0, security: false, app: true, web: false, tls: false, advanced_security: [], essential_security: [], app_controls: app_ids, app_controls_custom: [], web_controls: [], web_controls_custom: ["b665988a-05ed-4c7e-8964-50459265e8c9"], url_blocks: [], safe_search: "off", block_ech: true, schedules: [], tls_controls: { enabled: false, ignore_pinned_certs: false, lazy_inspection: false, webs_all: false, webs: [] }, casb: { actions: [] }, exclusion_blacklist: [], exclusion_whitelist: [], exclusion_blacklist_global: [], exclusion_whitelist_global: [] }) }); const result = await response.text(); res.json({ success: true, result }); } catch (err) { console.error("❌ Error in /update:", err.message); res.status(500).json({ error: "Failed to apply policy" }); } }); const PORT = 3000; app.listen(PORT, () => { console.log(`🚀 Server running at http://localhost:${PORT}`); });