mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-29 17:37:13 +00:00
|
Some checks are pending
License Headers / check (push) Waiting to run
* docs(device-guardian): Project A consolidation design — merge 5 device modules into nac (ref #817) * docs(device-guardian): Project A implementation plan — 9 tasks (ref #817) * feat(nac): SQLite device store + idempotent legacy migration (ref #817) Add packages/secubox-nac/api/store.py — pure-stdlib sqlite3 module with canon_mac(), DeviceStore (WAL, best-value upsert, list/get/count, history), and migrate_legacy() for idempotent, per-source best-effort import of mac-guard/device-intel/iot-guard legacy shapes. Reserved Project-B columns (plane/provenance/geo_cc/geo_asn) created but unused. Task 1 of the Device Guardian consolidation plan (docs/superpowers/plans/ 2026-07-05-device-guardian-consolidation.md). * fix(nac): store — preserve first_seen, skip corrupt legacy sources, no stray db, SPDX (ref #817) * feat(nac): unified dnsmasq+ISC+ARP discovery merge (ref #817) * fix(nac): discovery — latest ISC lease wins the IP on renewal (ref #817) The merge loop only updated ip/source on a strict rank increase (incoming_rank > existing_rank), so equal-rank sightings for the same MAC never touched ip/source. Since dnsmasq -> isc -> arp is processed in non-increasing rank order, multiple ISC dhcpd.leases blocks for one MAC (a fresh block per renewal) are equal-rank ties, and the first (oldest) block's ip was frozen instead of the latest one winning, as the original secubox-device-intel._get_dhcp_leases did. Change the condition to incoming_rank >= existing_rank so the latest same-or-higher-rank sighting updates source, and overwrites ip when the incoming ip is non-empty. Hostname rule and the lower-rank branch are unchanged, so a later ARP sighting still cannot clobber a higher-rank ip/hostname/source. Add test_isc_latest_lease_wins: two ISC lease blocks for one MAC with ip/hostname renewal, asserting the latest block wins. Confirmed this test fails against the pre-fix >-only logic. * feat(nac): absorbed enrichers — OUI vendor + device-type/risk + OpenWrt fingerprint (ref #817) * fix(nac): enrich — is_router strictly vendor-based; cover classify/oui edge cases (ref #817) * feat(nac): background collector + double-cache; handlers def, no inline scan (ref #817) Task 4 of the Device Guardian consolidation: a Collector background loop now owns all discover -> enrich -> upsert work (replacing _monitor_clients), publishing an in-memory snapshot(). The status, clients, and client/{mac} handlers become plain def reading the SQLite store / collector cache instead of calling _discover_clients() inline on every request -- the #808 aggregator SPOF. * fix(nac): finish #808 — def-convert alerts/list_quarantine/summary; first_seen + recent_events (ref #817) alerts/list_quarantine were still `async def` calling blocking _discover_clients() inline on the shared aggregator loop; summary awaited alerts on top of that (double loop-block). Converted all three to plain `def` reading the SQLite store/collector snapshot instead, completing the #808 SPOF fix started for status/clients/client. Also: collector.cycle_once() now stamps first_seen on newly discovered devices (store.upsert keeps the earliest via COALESCE), and get_client's recent_events merges the SQLite device_history (client_joined) with the JSON event log so a device's join event shows up again. * feat(nac): allow/deny actions + def-convert action handlers (finish #808) (ref #817) Task 5: fold mac-guard's allow/deny into nac's zones/nft. New POST /allow/{mac} and /deny/{mac} set allow_state in the SQLite store and mirror it into nft's existing inet secubox_nac blocked/lan_allowed sets via _nft_add_element/_nft_delete_element (mac-guard's separate inet secubox_mac_guard table stays retired; its element migration is Task 9). Carried from Task 4 review: zones, add_to_zone, remove_from_zone, approve_client, ban_client, update_client, quarantine_client and unquarantine were still async def wrapping blocking subprocess/nft calls on the shared aggregator loop (#808). Converted to plain def so FastAPI threadpools them off the loop; add_to_zone/ban_client's webhook notify now fires via a new _fire_webhook_sync helper (asyncio.run_coroutine_threadsafe against the loop captured at startup) since a plain def can no longer await _notify_webhooks directly. Tests: tests/test_actions.py mocks nft via monkeypatched _nft_add_element/_nft_delete_element/_nft_list_set (+ subprocess.run, since ban_client/unban_client build raw nft argv) into an in-memory set-membership dict; covers deny/allow/allow-then-deny, zones, add_to_zone+approve_client, and ban_client+unban_client. * feat(nac): absorbed endpoints — vendors/scan/probe/mdns/groups/export (ref #817) * fix(nac): /scan enriches + validates subnet; /probe IP + CSV injection guards (ref #817) * feat(nac): retire mac-guard/device-intel/iot-guard via 308 redirects; auth-gate network-anomaly (ref #817) secubox-mac-guard, secubox-device-intel and secubox-iot-guard are superseded by secubox-nac's consolidated Device Guardian. Their api/main.py are reduced to thin shims: every route 308-redirects to its secubox-nac equivalent (/devices->/clients, /device/{mac}-> /client/{mac}, /whitelist|/allow->/allow, /blacklist|/deny->/deny, /scan, /vendors, /groups, /export/* pass through unchanged, and a catch-all forwards anything else), with an X-SecuBox-Deprecated header. /health stays a plain 200 so liveness probes never 308-loop. Package removal is a separate, gated follow-up. secubox-network-anomaly stays (separate traffic-anomaly engine) but its /status endpoint was unauthenticated while every sibling route already required a JWT; it now matches. * feat(nac): webui — vendor/type/risk columns, groups view, export; drop retired webuis (ref #817) - clients.js: render enriched /clients fields — oui_vendor, device_type, risk_level (color-coded badge)/risk_score, and OpenWrt/SecuBox/Router fingerprint badges. All values are attacker-influenceable (DHCP hostname/vendor) and are rendered exclusively via E()/textContent, never innerHTML. Null/missing device_type/vendor/risk render as "unknown"/"—", never "null". Adds an Export CSV button (direct link to GET /export/csv — auth via the existing SSO session cookie, same as every other same-origin nav link in this app; no new auth scheme). - groups.js (new): list/create/delete device groups and assign a device to a group, hitting GET/POST/DELETE /groups* — mirrors zones.js's structure and auth (sbxFetch). - nav.js: register the new "Groupes" tab alongside Zones. - Remove packages/secubox-{mac-guard,device-intel,iot-guard}/www — their functionality is now consolidated into nac; secubox-network-anomaly/www is untouched (stays standalone per plan). Note for Task 9: device-intel/iot-guard's debian/rules unconditionally `cp -r www/<name>/.` — now broken since www/ is gone; mac-guard's rule is already guarded (`[ -d www ] && ... || true`). Needs a debian/rules fix when Task 9 retires/redirects these packages. * chore(nac): packaging — ieee-data dep, nft migration, retirement redirects, changelog 3.0.0; fix retired debian/rules www (ref #817) * fix(nac): whole-branch — lazy init for in-aggregator mount, collector off-loop, sqlite lock, batched zone lookup, sentinel-preserve (ref #817) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(nac): risk_score split — known router low, unknown router high (rogue-AP signal) (ref #817) Split the router risk axis out of the generic device-type/open-ports scoring: a router/gateway already known (allow-listed or already in the store) is trusted infrastructure -> low risk; a newly-seen/unknown router is a rogue-AP signal -> high risk, regardless of open ports. Removes the old flat -10 "trusted router" discount. Non-router devices keep the existing scoring unchanged. risk_score() gains an is_known=False parameter (backward compatible). collector.cycle_once() and main.scan() now compute is_known from the prior store row (existing row or allow_state == "allow") before upserting, reusing the row they already fetch for is_new/enrichment. * feat(nac): mesh-sync (p2p peers as devices) + fingerprinted-router classification for rogue-AP risk (ref #817) Part A: absorb iot-guard's missed "mesh-sync" capability. GET /mesh/peers and POST /mesh/sync now live in nac, reading live P2P peers over /run/secubox/p2p.sock (HTTP-over-UDS GET /peers, fail-safe -> [] on any error/timeout/absent socket) and upserting one sb:-prefixed synthetic device per peer (iot-guard's exact md5-hash MAC scheme), device_type "mesh_node", source "mesh". iot-guard's retired redirect-shim catch-all already forwards /mesh/* here, so no shim change needed. Part B: classify_device_type's "router" keyword list is much narrower than ROUTER_VENDORS (misses tp-link/asus/linksys/d-link/gl.inet/xiaomi/ huawei), so a router-vendor MAC with a generic hostname fingerprinted is_router=True still classified as device_type="unknown" and skipped risk scoring entirely (the omit-unknown guard) -- the known-router-vs- rogue-AP HIGH signal never fired for the most common vendor case. Both enrichment call sites (Collector.cycle_once and /scan) now reclassify device_type="unknown"+is_router to "router" before scoring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(nac): postinst ensures secubox_nac table + zone sets (incl lxc_zone) Nothing shipped created nac's inet secubox_nac table or its zone sets — they were assumed to pre-exist (they don't: the live board had no such table), so operator 'move to zone' failed for every zone and the mac-guard element migration silently no-op'd. postinst now creates the table + all ZONES sets (lan_allowed, lxc_zone, iot_zone, guest_zone, quarantine_zone) + blocked, idempotently and best-effort, before the migration. Makes operator moves to the LXC Containers zone work on a fresh install. nft commands validated on gk2 (create/idempotent re-add/add-element/list), no live drift left. Co-Authored-By: Gerald KERMA <devel@cybermind.fr> --------- Co-authored-by: CyberMind-FR <gandalf@Gk2.net> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| architecture | ||
| assets | ||
| cspn | ||
| demos | ||
| design | ||
| errata | ||
| eye-remote | ||
| hardware | ||
| marketing | ||
| notes | ||
| reference | ||
| references/gst | ||
| reports | ||
| screenshots | ||
| specs | ||
| superpowers | ||
| wiki | ||
| AI-BUILD-PROMPT.md | ||
| AI-HANDOVER-cabine-evolution.md | ||
| AI-HANDOVER-mistral.md | ||
| CACHE-PATTERN.md | ||
| FAQ-BUSYBOX-RESCUE.md | ||
| FAQ-KBIN-TOR.md | ||
| FAQ-LXC-DNS.md | ||
| grammar.md | ||
| LED-HEALTHBUMP.md | ||
| LIVE-USB.md | ||
| MODULE-GUIDELINES.md | ||
| MODULES.md | ||
| OPENWRT-CRT-THEME.md | ||
| OPENWRT-DEBIAN-COMPARISON.md | ||
| OPENWRT-MASTERLINK.md | ||
| OPENWRT-MESH-DAEMON.md | ||
| P2P-EVOLUTIONS-POSTER-PROMPT.md | ||
| PROMPT-BUSYBOX-TECHTIP.md | ||
| SCREENSHOTS-VM.md | ||
| SECUBOX-DEV-METHODOLOGY.md | ||
| TOOLS.md | ||
| UI-GUIDE.md | ||