Aller au contenu principal

V0.6.3 — Sécurisation d'ONVIF

Publiée le 16/10/2026.

Documentation fonctionnelle

Ce que change la version pour les collaborateurs

Pourquoi​

Depuis la 0.6.0, l’Administrateur règle une Caméra (Incrustations, Horloge) par ONVIF, mais ArgOS lui parlait en HTTP : qui écoutait le réseau des caméras capturait l’empreinte WS-Security du mot de passe (SHA-1, imposé par la norme, cassable hors ligne s’il est faible), lisait et modifiait les réglages au passage, et rien ne prouvait à ArgOS qu’il parlait à la bonne caméra. Avec l’authentification des Flux (0.6.2), c’était le dernier préalable à une installation sur de vraies caméras.

Ce qu'on peut faire maintenant​

  • Les Réglages d'une caméra qui propose HTTPS passent en HTTPS. ArgOS mémorise la clé de son certificat au premier contact et l'affiche (« Échange chiffré (HTTPS). Certificat de l'Appareil xxxx xxxx xxxx xxxx, mémorisé le … »), avec l'empreinte entière au survol. Rien n'est redemandé ensuite.

    Bandeau Échange chiffré avec l'empreinte du Certificat de l'Appareil

  • Si la caméra présente une autre clé, ArgOS s'arrête avant d'envoyer ses identifiants. Il montre le certificat mémorisé et le certificat présenté, ainsi que les causes possibles. L'Administrateur tranche : Faire confiance au nouveau certificat, puis Confirmer la confiance.

    Certificat changé : certificats mémorisé et présenté Confirmation avant de faire confiance au nouveau certificat

  • Une caméra déjà réglée en HTTPS qui ne répond plus qu'en HTTP n'est jamais réglée en clair. Oublier le certificat de cette caméra la fait repartir de zéro.

    HTTPS indisponible : ArgOS refuse de régler en clair

  • Une caméra sans HTTPS n'est réglée en clair qu'après l'accord de l'Administrateur (Régler quand même en clair), une fois par Caméra. Un bandeau le rappelle ensuite, et Retirer l'accord ONVIF en clair revient en arrière.

    ONVIF en clair non accepté Bandeau ONVIF en clair et réglage pris

  • Clé, port et accord sont gardés quand on ne change que le mot de passe ou le chemin de l'URL. Ils repartent de zéro quand on change l'hôte.

  • À l'ajout, un mot de passe de caméra de moins de 12 caractères est signalé sous les champs, sans bloquer l'ajout.

    Avertissement mot de passe court à l'ajout

  • Un refus de sécurité ne bloque que les Réglages de cette Caméra : le Live et l'état continuent.

    Live de la Caméra pendant un certificat changé

  • Chaque refus et chaque décision laisse une ligne dans les journaux de l'API (docker compose logs api | grep ONVIF), sans identifiant ni URL.

  • Une caméra qui ne parle qu’un TLS ancien (1.0 / 1.1) reste réglée en HTTPS, signalée « TLS ancien » dans ses Réglages : un TLS faible avec une clé mémorisée vaut mieux que du clair.

  • La Caméra simulée 2 répond désormais en ONVIF HTTPS sur 443 (HTTP gardé sur 8899) : on joue en dev le cas d’une caméra qui propose HTTPS ; la 4 reste en HTTP seul, pour l’ONVIF en clair.

  • Les # NOSONAR laissés en 0.6.0 ne renvoient plus à cette version : il ne reste que des justifications définitives (repli HTTP consenti, SHA-1 de WS-Security, TLS ancien).

Documentation technique

Spec versionnée : docs/specs/v0.6.3-securisation-d-onvif.md

Issue parente : #76

V0.6.3 — Sécurisation d'ONVIF

Problem Statement​

Depuis la 0.6.0, l'Administrateur règle une Caméra (Incrustations, Horloge) depuis ses Réglages, par ONVIF. Mais ArgOS parle ONVIF en HTTP à la caméra, sur les ports courants (80, 8899, 2000, 8000, 8080) :

  • le mot de passe part en empreinte WS-Security, en SHA-1 (imposé par la norme) : qui écoute le réseau des caméras capture l'empreinte et casse hors ligne un mot de passe faible, puis rejoue la requête ;
  • les réglages lus et envoyés circulent en clair et peuvent être modifiés au passage (heure incrustée fausse, Incrustation effacée) ;
  • rien ne prouve à ArgOS qu'il parle à la bonne caméra.

C'est, avec l'authentification des Flux (0.6.2), le dernier préalable à une installation sur de vraies caméras (docs/securite.md, dette « ONVIF en HTTP »). Les # NOSONAR laissés en 0.6.0 renvoient à cette version.

Solution​

Régler une Caméra ne livre plus son mot de passe ni ses réglages à qui écoute le réseau des caméras :

  • HTTPS d'abord : ArgOS cherche ONVIF en HTTPS sur 443 avant la recherche HTTP actuelle. Une enveloppe SOAP reçue en TLS prouve ONVIF chiffré. Une Caméra retenue en HTTP est re-sondée en HTTPS à chaque ouverture de ses Réglages ; dès qu'HTTPS répond, elle y passe pour de bon.
  • Certificat de l'Appareil : au premier contact HTTPS (première ouverture des Réglages), ArgOS mémorise l'empreinte SHA-256 de la clé publique du certificat présenté, sans regarder ni le nom ni l'expiration (certificats auto-signés, adressés par IP). Il refuse ensuite toute autre clé : rien d'authentifié ne part, les Réglages le signalent avec les deux empreintes, et l'Administrateur choisit « Faire confiance au nouveau certificat » (avec confirmation). Un renouvellement par la caméra avec la même clé ne demande rien.
  • Pas de rétrogradation : une Caméra déjà en HTTPS qui ne répond plus qu'en HTTP est refusée (« HTTPS indisponible »). « Oublier le certificat de cette caméra » fait repartir le contact suivant de zéro.
  • ONVIF en clair, consenti : une caméra qui ne propose pas HTTPS n'est réglée en HTTP qu'après l'accord de l'Administrateur, une fois par Caméra (« Régler quand même en clair »), mémorisé et révocable ; un bandeau le rappelle ensuite dans ses Réglages. Seule la recherche du port (GetSystemDateAndTime sans identifiants) part en HTTP sans accord.
  • TLS ancien : TLS 1.0 et 1.1 restent acceptés vers les caméras (un TLS faible avec une clé mémorisée vaut mieux que du clair), signalés « TLS ancien » dans les Réglages.
  • Mot de passe court : un mot de passe de caméra de moins de 12 caractères est signalé à l'ajout (non bloquant) et rappelé dans les Réglages d'une Caméra en ONVIF en clair, le seul cas où son empreinte SHA-1 circule en clair.
  • Les # NOSONAR ne promettent plus la 0.6.3 : les URL http:// en dur disparaissent, il ne reste que des justifications définitives (repli HTTP consenti, SHA-1 imposé par WS-Security).

User Stories​

Régler une Caméra​

  1. En tant qu'Administrateur, je veux que les Réglages d'une caméra qui propose HTTPS passent en HTTPS sans que j'aie rien à faire, pour que son mot de passe et ses réglages ne se lisent pas sur le réseau des caméras.
  2. En tant qu'Administrateur, je veux voir dans les Réglages que l'échange est chiffré, avec l'empreinte du Certificat de l'Appareil et sa date de mémorisation.
  3. En tant qu'Administrateur, je veux que rien d'authentifié ne parte vers une caméra dont la clé a changé, et voir pourquoi (ancienne et nouvelle empreinte, causes possibles : remise en usine, nouveau firmware, autre appareil à cette adresse).
  4. En tant qu'Administrateur, je veux faire confiance au nouveau certificat en un clic (avec confirmation) quand je sais pourquoi il a changé.
  5. En tant qu'Administrateur, je veux qu'une caméra qui répondait en HTTPS et ne répond plus qu'en HTTP soit refusée, et pouvoir oublier son certificat si je sais pourquoi.
  6. En tant qu'Administrateur, je veux qu'une caméra qui ne propose pas HTTPS ne soit réglée en clair qu'après mon accord, une fois, et pouvoir retirer cet accord.
  7. En tant qu'Administrateur, je veux voir qu'une Caméra est en ONVIF en clair, ou en TLS ancien, chaque fois que j'ouvre ses Réglages.
  8. En tant qu'Administrateur, je veux que le changement d'IP d'une Caméra retrouvée par sa MAC, ou le changement de son mot de passe, ne me redemande rien.
  9. En tant qu'Administrateur, je veux que le Live, l'état et le reste de l'Administration ne soient jamais bloqués par un certificat changé : seuls les Réglages de cette Caméra le sont.

Ajouter une Caméra​

  1. En tant qu'Administrateur, je veux être averti, sans être bloqué, quand le mot de passe de la caméra que j'ajoute a moins de 12 caractères, et savoir pourquoi.

Exploitation et documentation​

  1. En tant qu'Administrateur, je veux qu'un certificat refusé laisse une ligne dans les journaux de l'API (Caméra, les deux empreintes, jamais d'identifiant).
  2. En tant que lecteur de docs/securite.md et du schéma réseau, je veux savoir ce qui est chiffré vers les caméras, ce qui reste en clair (RTSP, ONVIF en clair consenti) et pourquoi.
  3. En tant que développeur, je veux tester HTTPS, le certificat changé et le repli consenti contre des Caméras simulées, sans matériel.

Implementation Decisions​

  • Glossaire (docs/glossaire.md) : ajout de Certificat de l'Appareil (« Certificat que l'Appareil présente quand le Site le règle en ONVIF chiffré ; le Site mémorise sa clé au premier contact et refuse ensuite toute autre. » À éviter : empreinte, pin, certificat de la caméra) et ONVIF en clair (« Réglages d'une Caméra dont l'Appareil ne propose pas ONVIF chiffré, envoyés sans chiffrement après accord de l'Administrateur. » À éviter : mode HTTP, mode non sécurisé).
  • ADR 0007 (docs/adr/0007-onvif-en-https-par-cle-memorisee.md) : ONVIF en HTTPS par clé mémorisée au premier contact (TOFU) plutôt que validation par une autorité (les caméras signent elles-mêmes) ou acceptation de tout certificat ; empreinte de la clé publique (SPKI) plutôt que du certificat ; repli HTTP seulement consenti, jamais après un contact HTTPS ; TLS 1.0+ accepté vers les caméras.
  • Client ONVIF (api/argos_api/onvif.py) :
    • recherche du port : sonde HTTPS 443 (TLS sans vérification d'autorité, la clé est comparée ensuite), puis la recherche HTTP actuelle ; le résultat porte le schéma, le port et, en HTTPS, l'empreinte SPKI vue et la version TLS ;
    • toutes les adresses de service (média…) sont reconstruites avec le schéma, l'hôte et le port réellement utilisés, seul le chemin du XAddr est gardé (une caméra jointe en HTTPS annonce souvent http://…) ; ce choix est commenté dans le code et écrit dans la doc réseau ;
    • l'empreinte de la clé est vérifiée sur chaque connexion TLS de l'échange (pas seulement la sonde) ;
    • TLS 1.0 minimum pour ce seul client ;
    • nouveaux codes d'ErreurOnvif : certificat changé (avec l'empreinte vue), HTTPS indisponible, ONVIF en clair non accepté.
  • Données (migration Alembic) : sur chaque Caméra, à côté de port_onvif, le schéma retenu, l'empreinte SPKI et sa date de mémorisation, l'accord « ONVIF en clair ». Après la mise à jour, une Caméra déjà réglée en HTTP repasse par la sonde HTTPS puis, si elle ne propose pas HTTPS, par l'accord.
  • Remise à zéro : port, schéma, empreinte et accord suivent l'hôte de l'URL RTSP. Gardés si l'Administrateur ne change que le mot de passe ou le chemin, gardés au changement d'IP par la MAC (_deplacer) ; remis à zéro quand l'Administrateur change l'hôte à la main. (Le port était remis à zéro à toute modification de l'URL depuis la 0.6.0.)
  • API : la lecture des Réglages renvoie aussi l'état de sécurité de l'échange (chiffré ou ONVIF en clair, empreinte et date, TLS ancien, mot de passe court) ; les trois refus portent de quoi les afficher ; trois actions par Caméra : faire confiance à l'empreinte vue (l'empreinte est renvoyée par l'UI et doit être celle que la caméra présente encore), oublier le certificat, accorder / retirer l'accord ONVIF en clair. Toutes exigent la session.
  • UI (web/src/pages/ReglagesCamera.tsx, AjoutCandidat.tsx) : bandeau d'état (chiffré, ONVIF en clair, TLS ancien) avec l'empreinte ; écrans de refus avec leurs boutons et confirmation ; avertissement « mot de passe court » à côté des identifiants à l'ajout et, en ONVIF en clair, dans les Réglages.
  • Journaux : une ligne par refus (certificat changé, HTTPS indisponible) et par décision de l'Administrateur (confiance, oubli, accord, retrait) : id de Caméra, empreintes ; jamais d'identifiant ni d'URL complète.
  • Sonar : plus d'URL http:// en dur (le schéma vient du contact retenu) ; # NOSONAR définitifs sur la seule ligne du repli HTTP (« HTTP seulement après accord de l'Administrateur, caméra sans HTTPS ») et sur le SHA-1 de la simulation (« SHA-1 imposé par WS-Security »). Plus aucun commentaire ne renvoie à la 0.6.3.
  • Simulation (simulation/onvif/, compose.simulation.yaml) : la Caméra simulée 2 sert ONVIF en HTTPS sur 443 (certificat auto-signé gardé dans un volume de dev) et garde HTTP sur 8899, comme beaucoup de vraies caméras ; ArgOS doit choisir HTTPS. La Caméra simulée 4 reste HTTP seulement, sans identifiants. Les Caméras simulées restent le banc de test de /t.
  • Docs : docs/securite.md (section ONVIF, dette retirée ou réécrite, contrainte « pas de vraies caméras » levée côté ONVIF), docs/features/reseau/schema-flux.md (flèche et ligne ONVIF, « Ce qui reste en clair », adresses de service reconstruites), docs/cameras/parametrer-une-camera.md (chiffré, certificat changé, ONVIF en clair), docs/cameras/ajouter-une-camera.md (mot de passe court), simulation/onvif/README.md. Les specs et ADR antérieurs ne sont pas modifiés.

Testing Decisions​

  • Un bon test vérifie un comportement observable depuis l'API, le navigateur ou le réseau de la stack : réponse, écran, ce que la caméra simulée a reçu. Jamais la configuration TLS en elle-même.
  • simulation/onvif/tests/ : la simulée sert la même interface en HTTPS et en HTTP ; son certificat est stable d'un démarrage à l'autre (volume).
  • tests/api/ (stack, prior art : tests/api/test_onvif_simule.py, tests/stack_compose.py) :
    • simulée 2 : Réglages lus en HTTPS, empreinte mémorisée au premier contact, puis réutilisée ; aucune requête authentifiée reçue en HTTP sur 8899 ;
    • clé changée (instance de test lancée avec une autre clé à la même adresse) : refus, rien d'authentifié reçu, empreintes renvoyées ; « faire confiance » puis lecture OK ; « faire confiance » avec une empreinte qui n'est plus celle présentée → refus ;
    • HTTPS indisponible sur une Caméra déjà en HTTPS (instance de test HTTP seulement) : refus, rien reçu en HTTP hors sonde ; « oublier le certificat » puis le parcours repart de zéro ;
    • simulée 4 (HTTP seulement) : refus « ONVIF en clair non accepté » sans requête autre que la sonde ; accord → lecture et modification OK, bandeau ; retrait → refus à nouveau ;
    • ONVIF en clair avec identifiants (instance de test HTTP avec identifiants) : mot de passe court signalé dans les Réglages ;
    • remise à zéro : changer le mot de passe ou le chemin garde empreinte et accord ; changer l'hôte les efface ; changement d'IP par la MAC les garde (prior art : tests/api/test_suivi_adresse.py).
  • tests/web/ (prior art : test_ajout_camera.py, tests des Réglages de la 0.6.0) : bandeau chiffré avec empreinte ; écran certificat changé et confirmation ; écran d'accord ONVIF en clair ; avertissement mot de passe court à l'ajout.
  • Tests humains : la vraie caméra du Site (HTTPS à vérifier : ArgOS le dira à l'ouverture des Réglages) — selon le cas, clé mémorisée seule, ou accord ONVIF en clair ; Caméras simulées 2 et 4 dans l'UI ; avertissement mot de passe court à l'ajout.

Out of Scope​

  • Isolement du réseau des caméras (VLAN, sans internet), dans la procédure d'installation (0.7.2).
  • Identifiants ONVIF distincts de ceux du Flux (Plus tard).
  • RTSP vers les caméras (Flux, sonde, Détection, essai), qui reste en clair ; RTSPS.
  • Passerelle chiffrante devant une caméra sans HTTPS (à ajouter en Plus tard).
  • Sortie des Caméras simulées de la stack de dev courante (à ajouter en Plus tard).
  • Recherche ONVIF par WS-Discovery ; réglages image et vidéo (0.6.4).

Changements apportés aux versions antérieures​

VersionÉlémentAvantAprèsÀ annoter
0.6.0Échange ONVIF avec la caméraen HTTP sur les ports courants, sans conditionHTTPS sur 443 d'abord, clé du Certificat de l'Appareil mémorisée et vérifiée ; HTTP seulement après accord de l'Administrateur (ONVIF en clair)v0.6.0, #52, #54
0.6.0Port ONVIF retenuremis à zéro à toute modification de l'URL RTSPremis à zéro seulement quand l'hôte changev0.6.0, #52, #54
0.6.0Caméra simulée 2ONVIF en HTTP sur 8899ONVIF en HTTPS sur 443, HTTP sur 8899 gardév0.6.0, #53

Further Notes​

  • Contexte : feuille de route de dev (section 0.6.3), docs/securite.md (dette ONVIF), spec et doc de la 0.6.0, ADR 0003 (MAC), ADR 0005 (HTTPS du Site, côté postes).
  • La vraie caméra du développeur semble proposer HTTPS, sans certitude : les tests humains le constateront.