Aller au contenu principal

V0.6.2 — Authentification des Flux

Publiée le 15/10/2026.

Documentation fonctionnelle

Ce que change la version pour les collaborateurs

Pourquoi​

Depuis la 0.6.1, l’UI, l’API et le Live passaient par une seule origine HTTPS et l’API exigeait une session, mais les Flux restaient en accès libre : nginx relayait WHEP (/flux/webrtc/…) et HLS (/flux/hls/…) vers MediaMTX sans demander de session, et RTSP 8554 était publié sur l’hôte, en clair et sans authentification. Avec de vraies caméras, le login d’ArgOS serait devenu décoratif : on aurait regardé n’importe quelle Caméra sans passer par la connexion.

Ce qu'on peut faire maintenant​

  • Regarder une Caméra demande d’être connecté à ArgOS : sans session, /flux/webrtc/… et /flux/hls/… répondent 401, même pour qui connaît le nom du chemin (camera-\<id> comme apercu-\<jeton>).
  • Le RTSP du pont n’est plus ouvert au réseau du Site : rtsp://\<IP du Site>:8554/… est refusé.
  • Le Live (WebRTC pour le H.264, HLS pour le H.265) et l’Aperçu marchent comme avant une fois connecté.
  • Si la session expire ou si on se déconnecte, l’écran du Live ou de l’Aperçu ramène à la connexion dès qu’un Flux est refusé, y compris dans Safari sur iPhone (HLS natif). Un Live WebRTC déjà ouvert continue jusqu’à la vidéo suivante : c’est une limite assumée.
  • En dev, les Flux restent lisibles depuis sa machine (rtsp://127.0.0.1:8554/camera-\<id>, VLC, ffprobe).
  • La Détection trouve toujours les Caméras et ne liste ni ArgOS ni le pont.

Documentation technique

Spec versionnée : docs/specs/v0.6.2-authentification-des-flux.md

Issue parente : #69

V0.6.2 — Authentification des Flux

Problem Statement​

Depuis la 0.6.1, l'UI, l'API et le Live passent par une seule origine HTTPS, et l'API exige une session. Mais les Flux restent en accès libre :

  • nginx relaie /flux/webrtc/… (WHEP) et /flux/hls/… (LL-HLS) vers MediaMTX sans demander de session : qui connaît le nom d'un chemin (camera-\<id>, apercu-\<jeton>) le lit ;
  • RTSP 8554 est publié sur l'hôte, en clair et sans authentification : tout poste du réseau local (Wi-Fi du Site, invités, caméra compromise) lit chaque Caméra active relayée par le pont.

Avec de vraies caméras, le login d'ArgOS deviendrait décoratif : on regarderait n'importe quelle Caméra sans passer par la connexion. C'est, avec la sécurisation d'ONVIF (0.6.3), un préalable à toute installation sur de vraies caméras (docs/securite.md).

Solution​

Regarder une Caméra passe par la connexion d'ArgOS :

  • WHEP et HLS : nginx vérifie la session ArgOS (cookie) à chaque requête /flux/… auprès de l'API (auth_request). Sans session valide : 401, rien n'est relayé vers MediaMTX. Toute session valide lit tout chemin servi par le pont (camera-\<id> et apercu-\<jeton>).
  • RTSP : 8554 n'est plus publié sur l'hôte en prod. Le pont ne sert RTSP qu'à l'intérieur du réseau Compose. En dev, la surimpression de simulation le republie sur 127.0.0.1:8554 seulement (CLI, VLC, tests).
  • MediaMTX reste sans authentification propre : il n'est plus joignable que par les conteneurs du réseau Compose (WHEP / HLS par web, API de contrôle par api). Le média WebRTC (8189/udp, DTLS-SRTP) reste publié : il ne s'ouvre qu'après une signalisation WHEP autorisée.
  • UI : un 401 du Live ou de l'Aperçu (WHEP ou HLS) renvoie à la connexion, comme un 401 de l'API.

La limite est assumée et écrite : le contrôle porte sur l'ouverture d'un Flux. Un Live WebRTC déjà établi continue après expiration de la session ou déconnexion ; un Live HLS s'arrête à la requête suivante.

User Stories​

Regarder une Caméra​

  1. En tant qu'Administrateur connecté, je veux que le Live et l'Aperçu marchent comme avant (WebRTC pour le H.264, HLS pour le H.265), sous l'origine HTTPS.
  2. En tant qu'Administrateur, je veux que personne sur le réseau du Site ne puisse lire un Flux par /flux/webrtc/… ou /flux/hls/… sans s'être connecté à ArgOS, même en connaissant le nom du chemin.
  3. En tant qu'Administrateur, je veux que personne sur le réseau du Site ne puisse lire un Flux en RTSP sur le Site (rtsp://\<IP du Site>:8554/…).
  4. En tant qu'Administrateur, je veux, quand ma session expire ou que je me déconnecte, que l'écran du Live ou de l'Aperçu me ramène à la connexion dès qu'un Flux est refusé, comme le reste de l'UI.

Détection​

  1. En tant qu'Administrateur, je veux que la Détection trouve toujours mes Caméras (et les Caméras simulées en dev) comme avant, et ne liste toujours pas ArgOS lui-même.

Dev​

  1. En tant que développeur, je veux lire les Flux du pont en RTSP depuis ma machine (rtsp://127.0.0.1:8554/camera-\<id>, ffprobe, VLC) quand la simulation est lancée, sans les exposer au réseau local.

Documentation​

  1. En tant que lecteur de docs/securite.md, je veux savoir ce qui protège désormais les Flux, ce qui reste ouvert (Live WebRTC déjà établi, MediaMTX sans authentification dans le réseau Compose, API de contrôle 9997), et pourquoi.
  2. En tant que lecteur du schéma réseau, je veux voir 8554 fermé sur l'hôte et /flux derrière la session.

Implementation Decisions​

  • Glossaire : inchangé (Flux, Aperçu, Live, Site suffisent).
  • ADR 0006 (docs/adr/0006-flux-authentifies-par-nginx.md) : « Flux authentifiés par nginx, MediaMTX sans authentification derrière le réseau Compose ». Compare auth_request nginx + cookie à l'authentification HTTP externe de MediaMTX (authMethod: http, jeton dans l'URL) et aux JWT MediaMTX (authMethod: jwt) ; écarte un identifiant de lecture interne pour MediaMTX tant que l'API de contrôle 9997 est ouverte en interne. Complète l'ADR 0005 (une origine) et l'ADR 0001 (le pont), sans les réécrire.
  • API : une route de vérification de session pour auth_request (2xx si la session du cookie est valide, 401 sinon), réutilisant administrateur_connecte. Pas de droits par chemin.
  • nginx (web/nginx.conf.template) : auth_request sur location /flux/webrtc/ et location /flux/hls/ ; la sous-requête transmet le cookie ; 401 renvoyé tel quel au navigateur. La route interne d'autorisation n'est pas le point d'entrée des Flux (le relais vers MediaMTX ne se fait qu'après 2xx).
  • Compose :
    • compose.yaml : 8554 retiré des ports de mediamtx (commentaire : réseau Compose seulement, docs/securite.md).
    • compose.simulation.yaml : 127.0.0.1:8554:8554 pour mediamtx.
  • MediaMTX (media/mediamtx.yml) : inchangé côté authentification (user: any) ; commentaire renvoyant à l'ADR 0006.
  • UI : le lecteur WHEP (fetch) et le lecteur HLS (hls.js, y compris les requêtes de segments et de playlists) branchent leur 401 sur le même rappel que web/src/api.ts (fermeture de la session côté UI, retour à la connexion).
  • Détection (api/argos_api/soi.py) : contrôle HTTPS de « soi » gardé comme garde-fou ; son commentaire dit qu'il ne joue plus que si 8554 (ou 554) est republié sur l'hôte.
  • Docs : docs/securite.md (sections MediaMTX, avec les limites ci-dessus), docs/features/reseau/schema-flux.md, docs/cameras/reseau-et-detection.md. Les specs et ADR antérieurs ne sont pas modifiés.

Testing Decisions​

  • Un bon test vérifie un comportement observable depuis l'hôte, un conteneur client ou le navigateur : code HTTP, Flux lu ou non, écran. Jamais la configuration nginx ou MediaMTX en elle-même.
  • tests/api/ (stack), prior art : tests/api/test_mediamtx_en_pont.py, tests/stack_compose.py :
    • sans cookie (ou cookie invalide, ou après DELETE /api/session) : WHEP (POST /flux/webrtc/\<chemin>/whep) → 401, playlist et segment HLS (/flux/hls/\<chemin>/…) → 401, pour camera-\<id> et pour un apercu-\<jeton> ;
    • avec session : WHEP accepte l'offre SDP, HLS sert la playlist d'une Caméra simulée H.265 (comme en 0.6.1) ;
    • 8554 ne répond pas sur l'hôte vu comme un poste du réseau local (passerelle du réseau de la stack depuis un conteneur ; sous Docker Desktop, host.docker.internal mène au loopback du Mac, où la simulation republie 8554) ;
    • le relais RTSP reste lisible depuis le réseau Compose (ffprobe attaché au réseau de la stack, rtsp://mediamtx:8554/\<chemin>) ;
    • la Détection trouve toujours les quatre Caméras simulées, ni la base, ni le pont, ni l'hôte (test existant inchangé).
  • tests/web/ (prior art : test_live.py, test_connexion.py) : Live H.264 et H.265 lus une fois connecté ; session fermée côté API pendant le Live → l'UI revient à la connexion au prochain Flux refusé.
  • Tests humains : depuis un autre poste du réseau, rtsp://\<IP du Site>:8554/camera-\<id> (VLC) échoue et une URL /flux/hls/… collée sans session renvoie 401 ; Live H.264 et H.265 dans Safari et Chrome une fois connecté ; déconnexion pendant un Live HLS → retour à la connexion.

Out of Scope​

  • Couper un Live WebRTC déjà établi à la déconnexion ou à l'expiration de la session (à ajouter en Plus tard).
  • Identifiant de lecture interne pour MediaMTX, et authentification de son API de contrôle 9997.
  • Droits de lecture par Caméra (multi-compte).
  • RTSP (ou RTSPS) authentifié pour un client externe (VLC, NVR).
  • Images versionnées et compose de prod (0.7.0).
  • ONVIF en HTTPS (0.6.3).

Changements apportés aux versions antérieures​

VersionÉlémentAvantAprèsÀ annoter
0.1.0Lecture RTSP des Flux sur le Sitertsp://\<hôte>:8554/… lisible depuis tout le réseau local8554 non publié en prod ; en dev (simulation), 127.0.0.1:8554 seulementv0.1.0, #1
0.3.0Relais du pont camera-\<id>lisible en RTSP 8554 et en WHEP sans authentificationRTSP réservé au réseau Compose ; WHEP exige la session ArgOS (401 sinon)v0.3.0, #12
0.4.0L'hôte du Site vu par la Détectionrépond en RTSP sur 8554, écarté par le contrôle HTTPS de « soi »ne répond plus en RTSP, donc n'est plus Candidat ; contrôle gardé comme garde-fou ; rien de visible pour l'Administrateurv0.4.0, #18
0.4.1Aperçu apercu-\<jeton>lisible par qui connaît le jeton (WHEP, HLS, RTSP)WHEP / HLS exigent la session ; RTSP réservé au réseau Composev0.4.1, #25
0.5.0Live HLS (H.265)/flux/hls/… lisible sans session (depuis 0.6.1 sous l'origine HTTPS)exige la session ArgOS (401 sinon)v0.5.0, #45
0.6.1Route /flux/ de nginxrelais vers MediaMTX sans sessionrelais seulement après auth_request validév0.6.1, #59

Further Notes​

  • La Détection n'est pas changée : elle sonde les caméras directement sur leurs ports ; l'hôte du Site, qui ne répond plus en RTSP, n'est plus Candidat dès l'OPTIONS.
  • Contexte : feuille de route de dev (section 0.6.2), docs/securite.md, docs/features/reseau/schema-flux.md, ADR 0001, 0004, 0005.