build(toolbox): package rlevel (policyctl, sudoers, panel, seed default_mode) + changelog

secubox-toolbox: install sbxmitm-policyctl (0755), the /rlevel panel +
menu.d entry, and a scoped sudoers.d/secubox-toolbox granting the portal
(User=secubox-toolbox) exactly the 5 policyctl subcommands
(set-floor|force|set-chosen|set-default|list) — no blanket ctl grant.
postinst seeds /var/lib/secubox/toolbox/peer-rlevel.json with
defaults.mode="reel" (never overwritten on upgrade, leaf-only chown) to
preserve current fleet-wide MITM behaviour instead of a surprise
fleet-wide downgrade; operators opt individual peers down afterwards.
control: + sudo (transport for the ctl delegation).

secubox-toolbox-ng: changelog bump only — rlevel.go/rlevel_test.go build
into the existing sbxmitm binary (same Go package), no rules/control
change needed. Cross-build verified: GOARCH=arm64 GOOS=linux go build
-mod=vendor produces a valid ARM aarch64 ELF; go test ./... passes in
full.

nftables.d @rlevel_off set + off-bypass rule were already shipped by the
existing execute_after_dh_auto_install block — verified, not touched.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
This commit is contained in:
CyberMind-FR 2026-07-24 16:25:08 +02:00
parent 668d920076
commit 8dc288db78
7 changed files with 211 additions and 208 deletions

View File

@ -1,234 +1,149 @@
# Task 8 — Rapport : TLS pour la série Z (nginx dans le LXC, secubox-picobrew)
# Task 8 — Rapport : Packaging + cross-build + rolling-deploy recipe (rlevel-per-peer)
**Statut :** Terminé.
(Note : ce fichier contenait précédemment un rapport Task-8 sans rapport avec
ce plan — sleeper `serve` daemon loop / secubox-profiles, ref #896 — écrasé
ici car il ne concernait pas ce plan.)
ce plan — TLS série Z / secubox-picobrew — écrasé ici car il ne concernait pas
le plan `feat/rlevel-per-peer`.)
## Commit
`bde53fb0` — "feat(picobrew): terminaison TLS dans le LXC pour la série Z"
Fichiers modifiés (scope volontairement limité à ces deux-là) :
- `packages/secubox-picobrew/sbin/picobrewctl` (modifié)
- `packages/secubox-picobrew/tests/test_ctl_tls.py` (créé)
`build(toolbox): package rlevel (policyctl, sudoers, panel, seed default_mode) + changelog`
## Séquence TDD
Fichiers modifiés/créés :
- `packages/secubox-toolbox/debian/rules` — installe `sbxmitm-policyctl` (0755),
`www/rlevel/``usr/share/secubox/www/rlevel/`, `menu.d/27-rlevel.json`, et
`debian/secubox-toolbox.sudoers``/etc/sudoers.d/secubox-toolbox` (0440).
- `packages/secubox-toolbox/debian/secubox-toolbox.sudoers` (créé) — 5 lignes,
une par sous-commande fixée (`set-floor *`, `force *`, `set-chosen *`,
`set-default *`, `list`), user `secubox-toolbox` (le `User=` du
`systemd/secubox-toolbox.service`), pas de `sbxmitm-policyctl ALL`.
Validé `visudo -cf` : OK.
- `packages/secubox-toolbox/debian/postinst` — seed idempotent de
`/var/lib/secubox/toolbox/peer-rlevel.json`
(`{"defaults":{"mode":"reel","floor":"passive"},"peers":{}}`), jamais
écrasé sur upgrade, chown/chmod du fichier seul (aucun parent partagé
touché). Choix `default_mode="reel"` documenté en commentaire +
changelog : préserve le comportement actuel (tout peer MITM'd + block
honoré) pour éviter un downgrade fleet-wide surprise au déploiement ;
les opérateurs abaissent ensuite par-peer.
- `packages/secubox-toolbox/debian/control` — ajoute `sudo` aux `Depends`
(transport de délégation `sudo -n` utilisé par `secubox_toolbox/api.py`
pour appeler le ctl).
- `packages/secubox-toolbox/debian/changelog` — bump `2.8.6``2.8.7-1~bookworm1`.
- `packages/secubox-toolbox-ng/debian/changelog` — bump `0.1.37``0.1.38-1~bookworm1`
(aucun changement `control`/`rules` : `rlevel.go` compile dans le binaire
`sbxmitm` existant, même package Go, aucun fichier d'install nouveau).
1. Test écrit (`test_ctl_tls.py`, verbatim du brief, 3 cas : TLS sur 443,
`proxy_pass` vers `127.0.0.1:80`, absence de `listen 80`).
2. Run initial → échec confirmé, `__emit-nginx` inconnu :
```
FFF
AssertionError: usage: picobrewctl {install|start|stop|status [--json]|update <sha>|logs}
assert 1 == 0
3 failed in 0.08s
```
3. Implémentation ajoutée (verbatim du brief) avant `usage()` :
`_emit_nginx_config` (heredoc `<<'EOF'` — délimiteur **quoté**, donc pas
d'interpolation bash de `$host`/`$remote_addr`) et `_ensure_cert`
(génération de certificat auto-signé via `lxc_attach`, effet de bord
confiné au conteneur, jamais sur l'hôte). Branche
`__emit-nginx) _emit_nginx_config ;;` ajoutée dans le `case`, avant `*)`.
Câblage dans `cmd_install` juste avant `_install_service_unit` :
`_ensure_cert`, écriture de la config dans `sites-available`, symlink vers
`sites-enabled`, suppression du vhost `default`, `nginx -t` puis
`systemctl enable --now nginx`.
4. Re-run → vert :
```
syntaxe OK
...
3 passed in 0.06s
```
Vérifié déjà en place (rien à ajouter) :
- `nftables.d/secubox-toolbox-wg.nft` + `-wg-fanout.nft` (named set
`@rlevel_off` + `ip saddr @rlevel_off return`) sont déjà installés par
`execute_after_dh_auto_install` dans `debian/rules` (confirmé par grep).
- API `/rlevel` déjà dans `secubox_toolbox/api.py`, packagée avec le reste
du module Python (`cp -r secubox_toolbox`), rien à ajouter.
## Vérifications obligatoires — sorties réelles
## Cross-build Go arm64
### `cd packages/secubox-picobrew && python3 -m pytest tests/ -q` (suite complète)
```
................... [100%]
19 passed in 0.34s
cd packages/secubox-toolbox-ng && GOARCH=arm64 GOOS=linux go build -mod=vendor -o /tmp/sbxmitm ./cmd/sbxmitm
file /tmp/sbxmitm
# ELF 64-bit LSB executable, ARM aarch64, ..., statically linked
```
**OK**. `rlevel.go`/`rlevel_test.go`/`rlevel_wire_test.go` déjà présents dans
`cmd/sbxmitm/`, même package `main` — inclus automatiquement, aucune
modification de `debian/rules` (toolbox-ng) nécessaire.
### `bash tests/test_picobrewctl_guards.sh`
## Tests
- `go test -mod=vendor ./cmd/sbxmitm/`**PASS**.
- `go test -mod=vendor ./...` (suite complète toolbox-ng : sbx-sentinel,
sbxmitm, sbxwaf, internal/forge, httpcodec, relay, reload, sentinel) →
**PASS** (8/8 packages ok).
- `pytest tests/test_rlevel_api.py tests/test_rlevel_panel.py` (secubox-toolbox)
**36 passed**.
- Suite complète `pytest tests/` (secubox-toolbox, 373 tests) → **335 passed,
3 failed** — les 3 échecs sont **préexistants, hors scope** :
`test_bypass_sources.py::test_load_bypass_tagged_missing_source_skipped`
(drift schéma non lié à rlevel, commit `45f8397e` antérieur à cette
branche) et 2 échecs `test_media_stats.py` (`ModuleNotFoundError:
secubox_core` — artefact d'environnement local, module hors PYTHONPATH du
venv de test, pas un régression rlevel). Vérifié : ces 3 tests échouent
déjà indépendamment de nos modifications.
## Build des `.deb`
**secubox-toolbox (arch:all)** :
```
PASS accept sha '0123456789abcdef0123456789abcdef01234567'
PASS reject sha 'HEAD'
PASS reject sha 'main'
PASS reject sha '0123456789abcdef0123456789abcdef0123456'
PASS reject sha '0123456789ABCDEF0123456789ABCDEF01234567'
PASS reject sha 'v1.0; rm -rf /'
PASS reject unknown cmd
cd packages/secubox-toolbox && dpkg-buildpackage -us -uc -b
```
7/7 PASS.
### `bash -n sbin/picobrewctl`
**OK**, `secubox-toolbox_2.8.7-1~bookworm1_all.deb` produit.
`dpkg-deb -c` confirme :
```
syntaxe OK
./etc/sudoers.d/secubox-toolbox (0440 root:root)
./usr/sbin/sbxmitm-policyctl (0755)
./usr/share/secubox/menu.d/27-rlevel.json
./usr/share/secubox/www/rlevel/index.html
```
(aucune sortie d'erreur — syntaxe bash valide, `set -e` toujours absent du
script, `set -uo pipefail` inchangé)
`bash -n postinst` (extrait du .deb, post `#DEBHELPER#` substitution par
dh_installsystemd) → OK, `#DEBHELPER#` correctement remplacé (aucune
occurrence littérale restante), `exit 0` final présent.
### Sortie réelle de `bash sbin/picobrewctl __emit-nginx` (preuve du non-interpolage)
Avertissements préexistants, hors scope de cette tâche (non liés à rlevel) :
`${python3:Depends}` non substituée et conffile `/etc/secubox/toolbox.toml`
« dupliqué » — déjà présents avant ce commit.
**secubox-toolbox-ng (arch:arm64)** :
```
# SecuBox-Deb :: PicoBrew — terminaison TLS pour la série Z.
#
# picobrew_pico écoute déjà en clair sur :80 — c'est le comportement upstream,
# et c'est ce que les Pico/Zymatic attendent. nginx ne prend donc QUE le 443 :
# le faire écouter aussi sur :80 tout en proxifiant vers 127.0.0.1:80 le ferait
# se parler à lui-même (boucle infinie). Les appareils non-Z continuent de
# joindre Flask directement en :80.
server {
listen 443 ssl;
server_name picobrew.com _;
client_max_body_size 32m;
ssl_certificate /etc/picobrew/tls/cert.pem;
ssl_certificate_key /etc/picobrew/tls/key.pem;
location / {
proxy_pass http://127.0.0.1:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
cd packages/secubox-toolbox-ng && dpkg-buildpackage -a arm64 -us -uc -b
```
`$host` et `$remote_addr` apparaissent **littéralement** dans la sortie (pas
de substitution bash — ces variables n'existent pas dans le shell hôte, une
interpolation les aurait remplacées par une chaîne vide). Le heredoc utilise
le délimiteur quoté `<<'EOF'`, ce qui désactive toute expansion. Confirmé
aussi dans cette même sortie : `listen 443 ssl` présent une seule fois,
`proxy_pass http://127.0.0.1:80` présent, et **aucune** occurrence de
`listen 80`.
**Bloqué par le dependency-checker** : `dpkg-checkbuilddeps` exige
`golang-go` pour l'arch hôte **arm64** (`golang-go:arm64`), absent de cette
machine (seul `golang-go:amd64` est installé — pas de support multiarch Go
sur ce poste). C'est une limitation de l'outillage dpkg de vérification des
Build-Depends pour une cross-compilation Go pure (`CGO_ENABLED=0`), pas un
problème du build lui-même : Go cross-compile sans avoir besoin d'un
toolchain arm64 installé.
Contournement de **vérification uniquement** (`dpkg-buildpackage -a arm64 -d
...`, `-d` = ignore les dépendances de build) : le build réel a ensuite
**réussi** — `secubox-toolbox-ng_0.1.38-1~bookworm1_arm64.deb` produit,
`dpkg-deb -c` confirme `./usr/sbin/sbxmitm` (0755), et le binaire extrait est
bien `ELF ... ARM aarch64 ... stripped`. `bash -n` sur le postinst extrait →
OK, `#DEBHELPER#` correctement substitué.
Le `.deb` produit avec `-d` est donc valide et déployable, mais un build CI
« propre » sur cette machine échouerait à la porte `dpkg-checkbuilddeps` tant
que `golang-go:arm64` (ou l'équivalent multiarch) n'est pas installé — ceci
est indépendant de ce plan et déjà vrai avant ce commit (aucune régression
introduite ici). Le binaire cross-buildé de l'étape 4 (`/tmp/sbxmitm`) reste
la référence pour un déploiement manuel immédiat si le `.deb` CI n'est pas
disponible.
## Diff appliqué (`sbin/picobrewctl`)
## Nettoyage post-build
Conforme verbatim au brief : ajout de `_emit_nginx_config`, `_ensure_cert`,
branche `__emit-nginx` avant `*)` dans le `case`, et câblage dans
`cmd_install` juste avant `_install_service_unit`. Vérifié via `git diff` :
deux blocs d'ajout uniquement, aucune suppression ni altération de code
existant.
Un fichier binaire préexistant et suivi par git,
`packages/secubox-toolbox-ng/sbx-sentinel` (déjà commité avant ce plan, non
gitignoré contrairement à `/sbxmitm`/`/sbxwaf`), a été régénéré à l'identique
(diff binaire, mêmes octets logiques mais horodatage/BuildID différents) par
`dh_auto_build`. Restauré via `git restore` pour ne pas polluer le commit
avec un artefact de build — signalé ici pour traçabilité, aucune action
requise côté plan (préexistant, hors scope).
```diff
@@ cmd_install() { ... } @@
+ _ensure_cert || { err "génération du certificat échouée"; return 1; }
+ _emit_nginx_config > "$LXC_PATH/$CONTAINER/rootfs/etc/nginx/sites-available/picobrew"
+ lxc_attach 'ln -sf /etc/nginx/sites-available/picobrew /etc/nginx/sites-enabled/picobrew
+ rm -f /etc/nginx/sites-enabled/default
+ nginx -t >/dev/null 2>&1 && systemctl enable --now nginx' \
+ || { err "configuration nginx invalide"; return 1; }
+
_install_service_unit
...
@@ après cmd_update(), avant usage() @@
+_emit_nginx_config() {
+ cat <<'EOF'
+ ...(config nginx, listen 443 ssl uniquement)...
+EOF
+}
+
+_ensure_cert() {
+ lxc_attach 'set -e
+ mkdir -p /etc/picobrew/tls
+ [ -s /etc/picobrew/tls/cert.pem ] && exit 0
+ openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
+ -subj "/CN=picobrew.com" \
+ -addext "subjectAltName=DNS:picobrew.com,DNS:*.picobrew.com" \
+ -keyout /etc/picobrew/tls/key.pem \
+ -out /etc/picobrew/tls/cert.pem >/dev/null 2>&1
+ chmod 600 /etc/picobrew/tls/key.pem'
+}
@@ case "${1:-}" in ... @@
__emit-config) _emit_lxc_config ;;
+ __emit-nginx) _emit_nginx_config ;;
```
Aucun `.deb`, `.buildinfo`, `.changes`, `debian/secubox-toolbox*/` de staging,
`.substvars` n'a été ajouté au commit — tous confirmés `git status
--ignored` sous les règles `.gitignore` existantes.
## Préoccupations
- `_ensure_cert` et le câblage nginx de `cmd_install` (symlink,
`nginx -t`, `systemctl enable --now nginx`) dépendent de `lxc_attach`,
donc d'un conteneur LXC réellement démarré — non testable en CI hors
environnement LXC. Seule `_emit_nginx_config` (sans effet de bord, stdout
uniquement, comme exigé) est couverte par des tests automatisés ; c'est le
même niveau de couverture que le reste du module (`_emit_lxc_config` /
`cmd_install` suivent déjà ce schéma — pas de régression de rigueur).
- Aucune régression détectée : 19/19 tests pytest du module (dont les 3
nouveaux) et 7/7 gardes shell passent après la modification.
---
## Correctif de revue — `enable --now nginx``enable && restart` (post-Task 8)
**Statut :** Terminé.
### Défaut relevé en revue
`nginx` figure dans `--include=` du debootstrap ; le paquet Debian
auto-active son unit via preset. Sur un conteneur fraîchement débootstrappé,
nginx tourne donc déjà (vhost `default` stock, `listen 80 default_server`)
avant même l'écriture de la config TLS. `systemctl enable --now nginx` sur
une unit **déjà active** est un no-op côté (re)démarrage : la nouvelle
config 443 n'est jamais chargée par le process en mémoire, et nginx reste
planté sur `:80`, empêchant ensuite `picobrew.service` (Flask) de se lier
sur ce port. Installation bloquée sur tout conteneur neuf.
### Correctif
Dans `cmd_install`, remplacement de :
```bash
nginx -t >/dev/null 2>&1 && systemctl enable --now nginx
```
par :
```bash
nginx -t >/dev/null 2>&1 && systemctl enable nginx && systemctl restart nginx
```
Commentaire ajouté juste avant le bloc `lxc_attach` expliquant pourquoi
`restart` (et non `enable --now`) est requis, pour empêcher qu'un futur
lecteur ne « simplifie » en réintroduisant le bug.
Conservé à l'identique : `nginx -t` avant toute (re)activation, le
`|| { err "configuration nginx invalide"; return 1; }`, `set -uo pipefail`
en tête sans `set -e` au niveau du script, et le reste de `cmd_install`
(ordre `_ensure_cert` → écriture config → nginx → `picobrew.service`).
### Vérifications obligatoires — sorties réelles
`bash -n sbin/picobrewctl` → aucune sortie, syntaxe OK.
`bash tests/test_picobrewctl_guards.sh` (depuis `packages/secubox-picobrew`) :
```
PASS accept sha '0123456789abcdef0123456789abcdef01234567'
PASS reject sha 'HEAD'
PASS reject sha 'main'
PASS reject sha '0123456789abcdef0123456789abcdef0123456'
PASS reject sha '0123456789ABCDEF0123456789ABCDEF01234567'
PASS reject sha 'v1.0; rm -rf /'
PASS reject unknown cmd
```
7/7 PASS.
`cd packages/secubox-picobrew && python3 -m pytest tests/ -q` :
```
................... [100%]
19 passed in 0.31s
```
`bash sbin/picobrewctl __emit-nginx` : sortie strictement identique à celle
documentée plus haut dans ce fichier (mêmes octets, `listen 443 ssl`
uniquement, `proxy_pass http://127.0.0.1:80`), confirmée par
`grep -n "listen 80"` → aucune occurrence.
`git diff` sur `packages/secubox-picobrew/sbin/picobrewctl` : diff minimal,
un commentaire ajouté + une ligne modifiée (`enable --now nginx` →
`enable nginx && systemctl restart nginx`), aucun autre changement.
### Préoccupations
- Comme pour le reste du câblage nginx/LXC de ce module, ce chemin dépend de
`lxc_attach` (conteneur réellement démarré) et n'est donc pas couvert par
un test automatisé direct — même limite déjà documentée plus haut pour
`_ensure_cert`/`cmd_install`. Seule la non-régression de `_emit_nginx_config`
(sortie statique) est vérifiable en CI, et elle est confirmée inchangée.
- Le correctif n'a pas été testé en conditions réelles sur un LXC fraîchement
débootstrappé (pas d'accès à un tel environnement dans cette session) ;
la garantie repose sur la sémantique documentée de `systemctl restart`
(fonctionne indifféremment sur une unit active ou arrêtée).
1. **arm64 cross-build CI** : si le runner CI n'a pas `golang-go:arm64`
(multiarch) installé, `dpkg-checkbuilddeps` bloquera le build
`secubox-toolbox-ng` même si le binaire compile parfaitement (Go pur,
`CGO_ENABLED=0`). À vérifier sur l'environnement CI réel — probablement
déjà résolu là-bas (image cross dédiée) puisque ce n'est pas nouveau à ce
plan.
2. **3 tests pytest préexistants en échec** (`test_bypass_sources.py` +
`test_media_stats.py` ×2) — sans rapport avec rlevel, mais à corriger
séparément (drift de schéma bypass-sources ; `secubox_core` absent du
PYTHONPATH de test local).
3. **Recette de rolling-deploy** (rolling restart des 4 workers,
`sudo -n` avant chaque appel ctl, vérification bypass nft "off") reste à
exécuter manuellement sur le board — hors périmètre de cette tâche de
packaging (cf. section « Recette de déploiement » du brief).

View File

@ -1,3 +1,18 @@
secubox-toolbox-ng (0.1.38-1~bookworm1) bookworm; urgency=medium
* sbxmitm: per-peer R-level MITM policy (rlevel-per-peer, task 8). The
worker fleet (cmd/sbxmitm/rlevel.go) now loads/hot-reloads
/var/lib/secubox/toolbox/peer-rlevel.json (written by the new
sbxmitm-policyctl in secubox-toolbox) and computes each peer's effective
inspection level (off < passive < active < reel = forced ?? clamp(chosen,
floor, reel)). Companion secubox-toolbox package seeds
defaults.mode="reel" on first install to preserve today's fleet-wide
behaviour (no silent downgrade); operators opt individual peers down via
the /rlevel panel or the ctl. No control/rules change here — rlevel.go
builds into the existing sbxmitm binary (same package, no new file).
-- Gerald KERMA <devel@cybermind.fr> Fri, 24 Jul 2026 09:00:00 +0200
secubox-toolbox-ng (0.1.37-1~bookworm1) bookworm; urgency=medium
* sbxwaf: fingerprint scanners on static-asset paths. Previously any path

View File

@ -1,3 +1,24 @@
secubox-toolbox (2.8.7-1~bookworm1) bookworm; urgency=medium
* rlevel-per-peer: package the R-level MITM policy surface (#rlevel-per-peer,
task 8). Ships sbxmitm-policyctl (root-scoped ctl owning peer-rlevel.json +
the @rlevel_off nft set), the /rlevel admin+self-service panel and its
menu.d entry, and a scoped sudoers.d/secubox-toolbox that only lets the
portal (User=secubox-toolbox) invoke the five fixed policyctl subcommands
(set-floor|force|set-chosen|set-default|list) — no blanket
`sbxmitm-policyctl ALL`. The panel's nftables.d off-bypass (@rlevel_off set
in secubox-toolbox-wg.nft + secubox-toolbox-wg-fanout.nft) already ships
via the existing nftables.d install block.
postinst seeds /var/lib/secubox/toolbox/peer-rlevel.json with
defaults.mode="reel" (never overwritten on upgrade) — a DELIBERATE choice
to PRESERVE current fleet-wide behaviour (every peer fully MITM'd + the
existing block policy honoured) instead of a surprise fleet-wide downgrade
to a lighter default at deploy time; operators opt individual peers DOWN
afterwards via the panel or the ctl.
Depends: + sudo (delegation transport for the ctl).
-- Gerald KERMA <devel@cybermind.fr> Fri, 24 Jul 2026 09:00:00 +0200
secubox-toolbox (2.8.6-1~bookworm2) bookworm; urgency=medium
* autolearn: NEVER-SPLICE guard so ad/tracker networks are never promoted to

View File

@ -34,7 +34,8 @@ Depends: ${misc:Depends}, ${python3:Depends},
python3-qrcode,
python3-geoip2 | geoipupdate,
lxc,
debian-archive-keyring
debian-archive-keyring,
sudo
Recommends: bridge-utils,
tor,
obfs4proxy,

View File

@ -104,6 +104,28 @@ SBXFILTERS
mkdir -p /var/lib/secubox/toolbox
chown secubox-toolbox:secubox-toolbox /var/lib/secubox/toolbox 2>/dev/null || true
chmod 0750 /var/lib/secubox/toolbox 2>/dev/null || true
# rlevel-per-peer (#task-8) : seed the per-peer wg-toolbox MITM policy
# store consumed by sbxmitm-policyctl + the Go workers (cmd/sbxmitm/
# rlevel.go). NEVER overwrite an existing file (would clobber operator
# per-peer settings on upgrade — leaf file only, no shared-parent chown).
#
# default_mode="reel" is a DELIBERATE choice: it PRESERVES today's
# behaviour (every wg-toolbox peer fully MITM'd + the existing block
# policy honoured), so installing/upgrading this package does NOT
# silently downgrade inspection for the whole fleet. Operators/admins
# opt individual peers DOWN to active/passive/off afterwards via the
# /rlevel panel or sbxmitm-policyctl — this is a privacy-forward
# opt-DOWN model, not an opt-in-UP one, to avoid a surprise fleet-wide
# relaxation at deploy time.
if [ ! -f /var/lib/secubox/toolbox/peer-rlevel.json ]; then
cat > /var/lib/secubox/toolbox/peer-rlevel.json <<'SBXRLEVEL'
{"defaults":{"mode":"reel","floor":"passive"},"peers":{}}
SBXRLEVEL
chown secubox-toolbox:secubox-toolbox /var/lib/secubox/toolbox/peer-rlevel.json 2>/dev/null || true
chmod 0640 /var/lib/secubox/toolbox/peer-rlevel.json 2>/dev/null || true
fi
# #577 : shared media proxy-cache dir (opt-in via filters ; 2 GB LRU).
mkdir -p /var/cache/secubox/toolbox/media
chown secubox-toolbox:secubox-toolbox /var/cache/secubox/toolbox/media 2>/dev/null || true

View File

@ -21,13 +21,25 @@ override_dh_auto_install:
# WebUI
install -d debian/secubox-toolbox/usr/share/secubox/www/toolbox
cp -r www/toolbox/. debian/secubox-toolbox/usr/share/secubox/www/toolbox/
# rlevel-per-peer (task 8) : panel is served alongside the toolbox WebUI.
install -d debian/secubox-toolbox/usr/share/secubox/www/rlevel
cp -r www/rlevel/. debian/secubox-toolbox/usr/share/secubox/www/rlevel/
# Menu
install -d debian/secubox-toolbox/usr/share/secubox/menu.d
install -m 0644 menu.d/26-toolbox.json debian/secubox-toolbox/usr/share/secubox/menu.d/
install -m 0644 menu.d/27-rlevel.json debian/secubox-toolbox/usr/share/secubox/menu.d/
# Helpers
install -d debian/secubox-toolbox/usr/sbin
install -m 0755 scripts/toolbox-up debian/secubox-toolbox/usr/sbin/
install -m 0755 scripts/ca-init debian/secubox-toolbox/usr/sbin/secubox-toolbox-ca-init
# rlevel-per-peer (task 4/8) : root-scoped ctl owning peer-rlevel.json +
# the @rlevel_off nft set (see sbin/sbxmitm-policyctl header).
install -m 0755 sbin/sbxmitm-policyctl debian/secubox-toolbox/usr/sbin/
# Scoped sudoers: the portal (User=secubox-toolbox) may only invoke the
# 5 fixed policyctl subcommands — no wildcard, no arbitrary root command.
install -d debian/secubox-toolbox/etc/sudoers.d
install -m 0440 debian/secubox-toolbox.sudoers \
debian/secubox-toolbox/etc/sudoers.d/secubox-toolbox
# sbin/ helpers (Phase 5 LXC, Phase 6 R3 WG, Phase 9 fanout, Phase 11 social).
# Pre-2.6.0 only db-tune + lxc-provision shipped — the mitm-wg-launch
# wrapper had to be hand-installed on the board. This block ships them

View File

@ -0,0 +1,17 @@
# rlevel-per-peer (#task-8) : the portal (User=secubox-toolbox, see
# systemd/secubox-toolbox.service) delegates every privileged mutation of
# /var/lib/secubox/toolbox/peer-rlevel.json + the @rlevel_off nft set to
# sbxmitm-policyctl (see sbin/sbxmitm-policyctl header) via `sudo -n`.
#
# Fixed verbs only — no blanket `sbxmitm-policyctl ALL`, so a future
# subcommand added to the ctl is NOT automatically grantable without a
# packaging change here. Trailing `*` wildcards only the pubkey/mode
# ARGUMENTS of an already-pinned verb (mirrors the wg show * pattern in
# secubox-wireguard) — the verb itself never has a wildcard.
# Relies on sudo's default env_reset (do NOT add SETENV/env_keep — the ctl
# also refuses env overrides as root, see the SBXMITM_POLICYCTL_TEST guard).
secubox-toolbox ALL=(root) NOPASSWD: /usr/sbin/sbxmitm-policyctl set-floor *
secubox-toolbox ALL=(root) NOPASSWD: /usr/sbin/sbxmitm-policyctl force *
secubox-toolbox ALL=(root) NOPASSWD: /usr/sbin/sbxmitm-policyctl set-chosen *
secubox-toolbox ALL=(root) NOPASSWD: /usr/sbin/sbxmitm-policyctl set-default *
secubox-toolbox ALL=(root) NOPASSWD: /usr/sbin/sbxmitm-policyctl list