diff --git a/monitoring/security/wazuh/config/wazuh_manager/agent.conf b/monitoring/security/wazuh/config/wazuh_manager/agent.conf index 9e7bc5d2..616f99d4 100644 --- a/monitoring/security/wazuh/config/wazuh_manager/agent.conf +++ b/monitoring/security/wazuh/config/wazuh_manager/agent.conf @@ -3,7 +3,7 @@ - + apache /var/log/nginx/access.log @@ -14,14 +14,6 @@ /var/log/nginx/error.log - - - - syslog - /var/lib/docker/containers/*/*-json.log - - - syslog @@ -35,4 +27,4 @@ - + diff --git a/monitoring/security/wazuh/config/wazuh_manager/decoders/api-decoder.xml b/monitoring/security/wazuh/config/wazuh_manager/decoders/api-decoder.xml deleted file mode 100644 index 32d7a8e1..00000000 --- a/monitoring/security/wazuh/config/wazuh_manager/decoders/api-decoder.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - backend - - - - - go-backend - [GIN] - \|\s+(\d{3})\s+\|\s+(\S+)\s+\|\s+([\d.]+)\s+\|\s+(\S+)\s+(\S+) - id,extra_data,srcip,protocol,url - - - - - go-backend - LOGIN_ADMIN|LOGIN_CLIENT - LOGIN_\S+ \S+ \S+ \S+: (\S+) - srcuser - - - - - LOGIN_ADMIN|LOGIN_CLIENT - LOGIN_\S+ \S+ \S+ \S+: (\S+) - srcuser - diff --git a/monitoring/security/wazuh/config/wazuh_manager/decoders/wireguard-decoder.xml b/monitoring/security/wazuh/config/wazuh_manager/decoders/wireguard-decoder.xml index e07ce144..fbe2336e 100644 --- a/monitoring/security/wazuh/config/wazuh_manager/decoders/wireguard-decoder.xml +++ b/monitoring/security/wazuh/config/wazuh_manager/decoders/wireguard-decoder.xml @@ -1,56 +1,45 @@ - + - - - kernel - wireguard: wg0: - - - - wireguard - Sending handshake initiation + kernel + wireguard: wg0: Sending handshake initiation wireguard: wg0: Sending handshake initiation to peer (\d+) \(([\d.]+):\d+\) id,srcip - - wireguard - Sending handshake response + kernel + wireguard: wg0: Sending handshake response wireguard: wg0: Sending handshake response to peer (\d+) \(([\d.]+):\d+\) id,srcip - - wireguard - Receiving handshake response + kernel + wireguard: wg0: Receiving handshake response wireguard: wg0: Receiving handshake response from peer (\d+) \(([\d.]+):\d+\) id,srcip - - wireguard - keepalive packet + kernel + wireguard: wg0: wireguard: wg0: \S+ keepalive packet \S+ peer (\d+) \(([\d.]+):\d+\) id,srcip - - wireguard - did not complete + kernel + wireguard: wg0: Handshake for peer wireguard: wg0: Handshake for peer (\d+)[^(]+\(([\d.]+):\d+\).+retrying \(try (\d+)\) id,srcip,extra_data - - wireguard - is now roaming + kernel + wireguard: wg0: Peer wireguard: wg0: Peer (\d+).+roaming to ([\d.]+):\d+ id,srcip diff --git a/monitoring/security/wazuh/config/wazuh_manager/rules/api-brute-force-rules.xml b/monitoring/security/wazuh/config/wazuh_manager/rules/api-brute-force-rules.xml deleted file mode 100644 index 25c5b2ca..00000000 --- a/monitoring/security/wazuh/config/wazuh_manager/rules/api-brute-force-rules.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - go-backend - Go Backend API: log entry - api_backend, - - - - - 100700 - [GIN] - API: Requete HTTP Gin loggee - api_backend,api_http, - - - - - 100701 - | 4\d\d | - API: Erreur client 4xx — $(srcip) - api_backend,api_http,api_error, - - - - - 100701 - | 5\d\d | - API: Erreur serveur 5xx — $(srcip) - api_backend,api_http,api_error, - - - - - 100700 - panic|PANIC|fatal|FATAL - API: Erreur critique Go backend (panic/fatal) - api_backend,api_error, - - - - - - - - - - go-backend-login-fail - LOGIN_ADMIN - API: Echec auth admin - api_auth_failure, - - - - - go-backend-login-fail - LOGIN_CLIENT - API: Echec auth client - api_auth_failure, - - - - - 100600 - - API: Brute-force login admin — 5 echecs/60s depuis $(srcip) - api_brute_force,authentication_failures, - - - - - 100601 - - API: Brute-force login client — 5 echecs/60s depuis $(srcip) - api_brute_force,authentication_failures, - - - - - api_auth_failure - - API: Scan auth — 20 echecs/120s depuis $(srcip) - api_brute_force,authentication_failures, - - - diff --git a/monitoring/security/wazuh/config/wazuh_manager/rules/wireguard-rules.xml b/monitoring/security/wazuh/config/wazuh_manager/rules/wireguard-rules.xml index 0114b9cc..2a922bff 100644 --- a/monitoring/security/wazuh/config/wazuh_manager/rules/wireguard-rules.xml +++ b/monitoring/security/wazuh/config/wazuh_manager/rules/wireguard-rules.xml @@ -1,69 +1,81 @@ - + - + - wireguard-keepalive + 5100 + wireguard: wg0: + keepalive packet WireGuard: keepalive peer $(srcip) wireguard,vpn_keepalive, - + - wireguard-handshake-init + 5100 + wireguard: wg0: Sending handshake initiation WireGuard: handshake initiation vers peer $(srcip) wireguard,vpn_handshake, - + - wireguard-handshake-resp-sent + 5100 + wireguard: wg0: Sending handshake response WireGuard: handshake reponse envoyee a peer $(srcip) wireguard,vpn_handshake, - + - wireguard-handshake-resp-recv - WireGuard: handshake complete avec peer $(srcip) + 5100 + wireguard: wg0: Receiving handshake response + WireGuard: handshake complet avec peer $(srcip) wireguard,vpn_handshake, - + - wireguard-timeout - WireGuard: handshake timeout peer $(srcip) (essai $(extra_data)) + 5100 + wireguard: wg0: Handshake for peer + did not complete + WireGuard: handshake timeout peer $(srcip) wireguard,vpn_warning, - + 100810 try 5|try 6|try 7|try 8|try 9 - WireGuard: peer $(srcip) deconnecte — handshake echoue 5 fois consecutives + WireGuard: peer $(srcip) deconnecte wireguard,vpn_disconnected, - + 100810 - retrying \(try 1\d\) - WireGuard: peer $(srcip) hors ligne depuis plus de 60 secondes + retrying .try 1\d. + WireGuard: peer $(srcip) hors ligne depuis plus de 60s wireguard,vpn_disconnected, - + - wireguard-roaming - WireGuard: peer $(id) a change d'IP (roaming) vers $(srcip) + 5100 + wireguard: wg0: Peer + is now roaming + WireGuard: peer $(id) roaming vers $(srcip) wireguard,vpn_roaming, - + - wireguard-handshake-resp-recv - WireGuard: peer $(srcip) handshake complet (reconnexion possible) + 5100 + wireguard: wg0: Receiving handshake response + WireGuard: peer $(srcip) reconnecte wireguard,vpn_reconnected, diff --git a/monitoring/security/wazuh/create-dashboard-go-api.py b/monitoring/security/wazuh/create-dashboard-go-api.py deleted file mode 100644 index e9e43b77..00000000 --- a/monitoring/security/wazuh/create-dashboard-go-api.py +++ /dev/null @@ -1,417 +0,0 @@ -#!/usr/bin/env python3 -""" -Crée le dashboard "API Go - Performance & Trafic" dans OpenSearch Dashboards (Wazuh). - -Usage: - docker cp create-dashboard-go-api.py wazuh_dashboard:/tmp/ - docker exec wazuh_dashboard python3 /tmp/create-dashboard-go-api.py - -Données utilisées : - - rule 100700 → toute ligne backend Go - - rule 100701 → requête HTTP Gin (tous codes) - - rule 100702 → erreur 4xx - - rule 100703 → erreur 5xx - - rule 100704 → panic / fatal - - fields: data.id (code HTTP), data.extra_data (temps réponse), - data.srcip (IP client), data.protocol (GET/POST...), - data.url (endpoint), agent.name (prod-mln / pre-prod-mln) -""" - -import json -import urllib.request -import urllib.error -import ssl -import base64 -import sys -import os - -# ── Configuration ────────────────────────────────────────────────────────────── -DASHBOARD_HOST = "https://localhost:5601" -DASHBOARD_USER = "kibanaserver" -DASHBOARD_PASS = os.environ.get("DASHBOARD_PASSWORD", "E9Jpr6586kQ3wYrCS2!") -INDEX_PATTERN = "wazuh-alerts-*" - -# ── Queries ──────────────────────────────────────────────────────────────────── -Q_ALL = "rule.id: 100700 OR rule.id: 100701 OR rule.id: 100702 OR rule.id: 100703 OR rule.id: 100704" -Q_HTTP = "rule.id: 100701 OR rule.id: 100702 OR rule.id: 100703" -Q_4XX = "rule.id: 100702" -Q_5XX = "rule.id: 100703" -Q_PANIC = "rule.id: 100704" - -# ── Client HTTP ──────────────────────────────────────────────────────────────── -ctx = ssl.create_default_context() -ctx.check_hostname = False -ctx.verify_mode = ssl.CERT_NONE - -_auth = base64.b64encode(f"{DASHBOARD_USER}:{DASHBOARD_PASS}".encode()).decode() -_headers = { - "Content-Type": "application/json", - "osd-xsrf": "true", - "Authorization": f"Basic {_auth}", -} - -def api(method, path, body=None): - data = json.dumps(body).encode() if body else None - req = urllib.request.Request(DASHBOARD_HOST + path, data=data, headers=_headers, method=method) - try: - with urllib.request.urlopen(req, context=ctx, timeout=15) as r: - return json.loads(r.read()) - except urllib.error.HTTPError as e: - return {"error": e.code, "msg": e.read().decode()[:300]} - -def search_src(query): - return json.dumps({ - "index": INDEX_PATTERN, - "filter": [], - "query": {"language": "kuery", "query": query}, - }) - -# ── Visualisations ───────────────────────────────────────────────────────────── -VISUALIZATIONS = [ - # ── 1. Métrique : total requêtes HTTP ───────────────────────────────────── - { - "id": "go-api-total-requests", - "title": "[API Go] Total Requetes HTTP", - "type": "metric", - "query": Q_HTTP, - "visState": { - "type": "metric", - "params": { - "metric": { - "percentageMode": False, "useRanges": False, - "colorSchema": "Blues", - "metricColorMode": "None", - "colorsRange": [{"from": 0, "to": 99999999}], - "labels": {"show": True}, - "invertColors": False, - "style": {"bgFill": "#000", "bgColor": False, "labelColor": False, - "subText": "requetes loggees", "fontSize": 60}, - } - }, - "aggs": [{"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}], - }, - }, - # ── 2. Métrique : erreurs 4xx ───────────────────────────────────────────── - { - "id": "go-api-4xx", - "title": "[API Go] Erreurs 4xx", - "type": "metric", - "query": Q_4XX, - "visState": { - "type": "metric", - "params": { - "metric": { - "percentageMode": False, "useRanges": False, - "colorSchema": "Yellow to Red", - "metricColorMode": "Labels", - "colorsRange": [{"from": 0, "to": 50}, {"from": 50, "to": 500}, {"from": 500, "to": 99999}], - "labels": {"show": True}, - "invertColors": False, - "style": {"bgFill": "#000", "bgColor": False, "labelColor": False, - "subText": "erreurs client 4xx", "fontSize": 60}, - } - }, - "aggs": [{"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}], - }, - }, - # ── 3. Métrique : erreurs 5xx ───────────────────────────────────────────── - { - "id": "go-api-5xx", - "title": "[API Go] Erreurs 5xx", - "type": "metric", - "query": Q_5XX, - "visState": { - "type": "metric", - "params": { - "metric": { - "percentageMode": False, "useRanges": False, - "colorSchema": "Green to Red", - "metricColorMode": "Labels", - "colorsRange": [{"from": 0, "to": 1}, {"from": 1, "to": 20}, {"from": 20, "to": 99999}], - "labels": {"show": True}, - "invertColors": False, - "style": {"bgFill": "#000", "bgColor": False, "labelColor": False, - "subText": "erreurs serveur 5xx", "fontSize": 60}, - } - }, - "aggs": [{"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}], - }, - }, - # ── 4. Timeline : requêtes par heure (prod vs pre-prod) ─────────────────── - { - "id": "go-api-timeline", - "title": "[API Go] Timeline Requetes par Serveur", - "type": "histogram", - "query": Q_HTTP, - "visState": { - "type": "histogram", - "params": { - "type": "histogram", - "grid": {"categoryLines": False}, - "categoryAxes": [{"id": "CategoryAxis-1", "type": "category", "position": "bottom", - "show": True, "style": {}, - "labels": {"show": True, "truncate": 100}, "title": {}}], - "valueAxes": [{"id": "ValueAxis-1", "name": "LeftAxis-1", "type": "value", - "position": "left", "show": True, "style": {}, - "scale": {"type": "linear", "mode": "normal"}, - "labels": {"show": True, "rotate": 0, "filter": False, "truncate": 100}, - "title": {"text": "Requetes"}}], - "seriesParams": [{"show": True, "type": "histogram", "mode": "stacked", - "data": {"label": "Requetes", "id": "1"}, - "valueAxis": "ValueAxis-1"}], - "addTooltip": True, "addLegend": True, "legendPosition": "right", - "times": [], "addTimeMarker": False, - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "date_histogram", "schema": "segment", - "params": {"field": "@timestamp", "interval": "auto", "min_doc_count": 1, "extended_bounds": {}}}, - {"id": "3", "enabled": True, "type": "terms", "schema": "group", - "params": {"field": "agent.name", "size": 3, "order": "desc", "orderBy": "1", - "otherBucket": False}}, - ], - }, - }, - # ── 5. Pie : distribution codes HTTP ────────────────────────────────────── - { - "id": "go-api-http-codes", - "title": "[API Go] Distribution Codes HTTP", - "type": "pie", - "query": Q_HTTP, - "visState": { - "type": "pie", - "params": { - "type": "pie", "addTooltip": True, "addLegend": True, - "legendPosition": "right", "isDonut": True, - "labels": {"show": True, "values": True, "last_level": True, "truncate": 100}, - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "terms", "schema": "segment", - "params": {"field": "data.id", "size": 10, "order": "desc", "orderBy": "1", - "otherBucket": True, "otherBucketLabel": "Autres", "missingBucket": False}}, - ], - }, - }, - # ── 6. Pie : méthodes HTTP ──────────────────────────────────────────────── - { - "id": "go-api-methods", - "title": "[API Go] Methodes HTTP", - "type": "pie", - "query": Q_HTTP, - "visState": { - "type": "pie", - "params": { - "type": "pie", "addTooltip": True, "addLegend": True, - "legendPosition": "right", "isDonut": False, - "labels": {"show": True, "values": True, "last_level": True, "truncate": 100}, - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "terms", "schema": "segment", - "params": {"field": "data.protocol", "size": 8, "order": "desc", "orderBy": "1", - "otherBucket": False, "missingBucket": False}}, - ], - }, - }, - # ── 7. Bar horizontal : top endpoints ──────────────────────────────────── - { - "id": "go-api-top-endpoints", - "title": "[API Go] Top Endpoints", - "type": "horizontal_bar", - "query": Q_HTTP, - "visState": { - "type": "horizontal_bar", - "params": { - "type": "horizontal_bar", - "grid": {"categoryLines": False}, - "categoryAxes": [{"id": "CategoryAxis-1", "type": "category", "position": "left", - "show": True, "style": {}, - "labels": {"show": True, "rotate": 0, "filter": True, "truncate": 300}, - "title": {}}], - "valueAxes": [{"id": "ValueAxis-1", "name": "LeftAxis-1", "type": "value", - "position": "bottom", "show": True, "style": {}, - "scale": {"type": "linear", "mode": "normal"}, - "labels": {"show": True, "rotate": 0, "filter": False, "truncate": 100}, - "title": {"text": "Requetes"}}], - "seriesParams": [{"show": True, "type": "horizontal_bar", "mode": "stacked", - "data": {"label": "Requetes", "id": "1"}, - "valueAxis": "ValueAxis-1"}], - "addTooltip": True, "addLegend": True, "legendPosition": "right", - "times": [], "addTimeMarker": False, - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "terms", "schema": "segment", - "params": {"field": "data.url", "size": 15, "order": "desc", "orderBy": "1", - "otherBucket": True, "otherBucketLabel": "Autres", "missingBucket": False}}, - {"id": "3", "enabled": True, "type": "terms", "schema": "group", - "params": {"field": "data.id", "size": 4, "order": "desc", "orderBy": "1", - "otherBucket": True, "otherBucketLabel": "Autres"}}, - ], - }, - }, - # ── 8. Bar horizontal : top endpoints en erreur ─────────────────────────── - { - "id": "go-api-error-endpoints", - "title": "[API Go] Endpoints en Erreur (4xx/5xx)", - "type": "horizontal_bar", - "query": Q_4XX + " OR " + Q_5XX, - "visState": { - "type": "horizontal_bar", - "params": { - "type": "horizontal_bar", - "grid": {"categoryLines": False}, - "categoryAxes": [{"id": "CategoryAxis-1", "type": "category", "position": "left", - "show": True, "style": {}, - "labels": {"show": True, "rotate": 0, "filter": True, "truncate": 300}, - "title": {}}], - "valueAxes": [{"id": "ValueAxis-1", "name": "LeftAxis-1", "type": "value", - "position": "bottom", "show": True, "style": {}, - "scale": {"type": "linear", "mode": "normal"}, - "labels": {"show": True, "rotate": 0, "filter": False, "truncate": 100}, - "title": {"text": "Erreurs"}}], - "seriesParams": [{"show": True, "type": "horizontal_bar", "mode": "stacked", - "data": {"label": "Erreurs", "id": "1"}, - "valueAxis": "ValueAxis-1"}], - "addTooltip": True, "addLegend": True, "legendPosition": "right", - "times": [], "addTimeMarker": False, - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "terms", "schema": "segment", - "params": {"field": "data.url", "size": 15, "order": "desc", "orderBy": "1", - "otherBucket": True, "otherBucketLabel": "Autres", "missingBucket": False}}, - {"id": "3", "enabled": True, "type": "terms", "schema": "group", - "params": {"field": "data.id", "size": 3, "order": "desc", "orderBy": "1", - "otherBucket": False}}, - ], - }, - }, - # ── 9. Bar horizontal : top IPs clientes ────────────────────────────────── - { - "id": "go-api-top-clients", - "title": "[API Go] Top IPs Clientes", - "type": "horizontal_bar", - "query": Q_HTTP, - "visState": { - "type": "horizontal_bar", - "params": { - "type": "horizontal_bar", - "grid": {"categoryLines": False}, - "categoryAxes": [{"id": "CategoryAxis-1", "type": "category", "position": "left", - "show": True, "style": {}, - "labels": {"show": True, "rotate": 0, "filter": True, "truncate": 200}, - "title": {}}], - "valueAxes": [{"id": "ValueAxis-1", "name": "LeftAxis-1", "type": "value", - "position": "bottom", "show": True, "style": {}, - "scale": {"type": "linear", "mode": "normal"}, - "labels": {"show": True, "rotate": 0, "filter": False, "truncate": 100}, - "title": {"text": "Requetes"}}], - "seriesParams": [{"show": True, "type": "horizontal_bar", "mode": "normal", - "data": {"label": "Requetes", "id": "1"}, - "valueAxis": "ValueAxis-1"}], - "addTooltip": True, "addLegend": True, "legendPosition": "right", - "times": [], "addTimeMarker": False, - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "terms", "schema": "segment", - "params": {"field": "data.srcip", "size": 15, "order": "desc", "orderBy": "1", - "otherBucket": False, "missingBucket": False}}, - ], - }, - }, - # ── 10. Table : erreurs critiques (panic / fatal) ────────────────────────── - { - "id": "go-api-panics", - "title": "[API Go] Erreurs Critiques (panic/fatal)", - "type": "table", - "query": Q_PANIC, - "visState": { - "type": "table", - "params": { - "perPage": 15, "showPartialRows": False, "showMetricsAtAllLevels": False, - "sort": {"columnIndex": None, "direction": None}, - "showTotal": False, "totalFunc": "sum", - }, - "aggs": [ - {"id": "1", "enabled": True, "type": "count", "schema": "metric", "params": {}}, - {"id": "2", "enabled": True, "type": "terms", "schema": "bucket", - "params": {"field": "agent.name", "size": 5, "order": "desc", "orderBy": "1", - "otherBucket": False, "missingBucket": False}}, - {"id": "3", "enabled": True, "type": "date_histogram", "schema": "bucket", - "params": {"field": "@timestamp", "interval": "1d", "min_doc_count": 1, "extended_bounds": {}}}, - ], - }, - "uiStateJSON": json.dumps({"vis": {"params": {"sort": {"columnIndex": 0, "direction": "desc"}}}}), - }, -] - -# ── Layout dashboard (grille 48 colonnes) ────────────────────────────────────── -# Ligne 0 : 3 métriques (total | 4xx | 5xx) -# Ligne 6 : timeline requêtes (pleine largeur) -# Ligne 18 : pie codes HTTP + pie méthodes -# Ligne 34 : top endpoints (pleine largeur) -# Ligne 50 : endpoints en erreur (gauche) + top clients (droite) -# Ligne 66 : table panics (pleine largeur) -PANELS = [ - {"panelIndex": "1", "gridData": {"x": 0, "y": 0, "w": 16, "h": 6, "i": "1"}, "version": "2.19.5", "type": "visualization", "id": "go-api-total-requests", "embeddableConfig": {}}, - {"panelIndex": "2", "gridData": {"x": 16, "y": 0, "w": 16, "h": 6, "i": "2"}, "version": "2.19.5", "type": "visualization", "id": "go-api-4xx", "embeddableConfig": {}}, - {"panelIndex": "3", "gridData": {"x": 32, "y": 0, "w": 16, "h": 6, "i": "3"}, "version": "2.19.5", "type": "visualization", "id": "go-api-5xx", "embeddableConfig": {}}, - {"panelIndex": "4", "gridData": {"x": 0, "y": 6, "w": 48, "h": 12, "i": "4"}, "version": "2.19.5", "type": "visualization", "id": "go-api-timeline", "embeddableConfig": {}}, - {"panelIndex": "5", "gridData": {"x": 0, "y": 18, "w": 24, "h": 16, "i": "5"}, "version": "2.19.5", "type": "visualization", "id": "go-api-http-codes", "embeddableConfig": {}}, - {"panelIndex": "6", "gridData": {"x": 24, "y": 18, "w": 24, "h": 16, "i": "6"}, "version": "2.19.5", "type": "visualization", "id": "go-api-methods", "embeddableConfig": {}}, - {"panelIndex": "7", "gridData": {"x": 0, "y": 34, "w": 48, "h": 16, "i": "7"}, "version": "2.19.5", "type": "visualization", "id": "go-api-top-endpoints", "embeddableConfig": {}}, - {"panelIndex": "8", "gridData": {"x": 0, "y": 50, "w": 28, "h": 16, "i": "8"}, "version": "2.19.5", "type": "visualization", "id": "go-api-error-endpoints", "embeddableConfig": {}}, - {"panelIndex": "9", "gridData": {"x": 28, "y": 50, "w": 20, "h": 16, "i": "9"}, "version": "2.19.5", "type": "visualization", "id": "go-api-top-clients", "embeddableConfig": {}}, - {"panelIndex": "10", "gridData": {"x": 0, "y": 66, "w": 48, "h": 12, "i": "10"}, "version": "2.19.5", "type": "visualization", "id": "go-api-panics", "embeddableConfig": {}}, -] - -# ── Main ─────────────────────────────────────────────────────────────────────── -def main(): - print("=== Creation dashboard: API Go - Performance & Trafic ===\n") - - for viz in VISUALIZATIONS: - vis_state = dict(viz["visState"]) - vis_state["title"] = viz["title"] - body = { - "attributes": { - "title": viz["title"], - "visState": json.dumps(vis_state), - "uiStateJSON": viz.get("uiStateJSON", "{}"), - "description": "", - "kibanaSavedObjectMeta": {"searchSourceJSON": search_src(viz["query"])}, - } - } - r = api("POST", f"/api/saved_objects/visualization/{viz['id']}?overwrite=true", body) - if "id" in r: - print(f" OK {viz['title']}") - else: - print(f" ERR {viz['title']}: {r}") - sys.exit(1) - - dashboard_body = { - "attributes": { - "title": "API Go - Performance et Trafic", - "description": "Requetes HTTP Gin, codes de statut, endpoints, temps de reponse, erreurs 4xx/5xx, panics", - "panelsJSON": json.dumps(PANELS), - "optionsJSON": json.dumps({"useMargins": True, "hidePanelTitles": False}), - "timeRestore": False, - "kibanaSavedObjectMeta": { - "searchSourceJSON": json.dumps({"query": {"language": "kuery", "query": ""}, "filter": []}) - }, - } - } - r = api("POST", "/api/saved_objects/dashboard/go-api-performance-dashboard?overwrite=true", dashboard_body) - if "id" in r: - print(f"\n OK Dashboard: {r['id']}") - print(f" URL: https:///#/app/dashboards#/view/{r['id']}") - else: - print(f"\n ERR Dashboard: {r}") - sys.exit(1) - - print("\n=== Termine ===") - -if __name__ == "__main__": - main()