Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-089 — Réservation du SecurityManager : sécurité active per-process (couche 1)

Statut : Accepté (2026-07-10, décision BDFL) — ADR de réservation d’architecture. Grave l’existence, le rôle, le placement et le seam du SecurityManager ; le moteur (politique, règles, détection, enforcement concret) fera l’objet d’un ADR ultérieur. Companion ADR-032 (préservation des données), ADR-077 (Managers), ADR-073 (config binaire).

Catégorie : Architecture (sécurité, couche 1). N’altère aucune API scellée ; introduit un seam (interface + défaut permissif) câblé additivement.

Contexte

Air est secure-first, au service de la préservation des données confiées par l’utilisateur (charte ; ADR-032). La sécurité compte dès la couche 1, à deux étages :

  • Sécurité passive — ce que le kernel offre (contrôle d’accès fichiers par uid/gid, DAC, capabilities). Nécessaire mais insuffisante : elle ne protège pas contre l’abus dynamique d’un exécutable déjà autorisé (un binaire lancé par l’utilisateur qui tente d’allouer des pages énormes, boucle en fork-bomb de shells, ou subit un flood réseau).
  • Sécurité active — une décision au moment de l’opération : autoriser ou refuser, et le journaliser. C’est ce qui manque, et c’est l’objet du SecurityManager.

On façonne les Managers de domaine en ce moment (ADR-077, ADR-088AirTaskManager vient d’être posé). Réserver dès maintenant le point de consultation évite un rétro-fit transverse coûteux et risqué une fois les Managers stabilisés (Principe d’ingénierie 5 : sur-sécuriser puis mesurer, jamais l’inverse ; Principe 4 : validation en amont).

Décision

  1. Existence & rôle. Le SecurityManager (couche 1) est l’oracle de sécurité active d’Air. Tous les Managers sensibles consultent le SecurityManager AVANT une opération sensible. Il répond une décision Allow/Deny et journalise la raison du oui/non dans les logs machine (AirLog/journald) — traçabilité obligatoire.

  2. Placement : per-process, embarqué par libair — PAS un daemon. Un démon central devrait répondre à tous les process → goulot d’étranglement + point de défaillance unique. Le SecurityManager vit dans chaque process, fourni par libair, et est sollicité par les autres Managers du même process. La décision est locale ; l’enforcement passe par les mécanismes kernel partagés que la couche 0 expose déjà (famille security : eBPF — map de drop réseau —, cgroups — quotas mémoire/CPU —, seccomp, Landlock) : une décision locale a donc un effet machine-wide via le kernel. Les règles proviennent de la configuration binaire (ADR-073).

  3. Seam (ce qu’on pose maintenant). Une interface SecurityManagercheck(operation) -> Decision { Allow | Deny(motif) }, le motif étant journalisé — avec un défaut PERMISSIF (allow-all + log). Les Managers sensibles (AirTaskManager, AirNetworkManager, AirFileManager, AirMemoryManager…) consultent un SecurityManager. Le câblage de la consultation est incrémental (ajouté quand on touche chaque Manager), pas un big-bang. Tant que le moteur n’existe pas, le défaut permissif rend la consultation sans effet (mais la place et la trace de log existent).

  4. Exemples cadrant le besoin (non normatifs, pour la spéc du moteur) : > 50 tentatives de connexion en < 5 s depuis une même IP → poser dynamiquement une règle eBPF qui drop cette source ; exécutable qui tente d’allouer des pages énormes ou boucle en fork-bomb → refus + log.

  5. Explicitement DIFFÉRÉ (ADR ultérieur). Le moteur : format des règles, détection d’abus, rate-limiting, intégration concrète eBPF/cgroups, agrégation d’états, politique par défaut. À aligner sur air-sshd (ADR-074), premier vrai consommateur de sécurité active (flood de connexions).

Conséquences

  • Les Managers sensibles gagnent, au fil de l’eau, un point de consultation à défaut permissif — coût quasi nul, zéro effet fonctionnel tant que le moteur est absent.
  • Ne bloque pas le chantier PAL (ADR-088) : le PAL binde les Managers ; ce sont les Managers qui consultent le SecurityManager, pas le PAL. On peut poursuivre le reprofilage de la cible et l’implémentation du PAL.
  • À terme, le SecurityManager est le bras actif du « rempart devant le kernel » (doctrine userland Rust safe) : la sécurité passive (kernel) + la sécurité active (SecurityManager) se cumulent (defense in depth).
  • Placement per-process ⇒ le manager ne porte pas d’état machine-wide en propre ; l’agrégation et l’enforcement transverses passent par le kernel (maps eBPF, cgroups).

Alternatives rejetées

  • Démon de sécurité central : rejeté — goulot d’étranglement (répond à tous les process), point de défaillance unique, latence sur chaque opération sensible.
  • Ne rien réserver, décider plus tard : rejeté — rétro-fitter la consultation dans chaque Manager une fois l’API stabilisée est coûteux et risqué (Principe 5). Le coût de la réservation maintenant est quasi nul.
  • Sécurité passive kernel seule (DAC) : insuffisante contre l’abus dynamique d’un exécutable déjà autorisé (flood, fork-bomb, huge-alloc) — d’où le besoin d’un étage actif.
  • Tout spécifier maintenant (moteur inclus) : rejeté — dériverait le chantier PAL en cours ; le moteur mérite son propre ADR, informé par air-sshd.