diff --git a/packages/secubox-profiles/debian/install b/packages/secubox-profiles/debian/install index 082418d5..75ccd77b 100644 --- a/packages/secubox-profiles/debian/install +++ b/packages/secubox-profiles/debian/install @@ -1,4 +1,5 @@ api/*.py usr/lib/secubox/profiles/api/ +profiles/*.toml usr/share/secubox/profiles/ sbin/secubox-profilectl usr/sbin/ www/profiles/index.html usr/share/secubox/www/profiles/ menu.d/11-profiles.json usr/share/secubox/menu.d/ diff --git a/packages/secubox-profiles/debian/postinst b/packages/secubox-profiles/debian/postinst index 18744778..df81c39a 100755 --- a/packages/secubox-profiles/debian/postinst +++ b/packages/secubox-profiles/debian/postinst @@ -15,6 +15,16 @@ case "$1" in # Phase 1 (scan) and is left untouched here. install -d -o secubox -g secubox -m 755 /etc/secubox/profiles + # Seed reference profiles into the operator-editable dir on first + # install only — never overwrite an edited profile on upgrade. + for f in /usr/share/secubox/profiles/*.toml; do + [ -e "$f" ] || continue + dest="/etc/secubox/profiles/$(basename "$f")" + if [ ! -e "$dest" ]; then + install -o secubox -g secubox -m 644 "$f" "$dest" + fi + done + # Own dedicated socket, own service — never served by the aggregator # (the profile engine must not depend on something it may later # restart). Restart (not just enable) so an upgrade picks up new code. diff --git a/packages/secubox-profiles/profiles/full.toml b/packages/secubox-profiles/profiles/full.toml new file mode 100644 index 00000000..b2589910 --- /dev/null +++ b/packages/secubox-profiles/profiles/full.toml @@ -0,0 +1,24 @@ +name = "full" +label = "Full — loadout courant (baseline)" +on = [ + "ad-guard", "admin", "aggregator", "annuaire", "appstore", "auth", + "avatar", "backup", "billets", "c3box", "cdn", "certs", + "cloner", "config-advisor", "cookies", "core", "crowdsec", "cs-bridge", + "cve-triage", "cyberfeed", "dns", "dns-guard", "dns-provider", "dpi", + "dpi-flowcap", "droplet", "exposure", "eye-remote", "eye-remote-dhcp", "fmrelay", + "frigate", "gitea", "glances", "grafana", "haproxy", "hardening", + "health-doctor", "health-prober", "hub", "identity", "interceptor", "ipblock", + "ksm", "led-heartbeat", "led-trigger", "leds", "localrecall", "lyrion", + "mail", "mcp-server", "mesh", "meshname", "metablogizer", "metabolizer", + "metacatalog", "metoblizer", "metrics", "mirror", "mitmproxy", "modem", + "module-prober", "mqtt", "nac", "ndpid", "netboot", "netdata", + "netdiag", "netifyd", "netmodes", "nettweak", "network-anomaly", "network-ready", + "nextcloud", "p2p", "peertube", "photoprism", "podcaster", "portal", + "proxypac", "publish", "qos", "reality", "repo", "reporter", + "rezapp", "roadmap", "routes", "rtty", "runtime", "rustdesk", + "saas-relay", "security-posture", "soc", "streamforge", "streamlit", "streamlit-routes", + "system", "threat-analyst", "threatmesh", "threats", "toolbox", "toolbox-mitm", + "tor", "traffic", "turn", "users", "vault", "vhost", + "vm", "vortex-dns", "vortex-firewall", "waf", "waf-ng", "waf-ratelimit", + "watchdog", "wireguard", "yacy", "zigbee", "zkp", +] diff --git a/packages/secubox-profiles/profiles/lite.toml b/packages/secubox-profiles/profiles/lite.toml new file mode 100644 index 00000000..b2244d35 --- /dev/null +++ b/packages/secubox-profiles/profiles/lite.toml @@ -0,0 +1,11 @@ +name = "lite" +label = "Lite — daily-driver optimisé" +on = [ + "ad-guard", "admin", "aggregator", "annuaire", "auth", "backup", + "cdn", "certs", "core", "crowdsec", "cs-bridge", "dns", + "dns-guard", "dns-provider", "exposure", "haproxy", "hardening", "health-doctor", + "hub", "ipblock", "led-trigger", "leds", "mesh", "netdata", + "network-ready", "p2p", "portal", "routes", "runtime", "system", + "users", "vhost", "vortex-firewall", "waf", "waf-ng", "waf-ratelimit", + "watchdog", "wireguard", +] diff --git a/packages/secubox-profiles/profiles/media-lab.toml b/packages/secubox-profiles/profiles/media-lab.toml new file mode 100644 index 00000000..af30433b --- /dev/null +++ b/packages/secubox-profiles/profiles/media-lab.toml @@ -0,0 +1,22 @@ +name = "media-lab" +label = "Media Lab — box maison-média" +on = [ + "ad-guard", "admin", "aggregator", "annuaire", "appstore", "auth", + "avatar", "backup", "billets", "c3box", "cdn", "certs", + "cloner", "config-advisor", "cookies", "core", "crowdsec", "cs-bridge", + "cyberfeed", "dns", "dns-guard", "dns-provider", "dpi", "dpi-flowcap", + "droplet", "exposure", "eye-remote", "eye-remote-dhcp", "fmrelay", "frigate", + "gitea", "glances", "grafana", "haproxy", "hardening", "health-doctor", + "health-prober", "hub", "identity", "ipblock", "ksm", "led-heartbeat", + "led-trigger", "leds", "localrecall", "lyrion", "mail", "mcp-server", + "mesh", "meshname", "metablogizer", "metacatalog", "metrics", "mirror", + "mitmproxy", "modem", "module-prober", "mqtt", "nac", "ndpid", + "netboot", "netdata", "netdiag", "netifyd", "netmodes", "nettweak", + "network-ready", "nextcloud", "p2p", "peertube", "photoprism", "podcaster", + "portal", "proxypac", "publish", "qos", "reality", "repo", + "reporter", "rezapp", "roadmap", "routes", "rtty", "runtime", + "rustdesk", "saas-relay", "streamforge", "streamlit", "streamlit-routes", "system", + "threats", "tor", "traffic", "turn", "users", "vault", + "vhost", "vm", "vortex-dns", "vortex-firewall", "waf", "waf-ng", + "waf-ratelimit", "watchdog", "wireguard", "yacy", "zigbee", "zkp", +] diff --git a/packages/secubox-profiles/profiles/secure-gateway.toml b/packages/secubox-profiles/profiles/secure-gateway.toml new file mode 100644 index 00000000..3c779291 --- /dev/null +++ b/packages/secubox-profiles/profiles/secure-gateway.toml @@ -0,0 +1,7 @@ +name = "secure-gateway" +label = "Secure Gateway — appliance durcie" +on = [ + "aggregator", "auth", "certs", "core", "crowdsec", "dns", + "dns-guard", "dns-provider", "exposure", "haproxy", "hardening", "ipblock", + "users", "vortex-firewall", "waf", "waf-ng", "waf-ratelimit", +] diff --git a/packages/secubox-profiles/tests/test_profiles_data.py b/packages/secubox-profiles/tests/test_profiles_data.py new file mode 100644 index 00000000..75ced7bf --- /dev/null +++ b/packages/secubox-profiles/tests/test_profiles_data.py @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: LicenseRef-CMSD-1.0 +# Copyright (c) 2026 CyberMind — Gérald Kerma +# Source-Disclosed License — All rights reserved except as expressly granted. +# See LICENCE-CMSD-1.0.md for terms. +from pathlib import Path + +import pytest + +from api.state import load_profile + +PROFILES_DIR = Path(__file__).resolve().parent.parent / "profiles" +PROFILE_FILES = sorted(PROFILES_DIR.glob("*.toml")) +EXPECTED = {"full", "lite", "secure-gateway", "media-lab"} + + +def test_all_four_profiles_ship(): + assert {p.stem for p in PROFILE_FILES} == EXPECTED + + +@pytest.mark.parametrize("path", PROFILE_FILES, ids=lambda p: p.stem) +def test_profile_loads_and_name_matches_stem(path): + prof = load_profile(path) # raises StateError if name != stem or bad 'on' + assert prof.name == path.stem + assert prof.on, f"{path.stem}: empty on-list" + for mid in prof.on: + assert mid and mid == mid.strip() and " " not in mid, f"bad id {mid!r}" + + +def test_protected_core_present_in_every_profile(): + # aggregator/auth/core are protected (always ON) but every functional tier + # lists them explicitly for readability; guard that nobody drops them. + for path in PROFILE_FILES: + on = load_profile(path).on + assert {"core", "auth", "aggregator"} <= on, f"{path.stem} missing protected"