// Matrix: what the rules do to new connections between zones, and to and // from the firewall itself. import { h, mount, modal, badge } from "../ui.js"; import { get, state } from "../api.js"; export async function render(el) { const m = await get("/matrix"); const cols = [...m.zones, "firewall"]; const cells = new Map(m.cells.map((c) => [c.from + "\u0000" + c.to, c])); const pending = state.draft && !state.immediate && (state.draft.ops || []).length; const name = (z) => z === "firewall" ? h("em", null, "firewall") : z; mount(el, h("div", { class: "page-head" }, h("div", { class: "grow" }, h("h1", null, "Zone matrix"), h("div", { class: "muted" }, "What happens to a new connection from a zone (rows) to a zone (columns), or to and from the firewall itself, worked out from the rules in order: allowed or blocked, and how many rules decide for part of the traffic first (some services, addresses, times). Click a cell for the rules."))), pending ? h("div", { class: "msg info" }, "Shown with your pending changes.") : null, !m.zones.length ? h("div", { class: "panel" }, h("div", { class: "empty" }, "No zones yet: add them under Objects → Zones.")) : h("div", { class: "panel" }, h("div", { class: "table-wrap" }, h("table", { class: "matrix" }, h("thead", null, h("tr", null, h("th", { class: "corner" }, "from ↓ to →"), cols.map((c) => h("th", null, name(c))))), h("tbody", null, cols.map((from) => h("tr", null, h("th", null, name(from)), cols.map((to) => { const c = cells.get(from + "\u0000" + to); if (!c) return h("td", { class: "matrix-none" }, "–"); const n = c.exceptions.length; return h("td", { class: "matrix-" + c.verdict + (n ? " matrix-some" : ""), title: c.verdict + " by " + c.decided_by + (n ? ", " + n + " exception" + (n === 1 ? "" : "s") + " first" : "") }, h("button", { type: "button", class: "matrix-cell", onclick: () => detail(c) }, c.verdict, n ? h("span", { class: "matrix-n" }, "+" + n) : null)); })))))), h("p", { class: "muted small" }, "Zone to zone is the forward chain; to the firewall, input; from it, output. Exceptions are rules (and built-ins such as ping or port forwards) that decide for some of the traffic before the rest falls to the deciding rule or the policy. Replies and established connections aren't shown: the built-in lets those through."))); } function detail(c) { const ruleLink = (id, chain, label) => id ? h("a", { href: "#/rules?chain=" + chain, onclick: () => document.querySelector(".modal-back") && document.querySelector(".modal-back").remove() }, label) : label; const v = (verdict) => badge(verdict, { allowed: "ok", blocked: "err", logged: "", unknown: "warn" }[verdict]); modal(c.from + " → " + c.to, h("div", null, h("p", { class: "muted" }, "New connections, checked in this order (the " + c.chain + " chain):"), h("div", { class: "table-wrap" }, h("table", null, h("tbody", null, c.exceptions.map((e) => h("tr", null, h("td", null, v(e.verdict)), h("td", null, e.what), h("td", { class: "small" }, ruleLink(e.rule_id, e.chain, e.label)))), h("tr", { class: "matrix-rest" }, h("td", null, v(c.verdict)), h("td", null, h("strong", null, c.exceptions.length ? "the rest" : "everything")), h("td", { class: "small" }, ruleLink(c.rule_id, c.chain, c.decided_by))))))), [{ label: "Close", value: null }], { wide: true }); }