Skip to content

Commit 008671a

Browse files
authored
Merge pull request #916 from Mathide-Team/feat/906-api-bpf-library
feat(#906): bibliothèque de filtres BPF dans l'API
2 parents d6f8bd5 + c70e7a3 commit 008671a

9 files changed

Lines changed: 535 additions & 4 deletions

File tree

‎docs/api-rest.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Réglages par variables d'environnement, lues au démarrage :
2424
| `NETCROSS_API_WORKERS` | `2` | Analyses simultanées en tâche de fond. |
2525
| `NETCROSS_DB_PATH` | absent | Base SQLite : analyses conservées et rechargées au redémarrage. Absent : tout reste en mémoire. |
2626
| `NETCROSS_HISTORY_DB` | absent | Historique des runs (format `--history-db`) : `history=true` sur `/comparisons` y enregistre la comparaison, sur `/captures` et `/captures/multi` l'analyse (#890), `GET /history` le consulte. Absent : enregistrement refusé (400), consultation 503. Le client ne choisit jamais le chemin. |
27+
| `NETCROSS_API_BPF_FILTERS` | `~/.netcross/bpf_filters.json` | Fichier de la bibliothèque de filtres BPF (`/bpf-filters`, issue #906), même format que la GUI et `--bpf-library`. Le client ne choisit jamais le chemin. |
2728
| `NETCROSS_CVE_DB` | absent | Base CVE complète du rapport de sécurité (équivalent de `--cve-db`). Absent : base minimale embarquée, comme la CLI. Un chemin inexistant fait échouer l'analyse (la base n'est jamais créée vide). |
2829
| `NETCROSS_API_MAX_BATCHES` | 20 | Lots conservés en mémoire avec leurs rapports (issue #872) ; au-delà, les plus anciens lots terminés sont supprimés. |
2930
| `NETCROSS_PLUGIN_PATH` | absent | Fichiers plugins locaux, séparés par `:` (équivalent de `--plugin-path`, issue #867). Fixés par l'administrateur : le client ne fait que nommer un plugin dans le champ `plugins`. Voir [plugins](plugins.md#api-rest-issue-867). |
@@ -80,6 +81,9 @@ La spécification OpenAPI est disponible sur :
8081
| `POST` | `/tools/export` | Sous-ensemble filtré (`file`, `bpf`, `time_start`, `time_end`, `endpoints`, `format`) : `--export-pcap` (issue #886) |
8182
| `POST` | `/tools/adjust-time` | Recalage (`file`, puis `time_offset`, `normalize` ou `align_to`, `format`) : `--adjust-time-output` (issue #887) |
8283
| `POST` | `/tools/replay` | Rejeu (`file`, `interface`, `speed`, `loop`) : `--replay`. ÉMET du trafic réel ; refusé (403) sauf si `interface` figure dans `NETCROSS_REPLAY_INTERFACES` (liste séparée par des virgules, vide par défaut) ; 503 si tcpreplay absent (issue #871) |
84+
| `GET` | `/bpf-filters` | Bibliothèque de filtres BPF (`--bpf-library`, issue #906) : catalogue prédéfini (`predefined: true`) puis filtres enregistrés |
85+
| `PUT` | `/bpf-filters/{nom}` | Crée ou remplace un filtre (JSON `expression`, `description`) ; 409 pour un nom du catalogue, 422 si l'expression est vide |
86+
| `DELETE` | `/bpf-filters/{nom}` | Supprime un filtre enregistré ; 404 s'il est inconnu, 409 pour un nom du catalogue |
8387
| `GET` | `/health` | Health check |
8488

8589
## Exemples curl

‎docs/bpf-filters.md‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,30 @@ Les erreurs (champ vide, nom déjà pris par le catalogue, fichier illisible,
2323
erreur d'écriture) s'affichent dans la fenêtre de sauvegarde ; rien n'est
2424
écrit dans ces cas.
2525

26+
## Par l'API
27+
28+
Issue #906. La bibliothèque est aussi gérée par l'API REST, sur le même
29+
fichier (celui du serveur : `$NETCROSS_API_BPF_FILTERS` s'il est défini,
30+
sinon `~/.netcross/bpf_filters.json` du compte qui exécute l'API) :
31+
32+
```bash
33+
# catalogue prédéfini puis filtres enregistrés ("predefined": true/false)
34+
curl -H "X-API-Key: $NETCROSS_API_TOKEN" http://localhost:8000/bpf-filters
35+
36+
# enregistrer (ou remplacer) un filtre
37+
curl -X PUT -H "X-API-Key: $NETCROSS_API_TOKEN" -H "Content-Type: application/json" \
38+
-d '{"expression": "host 10.0.0.1 and tcp", "description": "Serveur web"}' \
39+
"http://localhost:8000/bpf-filters/Serveur%20web"
40+
41+
# supprimer
42+
curl -X DELETE -H "X-API-Key: $NETCROSS_API_TOKEN" "http://localhost:8000/bpf-filters/Serveur%20web"
43+
```
44+
45+
Mêmes règles qu'en GUI : un nom du catalogue est refusé (409), une
46+
expression vide aussi (422), un fichier illisible n'est jamais écrasé (500,
47+
fichier intact). Un filtre enregistré par l'API est aussitôt utilisable par
48+
`--bpf-library NOM` et apparaît dans le menu « Filtres… » de la GUI.
49+
2650
## Catalogue prédéfini
2751

2852
| Nom | Expression BPF |

‎docs/class-diagram.md‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
> Il remplace l'ancienne section 3 de `docs/features-backlog.md`, tenue à la main, qui avait dérivé
1212
> (voir `docs/sessions/session-36.md`, issue #140).
1313
14-
194 modules · 282 classes · 671 fonctions publiques de module.
14+
195 modules · 283 classes · 678 fonctions publiques de module.
1515

1616
Conventions : `+` public, `-` privé (préfixe `_`) ; `int?` = `int | None` ; `list~str~` = `list[str]` ;
1717
`<<module>>` regroupe les fonctions publiques d'un module ; `A --> B : champ` = `A` a un champ annoté
@@ -42,7 +42,7 @@ flowchart TD
4242
netcross_gtk4 -->|"6 imports"| pcap_parser
4343
netcross_api -->|"19 imports"| netcross_report
4444
netcross_api -->|"5 imports"| netcross_ai
45-
netcross_api -->|"42 imports"| netcross_core
45+
netcross_api -->|"45 imports"| netcross_core
4646
netcross_api -->|"3 imports"| pcap_parser
4747
netcross_report -->|"40 imports"| netcross_core
4848
netcross_ai -->|"10 imports"| netcross_core
@@ -656,6 +656,7 @@ classDiagram
656656
+load_bpf_filters(path) list~BPFFilter~
657657
+available_bpf_filters(path) list~BPFFilter~
658658
+upsert_bpf_filter(new, path) list~BPFFilter~
659+
+delete_bpf_filter(name, path) list~BPFFilter~
659660
}
660661
661662
%% ===== netcross_core.capture_tools =====
@@ -3874,6 +3875,7 @@ classDiagram
38743875
| `netcross_api` | service REST FastAPI pour exposer les analyses Netcross (issue #209). |
38753876
| `netcross_api.app` | application FastAPI pour exposer les analyses Netcross (issues #209, #354, #356). |
38763877
| `netcross_api.batches` | lots de captures de l'API (issue #872). |
3878+
| `netcross_api.bpf_routes` | bibliothèque de filtres BPF enregistrés (issue #906), équivalent API de ``--bpf-library NOM`` et des boutons « Filtres… » / « Enregistrer » de la GUI. |
38773879
| `netcross_api.history_routes` | historique SQLite des runs (issue #874). |
38783880
| `netcross_api.lua_doc_routes` | documentation hors ligne de l'API Lua Wireshark (issue #873), équivalent de ``netcross-lua-doc --json``. |
38793881
| `netcross_api.models` | modèles Pydantic pour les requêtes/réponses API (issue #209). |
@@ -3980,6 +3982,22 @@ classDiagram
39803982
+new_workdir() tuple~str, str~
39813983
}
39823984
3985+
%% ===== netcross_api.bpf_routes =====
3986+
class BPFFilterBody {
3987+
<<BaseModel>>
3988+
+str expression
3989+
+str description
3990+
}
3991+
class mod_netcross_api_bpf_routes["netcross_api.bpf_routes"] {
3992+
<<module>>
3993+
+filters_path() Path?
3994+
+list_bpf_filters() dict~str, Any~
3995+
+put_bpf_filter(nom, body) dict~str, Any~
3996+
+delete_bpf_filter(nom) dict~str, Any~
3997+
+resolve_bpf_library(nom) str
3998+
+register(app, verify) None
3999+
}
4000+
39834001
%% ===== netcross_api.history_routes =====
39844002
class mod_netcross_api_history_routes["netcross_api.history_routes"] {
39854003
<<module>>

‎docs/openapi.yaml‎

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,106 @@ paths:
21312131
application/json:
21322132
schema:
21332133
$ref: '#/components/schemas/HTTPValidationError'
2134+
/bpf-filters:
2135+
get:
2136+
tags:
2137+
- bpf-filters
2138+
summary: List Bpf Filters
2139+
description: Catalogue prédéfini puis filtres enregistrés (la liste de la GUI).
2140+
operationId: list_bpf_filters_bpf_filters_get
2141+
responses:
2142+
'200':
2143+
description: Successful Response
2144+
content:
2145+
application/json:
2146+
schema:
2147+
additionalProperties: true
2148+
type: object
2149+
title: Response List Bpf Filters Bpf Filters Get
2150+
'500':
2151+
description: Fichier de filtres illisible ou non inscriptible (il n'est
2152+
pas modifié)
2153+
security:
2154+
- APIKeyHeader: []
2155+
/bpf-filters/{nom}:
2156+
put:
2157+
tags:
2158+
- bpf-filters
2159+
summary: Put Bpf Filter
2160+
description: Crée ou remplace le filtre ``nom`` ; renvoie la liste à jour.
2161+
operationId: put_bpf_filter_bpf_filters__nom__put
2162+
security:
2163+
- APIKeyHeader: []
2164+
parameters:
2165+
- name: nom
2166+
in: path
2167+
required: true
2168+
schema:
2169+
type: string
2170+
title: Nom
2171+
requestBody:
2172+
required: true
2173+
content:
2174+
application/json:
2175+
schema:
2176+
$ref: '#/components/schemas/BPFFilterBody'
2177+
responses:
2178+
'200':
2179+
description: Successful Response
2180+
content:
2181+
application/json:
2182+
schema:
2183+
type: object
2184+
additionalProperties: true
2185+
title: Response Put Bpf Filter Bpf Filters Nom Put
2186+
'409':
2187+
description: Nom réservé au catalogue prédéfini
2188+
'500':
2189+
description: Fichier de filtres illisible ou non inscriptible (il n'est
2190+
pas modifié)
2191+
'422':
2192+
description: Validation Error
2193+
content:
2194+
application/json:
2195+
schema:
2196+
$ref: '#/components/schemas/HTTPValidationError'
2197+
delete:
2198+
tags:
2199+
- bpf-filters
2200+
summary: Delete Bpf Filter
2201+
description: Supprime le filtre enregistré ``nom`` ; renvoie la liste à jour.
2202+
operationId: delete_bpf_filter_bpf_filters__nom__delete
2203+
security:
2204+
- APIKeyHeader: []
2205+
parameters:
2206+
- name: nom
2207+
in: path
2208+
required: true
2209+
schema:
2210+
type: string
2211+
title: Nom
2212+
responses:
2213+
'200':
2214+
description: Successful Response
2215+
content:
2216+
application/json:
2217+
schema:
2218+
type: object
2219+
additionalProperties: true
2220+
title: Response Delete Bpf Filter Bpf Filters Nom Delete
2221+
'404':
2222+
description: Filtre enregistré introuvable
2223+
'409':
2224+
description: Nom réservé au catalogue prédéfini
2225+
'500':
2226+
description: Fichier de filtres illisible ou non inscriptible (il n'est
2227+
pas modifié)
2228+
'422':
2229+
description: Validation Error
2230+
content:
2231+
application/json:
2232+
schema:
2233+
$ref: '#/components/schemas/HTTPValidationError'
21342234
components:
21352235
schemas:
21362236
AnalysisAccepted:
@@ -2221,6 +2321,22 @@ components:
22212321
- analysis_id
22222322
title: AnalysisSummary
22232323
description: Résumé d'une analyse (retourné par POST /captures).
2324+
BPFFilterBody:
2325+
properties:
2326+
expression:
2327+
type: string
2328+
title: Expression
2329+
description: Expression BPF (libpcap), transmise telle quelle à tshark (-f)
2330+
description:
2331+
type: string
2332+
title: Description
2333+
description: Description libre, facultative
2334+
default: ''
2335+
type: object
2336+
required:
2337+
- expression
2338+
title: BPFFilterBody
2339+
description: Corps de ``PUT /bpf-filters/{nom}``.
22242340
Body_adjust_time_route_tools_adjust_time_post:
22252341
properties:
22262342
file:

‎docs/parite-surfaces.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ ici fait donc échouer la CI.
1616
|---|---|---|
1717
| CLI | `cross_capture_analyzer_cli.py` (110 options), `cross_capture_diff_cli.py` (27), `cross_capture_batch_cli.py` (11), `cross_history_cli.py`, `netcross_lua_doc_cli.py`, `netcross_ai_models_cli.py` | Surface de référence : tout y est |
1818
| GUI | `netcross_gtk4` : 3 pages, 43 cases à cocher, 31 réglages numériques | Analyse interactive et exploration visuelle |
19-
| API | 41 routes FastAPI | Analyse avec sécurité ; options NAT, TLS, QUIC, anonymisation ; exports texte, PDF, CSV (issue #670) ; options avancées (#672) ; comparaison baseline/courant (#669) ; recherche forensic, extraction, comparaison de postes, NetFlow (#675) |
19+
| API | 44 routes FastAPI | Analyse avec sécurité ; options NAT, TLS, QUIC, anonymisation ; exports texte, PDF, CSV (issue #670) ; options avancées (#672) ; comparaison baseline/courant (#669) ; recherche forensic, extraction, comparaison de postes, NetFlow (#675) |
2020

2121

2222
Légende : **oui** = disponible ; **non** = absent ; **auto** = toujours
@@ -122,7 +122,7 @@ est conservée telle quelle pour les clients existants.
122122
| Durée maximale | oui | `--live-duration` | non |
123123
| Arrêt manuel puis analyse | oui (« Arreter et analyser ») | Ctrl+C | non |
124124
| Rotation de capture (ring buffer) | oui (« Rotation de capture », nombre de fichiers, durée par fichier) : même enregistreur que la CLI, répertoires et fichiers conservés indiqués dans le journal | `--ring-buffer N:SECONDES` : enregistre la capture brute de chaque point en pcapng tournants (ring buffer natif de tshark), incompatible avec `pipe://` (issue #676) | non |
125-
| Bibliothèque de filtres BPF enregistrés | oui (enregistrer, choisir) | `--bpf-library NOM` (lit `~/.netcross/bpf_filters.json`, issue #676) | non |
125+
| Bibliothèque de filtres BPF enregistrés | oui (enregistrer, choisir) | `--bpf-library NOM` (lit `~/.netcross/bpf_filters.json`, issue #676) | `GET /bpf-filters`, `PUT /bpf-filters/{nom}`, `DELETE /bpf-filters/{nom}` (même fichier, `$NETCROSS_API_BPF_FILTERS` côté serveur, issue #906) ; champ `bpf_library` par point avec #902 |
126126
| Rapport HTML rafraîchi en continu | oui (« Rapport HTML en continu », répertoire, intervalle, « Servir la page » et port ; issue #676) | `--live-report`, `--live-report-interval`, `--live-report-serve` | non |
127127
| Notifications (webhook, Slack, e-mail) | oui (« Notifier si », webhook, Slack, courriel, « Detail complet » ; avec « Rapport de securite », issue #676) | `--notify-on`, `--notify-webhook`, `--notify-slack`, `--notify-email`, `--notify-detail`, `--notify-silence`, `--notify-state` | `notify_on`, `notify_webhook`, `notify_slack`, `notify_email`, `notify_detail` (trace dans `security_report.notifications` de `/report`, URL jamais conservées ; issue #875) |
128128

@@ -296,6 +296,9 @@ l'option CLI de même nom) : `nat_tolerant`, `nat_window_ms`, `tls`,
296296
| `GET /lua-doc/search` | Recherche dans la documentation Lua, `q`, `limit`, `full` (issue #873) |
297297
| `GET /comparisons/{comparison_id}/redact-map` | Table d'anonymisation commune baseline/courant (issue #876) |
298298
| `POST /tools/replay` | Rejeu sur une interface autorisée (issue #871) |
299+
| `GET /bpf-filters` | Bibliothèque de filtres BPF : catalogue puis filtres enregistrés (issue #906) |
300+
| `PUT /bpf-filters/{nom}` | Crée ou remplace un filtre BPF enregistré, `expression`, `description` (issue #906) |
301+
| `DELETE /bpf-filters/{nom}` | Supprime un filtre BPF enregistré (issue #906) |
299302

300303
Réglages par variables d'environnement (`NETCROSS_API_TOKEN` pour
301304
l'en-tête `X-API-Key`, `NETCROSS_MAX_UPLOAD_MB`, `NETCROSS_API_MAX_FILES`,

‎src/netcross_api/app.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2828,3 +2828,8 @@ async def get_batch_report(batch_id: str, name: str, _auth: None = Depends(_veri
28282828
from netcross_api import lua_doc_routes as _lua_doc_routes # noqa: E402
28292829

28302830
_lua_doc_routes.register(app, _verify_api_key)
2831+
2832+
# Issue #906 : bibliothèque de filtres BPF (fichier fixé par NETCROSS_API_BPF_FILTERS)
2833+
from netcross_api import bpf_routes as _bpf_routes # noqa: E402
2834+
2835+
_bpf_routes.register(app, _verify_api_key)

0 commit comments

Comments
 (0)