feat(agent): enrichissement ONVIF authentifié côté agent — pool chiffré via config #49

Merged
nonobis merged 2 commits from feat/camera-discovery-agent into main 2026-08-11 16:15:41 +02:00
Owner

What

L'enrichissement ONVIF authentifié est déplacé côté agent. Le pool de credentials du site (login/mdp) est exposé à l'agent via GET /api/settings/agent/{id} sous forme d'enveloppe AES-256-GCM (AgentCredentialEnvelope, clé dérivée du SHA-256 de l'API key) — déchiffrable uniquement côté agent. NetworkCameraScanner tente GetDeviceInformation avec chaque couple du pool (PasswordDigest puis PasswordText) et remonte des devices déjà identifiés (fabricant/modèle ONVIF + CredentialLabel). Le central persiste et marque le credential utilisé (LastUsedAt) — plus aucun appel réseau ONVIF côté central.

Why

Le central n'est généralement pas sur le réseau des caméras : les appels ONVIF authentifiés qu'il faisait après réception des devices bruts échouaient. L'agent, lui, est sur le sous-réseau des caméras — c'est lui qui doit porter l'auth. Enrichissement et identification se font au moment du scan, avant la remontée.

How

  • AgentCredentialEnvelope (Application/Security) : AES-256-GCM, clé = SHA-256 de l'API key ; central chiffre (via l'ApiKeyHash stocké), agent déchiffre (via sa clé en clair).
  • GetEffectiveAgentConfigQuery : ajoute discovery.credentials (pool chiffré) au dict de config.
  • SettingsController.GetEffectiveConfig : accepte l'API key agent (vérification par site) en plus du JWT admin — corrige au passage un 403 latent sur cet endpoint.
  • NetworkCameraScanner : probe ONVIF authentifié avec le pool (anonyme d'abord, puis chaque couple).
  • AgentCredentialStore (mémoire, jamais sur disque) : reçoit le pool déchiffré par ConfigReceiverService, lu par AgentDiscoveryService.
  • CameraDiscoveryService : suppression de l'enrichissement réseau ; persistance + MarkUsed via CredentialLabel ; vendor déduit du fabricant ONVIF remonté.
  • SitesController : broadcast ConfigReload après add/delete credential pour que les agents re-fetch leur pool.
  • Multi-agents : inchangé — upsert par (site, IP) et anti-doublon IP/MAC à la confirmation évitent les caméras en double même si un agent est éteint.

Testing

  • dotnet build Heimdall.slnx : 0 erreur / 0 warning.
  • Application 346 verts, Agent 108 verts, Infrastructure 143 verts (hors Testcontainers).
  • Web.Tests 213 verts — nouveaux bUnit : DiscoveriesPage (5) + SiteDetail credentials (4).

Breaking Changes

Aucun changement de schéma (pas de migration). Comportement API : GET /api/settings/agent/{id} accepte désormais l'API key agent (accès élargi au cas d'usage prévu).

Related to #48

## What L'enrichissement ONVIF authentifié est déplacé côté **agent**. Le pool de credentials du site (login/mdp) est exposé à l'agent via `GET /api/settings/agent/{id}` sous forme d'enveloppe AES-256-GCM (`AgentCredentialEnvelope`, clé dérivée du SHA-256 de l'API key) — déchiffrable uniquement côté agent. `NetworkCameraScanner` tente `GetDeviceInformation` avec chaque couple du pool (PasswordDigest puis PasswordText) et remonte des devices **déjà identifiés** (fabricant/modèle ONVIF + `CredentialLabel`). Le central persiste et marque le credential utilisé (`LastUsedAt`) — plus aucun appel réseau ONVIF côté central. ## Why Le central n'est généralement **pas** sur le réseau des caméras : les appels ONVIF authentifiés qu'il faisait après réception des devices bruts échouaient. L'agent, lui, est sur le sous-réseau des caméras — c'est lui qui doit porter l'auth. Enrichissement et identification se font au moment du scan, avant la remontée. ## How - `AgentCredentialEnvelope` (Application/Security) : AES-256-GCM, clé = SHA-256 de l'API key ; central chiffre (via l'`ApiKeyHash` stocké), agent déchiffre (via sa clé en clair). - `GetEffectiveAgentConfigQuery` : ajoute `discovery.credentials` (pool chiffré) au dict de config. - `SettingsController.GetEffectiveConfig` : accepte l'API key agent (vérification par site) en plus du JWT admin — corrige au passage un 403 latent sur cet endpoint. - `NetworkCameraScanner` : probe ONVIF authentifié avec le pool (anonyme d'abord, puis chaque couple). - `AgentCredentialStore` (mémoire, jamais sur disque) : reçoit le pool déchiffré par `ConfigReceiverService`, lu par `AgentDiscoveryService`. - `CameraDiscoveryService` : suppression de l'enrichissement réseau ; persistance + `MarkUsed` via `CredentialLabel` ; vendor déduit du fabricant ONVIF remonté. - `SitesController` : broadcast `ConfigReload` après add/delete credential pour que les agents re-fetch leur pool. - Multi-agents : inchangé — upsert par (site, IP) et anti-doublon IP/MAC à la confirmation évitent les caméras en double même si un agent est éteint. ## Testing - `dotnet build Heimdall.slnx` : 0 erreur / 0 warning. - Application 346 verts, Agent 108 verts, Infrastructure 143 verts (hors Testcontainers). - Web.Tests 213 verts — nouveaux bUnit : DiscoveriesPage (5) + SiteDetail credentials (4). ## Breaking Changes Aucun changement de schéma (pas de migration). Comportement API : `GET /api/settings/agent/{id}` accepte désormais l'API key agent (accès élargi au cas d'usage prévu). Related to #48
feat(agent): enrichissement ONVIF authentifié côté agent — pool chiffré via config
All checks were successful
CI / ci (pull_request) Successful in 3m59s
9c7295d409
Le central ne fait plus d'appels réseau ONVIF pour les découvertes
soumises par les agents : hors du réseau caméras, ces appels échouent.
Le pool de credentials du site est désormais exposé à l'agent via
GET /api/settings/agent/{id} sous forme d'enveloppe AES-256-GCM (clé
dérivée du hash SHA-256 de l'API key de l'agent), déchiffrable
uniquement côté agent.

NetworkCameraScanner tente GetDeviceInformation avec chaque couple du
pool (PasswordDigest puis PasswordText) et remonte des devices déjà
identifiés (fabricant/modèle ONVIF + label du credential utilisé).
Le central persiste et marque le credential utilisé (LastUsedAt).

SettingsController.GetEffectiveConfig accepte l'API key agent
(vérification par site) en plus du JWT admin ; SitesController
broadcast ConfigReload après add/delete credential.

Tests : Application 346, Agent 108, Infrastructure 143 (hors
Testcontainers), Web.Tests 213 — nouveaux bUnit DiscoveriesPage (5)
et SiteDetail credentials (4).

Fixes #48
nonobis deleted branch feat/camera-discovery-agent 2026-08-11 16:15:42 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nonobis/Heimdall!49
No description provided.