Übersicht
In diesem Leitfaden wird die End-to-End-Bereitstellung des Elastic Stack (Elasticsearch und Kibana) auf einem freigegebenen Cluster von Google Distributed Cloud (GDC) mit Air Gap beschrieben. Außerdem wird gezeigt, wie Sie ihn in einen LLM-Dienst (Large Language Model) einbinden, um die generativen KI-Funktionen von Elastic zu bewerten.
Bei der Bereitstellung wird der offizielle Elastic Cloud on Kubernetes (ECK)-Operator verwendet, der im GDC mit Air Gap-Marketplace verfügbar ist. Der Operator wird in einem Projekt-Namespace in einem freigegebenen Kubernetes-Cluster installiert und automatisiert die Bereitstellung und das Lebenszyklusmanagement von Elasticsearch- und Kibana-Ressourcen. Nach der Bereitstellung stellt Kibana eine Verbindung zu einem LLM-Inferenzendpunkt her, z. B. zu verwaltetem Gemini auf GDC oder einem selbstverwalteten OpenAI-kompatiblen Dienst wie Ollama oder vLLM. Diese Integration unterstützt die generativen KI-Funktionen von Elastic, einschließlich des Elastic AI-Agents, benutzerdefinierter Agents, die mit Agent Builder erstellt wurden, und Attack Discovery.
Dieser Leitfaden wurde für Elastic v9.4.0, den Elastic Kubernetes Operator v3.4.0 und GDC v1.16.2 geschrieben. Einige Anleitungen können sich leicht unterscheiden, wenn Sie verschiedene Versionen verwenden.
Architektur
Die Architektur besteht aus einer Elastic Stack-Bereitstellung, die vom ECK-Operator in einem Projekt-Namespace in einem freigegebenen GDC-Nutzercluster verwaltet wird. Kibana kommuniziert über das interne GDC-Netzwerk mit einem LLM-Inferenzendpunkt.

Zu den wichtigsten Komponenten dieser Architektur gehören:
- GDC-Cluster: Ein gemeinsamer Kubernetes-Cluster mit Organisationsbereich, der an mehrere Projekte angehängt ist und GDC Marketplace-Softwarepakete und Anwendungsarbeitslasten hostet.
- GDC-Projekt: Der Projekt-Namespace im freigegebenen Cluster, der den ECK-Operator, den Elasticsearch-Cluster, die Kibana-Instanz und die zugehörigen Kubernetes-Secrets und NetworkPolicies isoliert.
- Elastic Cloud on Kubernetes (ECK)-Operator: Der Operator wird vom GDC Marketplace im Projekt-Namespace installiert und verwaltet die benutzerdefinierten Ressourcen
ElasticsearchundKibana. Außerdem gleicht er die Elastic-Lizenz ab, die für generative KI-Funktionen und externe LLM-Connectors erforderlich ist. - Elasticsearch: Speichert und indexiert Betriebs- und Sicherheitsdaten und führt Such- und ES|QL-Abfragen aus, die von den KI-Funktionen und -Agents von Kibana generiert werden.
- Kibana: Hier werden die generativen KI-Funktionen von Elastic gehostet, darunter der Elastic AI-Agent (für die Untersuchung von Protokollen in natürlicher Sprache und die ES|QL-Generierung), der Agent Builder (zum Erstellen benutzerdefinierter konversationeller Agents und Tools für Elasticsearch-Daten) und Attack Discovery (für die Korrelation von Sicherheitswarnungen und die Analyse von Angriffsketten). Kibana verwaltet auch die LLM-Aktions-Connectors, die den mehrstufigen Toolaufruf zwischen dem Nutzer, Elasticsearch und dem LLM-Dienst orchestrieren.
- LLM-Dienst: Ein verwalteter LLM-Dienst (z. B. Gemini on GDC) oder ein selbstverwalteter Inferenzserver (z. B. Ollama oder vLLM), der Kibana über das interne GDC-Netzwerk Chatvervollständigungs- und Toolaufruffunktionen bereitstellt.
Hinweis
Prüfen Sie vor der Bereitstellung, ob Ihre GDC-Umgebung die folgenden Voraussetzungen und Annahmen erfüllt:
- Gemeinsam genutzter Kubernetes-Cluster und GDC-Projekt: Sie haben Zugriff auf einen vorhandenen gemeinsam genutzten GDC-Cluster und ein GDC-Projekt, das mit diesem Cluster verknüpft ist. Das Projekt dient als Namespace-Container für alle Kubernetes-Ressourcen, die in dieser Anleitung bereitgestellt werden. Achten Sie darauf, dass der Cluster über genügend Rechen- und nichtflüchtige Speicherressourcen verfügt, um die ECK-Operator-, Elasticsearch- und Kibana-Arbeitslasten zu hosten.
- LLM-Dienst: Sie haben Netzwerkzugriff auf einen LLM-Dienst, entweder auf den verwalteten Gemini-Dienst (falls in Ihrer GDC-Umgebung verfügbar) oder auf einen selbstverwalteten OpenAI-kompatiblen LLM-Dienst (z. B.
gemma4:31b, der über Ollama oder vLLM in einem GPU-Projekt bereitgestellt wird). Die Bereitstellung der LLM-Infrastruktur selbst wird in diesem Leitfaden nicht behandelt. Die spezifischen Modell- und API-Anforderungen werden jedoch unter Anforderungen für den LLM-Dienst beschrieben. Rufen Sie die Elastic-Version ab, die in Ihrer GDC-Umgebung enthalten ist:
export ELASTIC_VERSION=$(curl -sk "https://harbor.${ORG}.${ZONE}.${GDCH_DOMAIN}/api/v2.0/projects/library/repositories/elasticsearch%252Felasticsearch/artifacts" | jq -r '[.[].tags[]?.name] | sort_by(split(".") | map(tonumber)) | last')Konfigurieren Sie Umgebungsvariablen, auf die in diesem Leitfaden verwiesen wird. Ändern Sie diese Werte nach Bedarf, um sie an Ihre spezifische Umgebung anzupassen:
# GDC environment configuration export PROJECT_ID="your-project-id" export CLUSTER_NAME="your-shared-cluster-name" export ZONE="your-zone-name" export USER_NAME="your-gdc-user-email" # Marketplace package and Elastic Stack configuration export MARKETPLACE_SERVICE_NAME="elastic" # LLM service configuration export LLM_CONNECTOR_NAME="your-llm-connector-name" export LLM_API_URL="http://your-llm-service-host:11434/v1/chat/completions" export LLM_MODEL_NAME="your-llm-model-name" export LLM_API_KEY="your-llm-api-key"Konfigurieren Sie
gdcloud:gdcloud config set project ${PROJECT_ID} gdcloud config set core/zone ${ZONE}Fordern Sie die erforderlichen IAM-Rollen auf Projektebene für Ihren Nutzer im Ziel-GDC-Projekt (
${PROJECT_ID}) an oder binden Sie sie. Gemäß der GDC Marketplace-Dokumentation zum Lebenszyklus und den GDC-Netzwerkanforderungen sind mindestens die folgenden Projektrollen erforderlich:- Namespace-Administrator (
namespace-admin): Vollständiger Administratorzugriff zum Erstellen und Verwalten von Kubernetes-Arbeitslasten, Secrets, Diensten und benutzerdefinierten Ressourcen im Projekt-Namespace auf dem freigegebenen Cluster. - Projektbetrachter (
project-viewer): Lesezugriff zum Aufrufen des vorhandenen Projekts und seiner Ressourcen in der GDC-Konsole und ‑CLI. - Marketplace-Bearbeiter (
marketplace-editor): Berechtigung zum Installieren, Aktualisieren und Deinstallieren von GDC Marketplace-Softwarepaketen im Projekt. - Project NetworkPolicy Admin (
project-networkpolicy-admin): Berechtigung zum Konfigurieren globalerProjectNetworkPolicy-Regeln, die projektübergreifenden und externen Traffic zu den LoadBalancer-Diensten von Kibana und Elasticsearch zulassen.
Bitten Sie Ihren IAM-Administrator der Organisation oder Ihren IAM-Administrator des Projekts, Ihnen diese Rollen zuzuweisen. Wenn Sie IAM-Administratorberechtigungen haben, können Sie die folgenden Befehle ausführen:
gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=namespace-admin gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=project-viewer gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=marketplace-editor gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=project-networkpolicy-admin- Namespace-Administrator (
Rufen Sie die kubeconfig-Datei für den freigegebenen Cluster ab und konfigurieren Sie einen
ku-Shell-Alias fürkubectl:KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \ get-credentials ${CLUSTER_NAME} \ --zone ${ZONE} alias ku="kubectl --kubeconfig=kubeconfig-${CLUSTER_NAME}.yaml"
Elastic Marketplace-Paket installieren
In diesem Abschnitt installieren Sie den ECK-Operator (Elastic Cloud on Kubernetes) aus dem GDC mit Air Gap-Marketplace in Ihrem Projekt-Namespace. Folgen Sie dazu der Anleitung zum GDC-Marketplace-Lebenszyklus.
Über die gdcloud-Befehlszeile (oder die GDC-Konsole) installieren
Listen Sie die verfügbaren Marketplace-Softwarepakete auf, um den Dienstnamen und die verfügbare Version zu bestätigen:
gdcloud marketplace services listDie Ausgabe sollte in etwa so aussehen:
SERVICE LATEST VERSION confluent <CONFLUENT_VERSION> dataproc <DATAPROC_VERSION> elastic <ECK_OPERATOR_VERSION> mariadb <MARIADB_VERSION> mattermost <MATTERMOST_VERSION> mongodb <MONGODB_VERSION> neo4j <NEO4J_VERSION> redis <REDIS_VERSION> starboard <STARBOARD_VERSION> starburst <STARBURST_VERSION> tes <TES_VERSION> vault <VAULT_VERSION>Installieren Sie das Elastic Marketplace-Paket auf dem freigegebenen Zielcluster:
gdcloud marketplace services install ${MARKETPLACE_SERVICE_NAME} \ --cluster=${CLUSTER_NAME} \ --zone=${ZONE} \ --project ${PROJECT_ID}*(Alternativ können Sie in der GDC-Konsole Ihr Projekt auswählen
${PROJECT_ID}, zu Marketplace navigieren, den Eintrag Elastic Cloud on Kubernetes auswählen, auf Installieren klicken, den Cluster${CLUSTER_NAME}auswählen und auf Installieren klicken.)*Prüfen Sie, ob das StatefulSet
elastic-operatorund der Pod in Ihrem Projekt-Namespace (${PROJECT_ID}) ausgeführt werden:ku get statefulset,pods -n ${PROJECT_ID}Die Ausgabe sollte in etwa so aussehen:
NAME READY AGE statefulset.apps/elastic-operator 1/1 3m NAME READY STATUS RESTARTS AGE pod/elastic-operator-0 1/1 Running 0 3m
Elastic Stack bereitstellen
Elastic Stack-Manifest erstellen
Das GDC Marketplace-Paket stellt den ECK-Operator bereit, der vorkonfiguriert ist, um Elasticsearch- und Kibana-Container-Images aus der lokalen, Air-Gap-geschützten Harbor-Registry abzurufen.
Erstellen Sie elastic-stack.yaml, um einen Elasticsearch-Cluster mit einem Knoten, eine Kibana-UI-Instanz, LoadBalancer-HTTP-Dienste und eine allow-all NetworkPolicy in Ihrem Projekt-Namespace (${PROJECT_ID}) bereitzustellen. Das Manifest enthält auch eine Lizenz Secret, die vom ECK-Operator abgeglichen wird. Diese ist hier als 30-tägige Enterprise-Testversion (eck-trial-license) konfiguriert, falls Sie noch keine eigene Enterprise-Lizenz haben:
cat <<EOF > elastic-stack.yaml
apiVersion: v1
kind: Secret
metadata:
name: eck-trial-license
namespace: ${PROJECT_ID}
labels:
license.k8s.elastic.co/type: enterprise_trial
annotations:
elastic.co/eula: accepted
---
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elastic-cluster
namespace: ${PROJECT_ID}
spec:
version: ${ELASTIC_VERSION}
http:
service:
spec:
type: LoadBalancer
nodeSets:
- name: default
count: 1
config:
# Disable mmap to avoid requiring privileged host sysctl modifications
node.store.allow_mmap: false
podTemplate:
spec:
initContainers:
- name: sysctl
securityContext:
privileged: false
allowPrivilegeEscalation: false
runAsNonRoot: true
capabilities:
drop:
- ALL
command: ["sh", "-c", "true"]
containers:
- name: elasticsearch
resources:
requests:
memory: 2Gi
cpu: 500m
limits:
memory: 4Gi
cpu: 2
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
name: kibana-ui
namespace: ${PROJECT_ID}
spec:
version: ${ELASTIC_VERSION}
count: 1
elasticsearchRef:
name: elastic-cluster
http:
service:
spec:
type: LoadBalancer
podTemplate:
spec:
containers:
- name: kibana
resources:
requests:
memory: 1Gi
cpu: 200m
limits:
memory: 2Gi
cpu: 1
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
namespace: ${PROJECT_ID}
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0
EOF
Deployment anwenden und prüfen
Wenden Sie das Manifest an:
ku apply -f elastic-stack.yaml
Wenden Sie eine globale ProjectNetworkPolicy an, damit GDC-Firewallregeln eingehenden Traffic zu den LoadBalancer-IP-Adressen sowie projektübergreifenden Traffic (z. B. Kommunikation mit dem LLM-Dienst) zulassen:
kubectl --kubeconfig=kubeconfig-global.yaml apply -f - <<EOF
apiVersion: networking.global.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
namespace: ${PROJECT_ID}
name: allow-inbound-traffic-from-external
spec:
policyType: Ingress
subject:
subjectType: UserWorkload
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0
---
apiVersion: networking.global.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
namespace: ${PROJECT_ID}
name: allow-inbound-traffic-from-all-projects
spec:
policyType: Ingress
subject:
subjectType: UserWorkload
ingress:
- from:
- projects: {}
EOF
Überwachen Sie die Pods, Dienste und benutzerdefinierten Ressourcen, bis sowohl Elasticsearch als auch Kibana den Status Running und Ready erreichen und LoadBalancer-IP-Adressen auf ${CLUSTER_NAME} erhalten:
ku get pods,svc,elasticsearch,kibana -n ${PROJECT_ID}
Sobald die Ressourcen bereit sind, sollte die Ausgabe in etwa so aussehen:
NAME READY STATUS RESTARTS AGE
pod/elastic-cluster-es-default-0 1/1 Running 0 3m
pod/elastic-operator-0 1/1 Running 0 15m
pod/kibana-ui-kb-869844478d-59ptw 1/1 Running 0 3m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/elastic-cluster-es-default ClusterIP None <none> 9200/TCP 11m
service/elastic-cluster-es-http LoadBalancer 10.101.18.181 <ELASTIC_EXTERNAL_IP> 9200:32159/TCP 11m
service/elastic-cluster-es-internal-http ClusterIP 10.101.18.81 <none> 9200/TCP 11m
service/elastic-cluster-es-transport ClusterIP None <none> 9300/TCP 11m
service/g-svc-g-fre-elastic-cluster-es-http-shared-clus-extern-56d5eb67 ClusterIP None <none> 9200/TCP 11m
service/g-svc-g-fre-kibana-ui-kb-http-shared-cluster-0b-extern-75a78b1f ClusterIP None <none> 5601/TCP 11m
service/kibana-ui-kb-http LoadBalancer 10.101.19.86 <KIBANA_EXTERNAL_IP> 5601:32735/TCP 11m
NAME HEALTH NODES VERSION PHASE AGE
elasticsearch.elasticsearch.k8s.elastic.co/elastic-cluster green 1 <ELASTIC_VERSION> Ready 3m
NAME HEALTH NODES VERSION AGE
kibana.kibana.k8s.elastic.co/kibana-ui green 1 <ELASTIC_VERSION> 3m
Exportieren Sie die externen LoadBalancer-IP-Adressen, die Elasticsearch und Kibana zugewiesen sind, zur Verwendung in nachfolgenden Schritten:
export ELASTICSEARCH_IP=$(ku get svc elastic-cluster-es-http \
-n ${PROJECT_ID} \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export KIBANA_IP=$(ku get svc kibana-ui-kb-http \
-n ${PROJECT_ID} \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Kibana External URL: https://${KIBANA_IP}:5601"
echo "Elasticsearch External URL: https://${ELASTICSEARCH_IP}:9200"
Anmeldedaten abrufen und auf die Kibana-Benutzeroberfläche zugreifen
elastic-Superuser-Passwort abrufen
ECK generiert automatisch ein Kubernetes-Secret (elastic-cluster-es-elastic-user), das das Standard-Superuser-Passwort für elastic enthält. Rufen Sie sie ab und decodieren Sie sie mit:
export ELASTIC_PASSWORD=$(ku get secret elastic-cluster-es-elastic-user \
-n ${PROJECT_ID} \
-o jsonpath='{.data.elastic}' | base64 -d)
echo "${ELASTIC_PASSWORD}"
Verbindung prüfen und anmelden
Prüfen Sie, ob Elasticsearch von Ihrer Workstation aus über HTTPS erreichbar ist:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" "https://${ELASTICSEARCH_IP}:9200"Öffnen Sie
https://${KIBANA_IP}:5601in Ihrem Browser, akzeptieren Sie die Warnung zum selbst signierten Zertifikat und melden Sie sich mit folgenden Anmeldedaten an:- Nutzername:
elastic - Passwort:
<output from ELASTIC_PASSWORD above>
- Nutzername:
Elastic-Lizenz prüfen
Für die generativen KI-Funktionen von Elastic (einschließlich Elastic AI Agent, Agent Builder und Attack Discovery) und externe LLM-Connectors ist eine Enterprise-Lizenz (oder eine aktive 30-tägige Enterprise-Testlizenz) erforderlich.
Wenn ein Elasticsearch-Cluster vom ECK-Operator verwaltet wird, gleicht der license-controller von ECK die Clusterlizenz kontinuierlich mit Kubernetes-Secrets im Operator-Namespace (${PROJECT_ID}) ab. Wenn Sie noch keine Enterprise-Produktionslizenz haben, weist das in elastic-stack.yaml (license.k8s.elastic.co/type:
enterprise_trial) enthaltene eck-trial-license-Secret ECK an, automatisch eine 30-tägige Enterprise-Testlizenz bereitzustellen und zu verwalten. (Hinweis: Wenn Sie einen Testzeitraum manuell über POST
/_license/start_trial ohne ein ECK-Lizenz-Secret starten, wird der Cluster im nächsten Abgleichszyklus von ECK auf basic zurückgesetzt.)
So prüfen Sie die aktive Lizenz über die Befehlszeile:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \
"https://${ELASTICSEARCH_IP}:9200/_license" | jq .
*(Alternativ können Sie in Kibana das Navigationsmenü öffnen und zu Management > Dev Tools gehen und dann auf dem Tab „Console“ GET /_license ausführen.)*
Die Ausgabe sollte in etwa so aussehen und "status": "active" und "type": "enterprise" (oder "type": "trial", wenn Sie die Testlizenz verwenden) enthalten:
{
"license": {
"status": "active",
"uid": "d8c2b566-8c2b-436c-a1ea-5502d6790505",
"type": "trial",
"issue_date": "2026-09-17T23:19:25.053Z",
"issue_date_in_millis": 1789687165053,
"expiry_date": "2026-10-17T23:19:25.053Z",
"expiry_date_in_millis": 1792279165053,
"max_nodes": 1000,
"max_resource_units": null,
"issued_to": "elastic-cluster",
"issuer": "elasticsearch",
"start_date_in_millis": -1
}
}
Integriertes Beispiel-Dataset laden
Wenn Sie die KI-Funktionen von Elastic bewerten möchten, ohne benutzerdefinierte Pipelines für die Datenaufnahme zu schreiben oder externen Internetzugriff zu benötigen, können Sie das in Kibana integrierte Beispiel-Webprotokoll-Dataset (kibana_sample_data_logs) laden. Da das Beispiel-Datenarchiv im Kibana-Container-Image enthalten ist, wird es in einer Air-Gap-Umgebung in Sekundenschnelle installiert. Das Dataset enthält 14.074 Webzugriffs-Logdokumente mit Client-IP-Adressen (clientip), HTTP-Statuscodes (response), Quell- und Zielländern (geo.src, geo.dest), übertragenen Byte (bytes), URLs und User-Agent-Strings.
Weitere integrierte Datasets (flights und ecommerce) finden Sie unter Beispieldaten in Kibana hinzufügen und elastic-datasets-builtin.md.
Dataset laden
Führen Sie den folgenden Befehl aus, um kibana_sample_data_logs über den internen Beispieldaten-Endpunkt von Kibana zu laden:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \
-X POST "https://${KIBANA_IP}:5601/api/sample_data/logs" \
-H "kbn-xsrf: true" \
-H "x-elastic-internal-origin: Kibana"
Beispiel-Dataset prüfen
Prüfen Sie, ob das Beispieldataset logs in Kibana als installed gekennzeichnet ist, und ob der zugrunde liegende Datenstream 14,074 Dokumente in Elasticsearch enthält:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \
"https://${KIBANA_IP}:5601/api/sample_data" \
-H "kbn-xsrf: true" \
-H "x-elastic-internal-origin: Kibana" \
| jq '.[] | select(.id == "logs") | {id, name, status}'
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \
"https://${ELASTICSEARCH_IP}:9200/_cat/indices/kibana_sample_data_logs*?v"
Die Ausgabe sollte in etwa so aussehen:
{
"id": "logs",
"name": "Sample web logs",
"status": "installed"
}
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size
yellow open .ds-kibana_sample_data_logs-2026.09.22-000001 0YivG3oFQQmb-mYqmULr_g 1 1 14074 0 8.7mb 8.7mb 8.7mb
Anforderungen an den LLM-Dienst
In einer GDC-Umgebung mit Air Gap sind in der Cloud gehostete Elastic Managed LLMs und externe öffentliche SaaS-LLM-Anbieter nicht erreichbar. Je nach GDC-Umgebung:
- Verwaltetes Gemini in GDC: In GDC-Umgebungen, die Gemini als verwalteten LLM-Dienst anbieten, können Sie Kibana direkt mit dem verwalteten Gemini-Dienst verbinden, sofern verfügbar.
- Selbstverwalteter LLM-Dienst: Alternativ können Sie Elastic mit einem selbstverwalteten LLM-Dienst verbinden, der in Ihrer GDC-Umgebung gehostet wird (z. B. auf GDC-GPU-Knoten).
Die Bereitstellung eines selbstverwalteten LLM-Dienstes wird in diesem Leitfaden nicht behandelt. Achten Sie beim Bereitstellen oder Auswählen eines selbstverwalteten LLM-Dienstes für Elastic darauf, dass er die Anforderungen erfüllt, die sich aus den offiziellen Leitfäden von Elastic ergeben:
- Zugriff auf LLMs konfigurieren
- Selbstverwaltete benutzerdefinierte LLMs (siehe auch Verbindung zu vLLM in Air-Gap-Umgebungen herstellen)
- Beobachtbarkeit von LLMs und agentischer KI
Zusammenfassung der technischen Anforderungen
Die folgenden Punkte fassen die wichtigsten Anforderungen an API, Modellfunktionen, Kontextfenster und Laufzeit zusammen, die für einen selbstverwalteten LLM-Dienst erforderlich sind, damit er zuverlässig mit dem KI-Agenten, dem Agent Builder und der Attack Discovery von Elastic funktioniert. Die in den folgenden Abschnitten genannten spezifischen Konfigurationsparameternamen (z. B. num_ctx, num_predict, repeat_penalty, repeat_last_n, OLLAMA_FLASH_ATTENTION und OLLAMA_NUM_PARALLEL) werden am Beispiel von Ollama angegeben. Wenden Sie die entsprechenden Einstellungen an, wenn Sie eine andere Inferenz-Engine wie vLLM verwenden.
- OpenAI-kompatible Chat-Vervollständigungs-API (
/v1/chat/completions) mit nativen Funktionsaufrufen:- Jeder selbstverwaltete Inferenzserver (z. B. Ollama oder vLLM), der einen OpenAI-kompatiblen
/v1/chat/completions-Endpunkt (einschließlich Server-Sent Events-Streaming über"stream": true) bereitstellt, kann über den OpenAI-Connector von Kibana integriert werden. Der Anbieter muss dabei auf Other (OpenAI Compatible Service) (Andere (OpenAI-kompatibler Dienst)) festgelegt sein. - Aktivieren Sie den nativen Funktionsaufruf (
"enableNativeFunctionCalling": true) für den Kibana-Connector, wenn Sie Modelle verwenden, die den Aufruf von cloudnativen Tools unterstützen (z. B.gemma4:31b). Standardmäßig ("enableNativeFunctionCalling": false) verwendet Kibana den promptbasierten simulierten Funktionsaufruf, der bei verschachtelten Toolaufrufen weniger zuverlässig ist und mit Parsing-Fehlern (z. B.Error: Missing name for tool use) fehlschlagen kann. Wenn Sie den nativen Funktionsaufruf aktivieren, wird die Formatierung des Toolaufrufs direkt an das OpenAI-tools-Protokoll des Inferenzservers delegiert.
- Jeder selbstverwaltete Inferenzserver (z. B. Ollama oder vLLM), der einen OpenAI-kompatiblen
- Anweisungsoptimiertes Modell mit nativen Tool- und Funktionsaufruffunktionen:
- Der Elastic KI-Agent (
elastic-ai-agent) und benutzerdefinierte Agent Builder-Agenten basieren auf mehrstufigen Toolaufrufen (platform.core.list_indices,platform.core.get_index_mapping,platform.core.search,platform.core.execute_esqlundplatform.core.cases). Sie verwenden diese Tools, um Indexzuordnungen zu ermitteln, ES|QL-Abfragen für Elasticsearch zu generieren und auszuführen und Ergebnisse zu synthetisieren. - Das ausgewählte Modell muss auf Anweisungen abgestimmt sein und in der Lage sein, gültige Aufrufe von cloudnativen Tools, strukturierte JSON-Ausgaben und ES|QL-Abfragen zu generieren. Weitere Informationen zu den Kriterien für die Modellbewertung finden Sie in der LLM-Leistungsmatrix für Observability und der LLM-Leistungsmatrix für Elastic Security von Elastic.
- Der Elastic KI-Agent (
- Kontextfenster von mindestens
128,000Tokens (z. B.num_ctx: 131072in Ollama):- In der allgemeinen Dokumentation zu selbstverwalteten benutzerdefinierten LLMs von Elastic wird ein Minimum von 64.000 Tokens angegeben. Für den Elastic KI-Agent (
elastic-ai-agent) wird jedoch dringend ein Kontextfenster von 128.000 Tokens (131,072Tokens) empfohlen. - Bei mehrstufigen Prüfungen kombiniert der Agent Systemanweisungen und Tooldefinitionen mit Indexschemas, ES|QL-Dokumentation und Rohsuchergebnissen (z. B. Abrufen von bis zu 100 Beispieldokumenten, um Feldwerte vor der Aggregation zu prüfen). Eine einzelne Untersuchung kann mehr als 70.000 Tokens im Unterhaltungsverlauf umfassen. Bei einem Kontextfenster mit 64.000 Tokens wird der Prompt dann mitten in der Unterhaltung abgeschnitten.
- Beachten Sie, dass in Ollama eine
PARAMETER num_ctx-Anweisung, die in dieModelfileeines Modells eingebettet ist, die UmgebungsvariableOLLAMA_CONTEXT_LENGTHdes Containers überschreibt. Achten Sie darauf, dass sowohlOLLAMA_CONTEXT_LENGTH=131072als auchPARAMETER num_ctx 131072in derModelfiledes Modells konfiguriert sind. Auf einer NVIDIA A100- oder H100-GPU mit 80 GB passtgemma4:31bbei einem Kontext von128Kproblemlos in den VRAM.
- In der allgemeinen Dokumentation zu selbstverwalteten benutzerdefinierten LLMs von Elastic wird ein Minimum von 64.000 Tokens angegeben. Für den Elastic KI-Agent (
- Tokenausgabelimit und mäßige Wiederholungsstrafe (z. B.
num_predict: 8192undrepeat_penalty: 1.05in Ollama):- Der OpenAI-Stream-Adapter von Kibana behandelt
"finish_reason": "length"als schwerwiegendenToken limit reached-Fehler und sendet in jeder Anfrage"temperature": 0(Greedy-Decodierung). - Konfigurieren Sie für Modelle mit logischen Fähigkeiten (z. B.
gemma4:31b, das interne Denk-Tokens generiert, bevor es Toolaufrufe ausgibt) ein Tokenausgabelimit von mindestens8,192Tokens und eine milde Wiederholungsstrafe. Legen Sie in Ollama beispielsweisenum_predict: 8192,repeat_penalty: 1.05undrepeat_last_n: 64fest. Vermeiden Sie zu aggressive Strafen für Wiederholungen (z. B.1.15+über große Fenster), da das Modell sonst bestraft wird, wenn es eine ES|QL-Abfrage aus seinem internen Reasoning-Block in das endgültige Toolaufruf-JSON kopiert.
- Der OpenAI-Stream-Adapter von Kibana behandelt
- GPU-Beschleunigung, Flash Attention und parallele KV-Cache-Slots (< 60 Sekunden pro Runde):
- Der OpenAI-Connector von Kibana erzwingt ein standardmäßiges HTTP-Zeitlimit von 60 Sekunden pro Streaming-Turn.
- Da ein einzelner Agenten-Turn verschachtelte LLM-Unteraufrufe auslösen kann (z. B. um Suchanfragen in natürlicher Sprache in ES|QL-Abfragen zu übersetzen, während die Hauptunterhaltung des Agenten aktiv ist), kann das Ausführen eines Inferenzservers mit nur einem KV-Cache-Slot dazu führen, dass Unteraufrufe den im Cache gespeicherten Kontext der Hauptunterhaltung entfernen und nachfolgende Turns verlangsamen.
- Legen Sie in Ollama
OLLAMA_FLASH_ATTENTION=1undOLLAMA_NUM_PARALLEL=2so fest, dass Flash Attention die Auswertung von Langkontexten beschleunigt und die Hauptunterhaltung und die verschachtelten Unteraufrufe separate KV-Cache-Slots im GPU-Speicher beibehalten.
LLM-Connector in Kibana konfigurieren
Sobald Ihr OpenAI-kompatibler LLM-Dienst ausgeführt wird und vom Kibana-Pod aus erreichbar ist, konfigurieren Sie einen OpenAI-Connector in Kibana entweder über die Befehlszeile oder die Kibana-Benutzeroberfläche.
Option 1: Connector über die Befehlszeile erstellen
Führen Sie den folgenden
POST /api/actions/connector-Befehl aus, um einen OpenAI-Connector (.gen-ai) zu erstellen, der auf Ihren LLM-Dienst (${LLM_API_URL}) verweist, wobei native Funktionsaufrufe aktiviert sind ("enableNativeFunctionCalling": true). Kibana generiert und weist automatisch eine eindeutige Connector-ID zu:curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/actions/connector" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"${LLM_CONNECTOR_NAME}\", \"connector_type_id\": \".gen-ai\", \"config\": { \"apiProvider\": \"Other\", \"apiUrl\": \"${LLM_API_URL}\", \"defaultModel\": \"${LLM_MODEL_NAME}\", \"enableNativeFunctionCalling\": true }, \"secrets\": { \"apiKey\": \"${LLM_API_KEY}\" } }" | jq .Prüfen Sie, ob der Connector
${LLM_CONNECTOR_NAME}vorhanden ist und keine Secrets fehlen. Listen Sie dazu die Connectors von Kibana auf und filtern Sie nach Name:curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ "https://${KIBANA_IP}:5601/api/actions/connectors" \ -H "kbn-xsrf: true" \ | jq ".[] | select(.name == \"${LLM_CONNECTOR_NAME}\")"Die Ausgabe sollte in etwa so aussehen:
{ "id": "<GENERATED_CONNECTOR_ID>", "name": "<LLM_CONNECTOR_NAME>", "config": { "apiProvider": "Other", "apiUrl": "<LLM_API_URL>", "defaultModel": "<LLM_MODEL_NAME>", "enableNativeFunctionCalling": true }, "connector_type_id": ".gen-ai", "is_preconfigured": false, "is_deprecated": false, "referenced_by_count": 0, "is_missing_secrets": false, "is_system_action": false }Um die End-to-End-Konnektivität zwischen Kibana und dem LLM-Dienst über die CLI zu testen, suchen Sie die automatisch generierte Connector-ID anhand des Namens und rufen Sie den
_execute-Endpunkt auf:export CONNECTOR_ID=$(curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ "https://${KIBANA_IP}:5601/api/actions/connectors" \ -H "kbn-xsrf: true" \ | jq -r ".[] | select(.name == \"${LLM_CONNECTOR_NAME}\") | .id") curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/actions/connector/${CONNECTOR_ID}/_execute" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d "{ \"params\": { \"subAction\": \"invokeAI\", \"subActionParams\": { \"model\": \"${LLM_MODEL_NAME}\", \"messages\": [ { \"role\": \"user\", \"content\": \"Reply with the single word Pong.\" } ] } } }" | jq .Die Ausgabe sollte in etwa so aussehen und
"status": "ok"sowie die Antwort des Modells enthalten:{ "status": "ok", "data": { "message": "Pong", "usage": { "prompt_tokens": 23, "prompt_tokens_details": { "cached_tokens": 0 }, "completion_tokens": 38, "total_tokens": 61 } }, "connector_id": "<GENERATED_CONNECTOR_ID>" }
Option 2: Connector über die Kibana-Benutzeroberfläche erstellen
- Melden Sie sich in Kibana (
https://${KIBANA_IP}:5601) an. - Öffnen Sie das Hauptnavigationsmenü und rufen Sie Verwaltung > Benachrichtigungen und Statistiken > Connectors auf.
- Klicken Sie auf Connector erstellen und wählen Sie OpenAI aus.
- Konfigurieren Sie die Connector-Felder:
- Connector-Name: Geben Sie den Wert von
${LLM_CONNECTOR_NAME}ein (z. B.Gemma4-31B). - OpenAI-Anbieter auswählen: Wählen Sie Other (OpenAI Compatible Service) (Andere (OpenAI-kompatibler Dienst)) aus.
- URL: Geben Sie den Wert von
${LLM_API_URL}(den/v1/chat/completions-Endpunkt Ihres LLM-Dienstes) ein. - Standardmodell: Geben Sie den Wert von
${LLM_MODEL_NAME}ein (z. B.gemma4:31b). - API-Schlüssel: Geben Sie den Wert von
${LLM_API_KEY}ein (einen beliebigen nicht leeren String, wenn auf Ihrem Server keine Bearer-Authentifizierung erzwungen wird, oder den API-Schlüssel Ihres Servers). - Native Funktionsaufrufe aktivieren: Aktivieren Sie den Ein/Aus-Button.
- Connector-Name: Geben Sie den Wert von
- Klicken Sie auf Speichern und testen, um den Connector zu speichern und sofort den Tab Test zu öffnen.
- Geben Sie auf dem Tab Test einen Beispiel-Prompt ein (z. B.
Reply with the single word Pong.) und klicken Sie auf Ausführen, um zu prüfen, ob Kibana eine gültige Antwort vom LLM-Dienst erhält.
LLM-Integrationen testen
Nachdem das Dataset kibana_sample_data_logs installiert und Ihr LLM-Connector verifiziert wurde, können Sie die KI-Funktionen von Elastic in Kibana testen.
Elastic KI-Agent
Der Elastic AI Agent (elastic-ai-agent) ist der standardmäßige Konversations-Agent, der in Kibana integriert ist, um Daten in Elasticsearch mithilfe natürlicher Sprache zu untersuchen und zu analysieren.
Der Agent wird von Ihrem konfigurierten LLM-Connector und den integrierten Agent Builder-Tools unterstützt. Er erkennt automatisch Elasticsearch-Indizes und ‑Zuweisungen (platform.core.list_indices, platform.core.get_index_mapping), generiert und führt ES|QL-Abfragen (platform.core.search, platform.core.execute_esql) aus und fasst Ergebnisse zusammen, ohne dass Sie das zugrunde liegende Schema im Voraus kennen müssen. Sie können auch eigene benutzerdefinierte Agenten mit maßgeschneiderten Anweisungen und Tools erstellen. Weitere Informationen finden Sie unter Benutzerdefinierte Agenten mit Agent Builder.
So öffnen und konfigurieren Sie den Elastic KI-Agenten in der Kibana-Benutzeroberfläche:
- Öffnen Sie das Hauptnavigationsmenü in Kibana und wählen Sie KI-Agent aus. Alternativ können Sie in der Kopfzeile oben auf die Schaltfläche Ask AI klicken oder direkt zu
https://${KIBANA_IP}:5601/app/chatnavigieren. - Achten Sie darauf, dass Elastic AI Agent als aktiver Agent und Ihr LLM-Connector (
${LLM_CONNECTOR_NAME}) als Modell-Connector ausgewählt ist.
Beispiel 1: Fehlgeschlagene HTTP-Anfragen und potenzielle Scanner untersuchen
Bitten Sie den Elastic KI-Agent, die wichtigsten Client-IP-Adressen zu identifizieren, die in kibana_sample_data_logs HTTP-Antworten generieren, die nicht 200 sind, sowie deren Herkunftsländer und ob für eine dieser IP-Adressen auch erfolgreicher HTTP-200-Traffic verzeichnet wurde:
Option 1: Über die Kibana-Benutzeroberfläche: Geben Sie die folgende Frage in den Chat-Prompt des KI-Agenten ein:
In kibana_sample_data_logs, which client IP addresses had the most failed HTTP requests (non-200 status codes), what countries did they come from, and did any of those IPs also have successful HTTP 200 requests?Option 2: Über die Befehlszeile:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/agent_builder/converse" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d "{ \"agent_id\": \"elastic-ai-agent\", \"connector_id\": \"${CONNECTOR_ID}\", \"input\": \"In kibana_sample_data_logs, which client IP addresses had the most failed HTTP requests (non-200 status codes), what countries did they come from, and did any of those IPs also have successful HTTP 200 requests?\" }" | jq '{ status: .status, tools_called: [.steps[] | select(.type == "tool_call") | {tool_id: .tool_id, params: .params}], response: .response.message }'
Was passiert hinter den Kulissen:
- Der KI-Agent ruft
platform.core.get_index_mapping(indices=["kibana_sample_data_logs"])auf, um die verfügbaren Felder (clientip,geo.src,response,bytes,requestusw.) zu prüfen. Es ruft
platform.core.searchauf, um Beispieldokumente zu prüfen und zu bestätigen, dass HTTP-Statuscodes inresponsegespeichert sind. Anschließend werden ES|QL-Aggregationen ausgeführt, um Nicht-200-Anfragen nachclientipundgeo.srczu sortieren und zu prüfen, welche der Top-IPs auchresponse == "200"-Traffic aufgezeichnet haben:FROM kibana_sample_data_logs | WHERE response != "200" | STATS failed_count = COUNT(*) BY clientip, geo.src | SORT failed_count DESC | LIMIT 10FROM kibana_sample_data_logs | WHERE clientip IN ("30.156.16.164", "213.235.30.99", "221.241.228.46", "209.94.234.133", "7.127.73.138", "247.240.202.244", "130.125.65.24", "164.85.94.243", "81.194.200.150", "30.145.143.210") AND response == "200" | STATS success_count = COUNT(*) BY clientip
Die Antwort des Elastic KI-Agenten sollte in etwa so aussehen:
Die Client-IP-Adresse mit den meisten fehlgeschlagenen HTTP-Anfragen (Statuscodes ungleich 200) in
kibana_sample_data_logsist 30.156.16.164. Sie stammt aus den USA und hat 100 fehlgeschlagene Anfragen verzeichnet.Andere Top-IP-Adressen mit fehlgeschlagenen Anfragen, die ebenfalls aus den USA stammen, sind:
- 213.235.30.99: 6 Fehler
- 221.241.228.46: 6 Fehler
- 209.94.234.133: 6 Fehler
- 7.127.73.138: 5 Fehler
- 247.240.202.244: 5 Fehler
- 130.125.65.24: 5 Fehler
- 164.85.94.243: 4 Fehler
- 81.194.200.150: 4 Fehler
- 30.145.143.210: 4 Fehler
Bei erfolgreichen Anfragen hatten alle oben aufgeführten IP-Adressen mindestens einige erfolgreiche HTTP 200-Antworten, mit Ausnahme von 30.156.16.164, die keine erfolgreichen Anfragen hatte.
Beispiel 2: Trafficvolumen und Nutzlastbyte nach HTTP-Statuscode analysieren
Fragen Sie den Elastic KI-Agent nach der Aufschlüsselung der HTTP-Antwortstatuscodes für alle Anfragen in kibana_sample_data_logs und der Gesamtzahl der übertragenen Byte für jeden Statuscode:
Option 1: Über die Kibana-Benutzeroberfläche: Starten Sie eine neue Unterhaltung im KI-Agenten und geben Sie die folgende Frage ein:
In kibana_sample_data_logs, what is the breakdown of HTTP response status codes across all requests, and how much total data (in bytes) was transferred for each status code?Option 2: Über die Befehlszeile:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/agent_builder/converse" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d "{ \"agent_id\": \"elastic-ai-agent\", \"connector_id\": \"${CONNECTOR_ID}\", \"input\": \"In kibana_sample_data_logs, what is the breakdown of HTTP response status codes across all requests, and how much total data (in bytes) was transferred for each status code?\" }" | jq '{ status: .status, tools_called: [.steps[] | select(.type == "tool_call") | {tool_id: .tool_id, params: .params}], response: .response.message }'
Was passiert hinter den Kulissen:
- Der Agent prüft das Schema
kibana_sample_data_logsüberplatform.core.get_index_mappingund identifiziert die Felderresponse.keywordundbytes. Es ruft
platform.core.searchauf, wodurch die folgende ES|QL-Aggregation generiert und ausgeführt wird:FROM kibana_sample_data_logs | STATS request_count = COUNT(*), total_bytes = SUM(bytes) BY response.keyword | LIMIT 100
Die Antwort des Elastic KI-Agenten sollte in etwa so aussehen:
Die Aufschlüsselung der HTTP-Antwortstatuscodes und der insgesamt in
kibana_sample_data_logsübertragenen Daten sieht so aus:
| Statuscode | Anzahl der Anfragen | Übertragene Daten insgesamt (Byte) |
|---|---|---|
| 200 | 12.832 | 75.681.246 |
| 404 | 801 | 4.044.443 |
| 503 | 441 | 0 |
Benutzerdefinierte KI-Agenten mit Agent Builder
Mit dem Agent Builder können Sie benutzerdefinierte KI-Agenten erstellen, die auf bestimmte operative Workflows zugeschnitten sind. Dazu kombinieren Sie benutzerdefinierte Systemanweisungen mit integrierten Tools (wie platform.core.cases, platform.core.execute_esql und platform.core.search) und benutzerdefinierten Tools (esql, index_search, workflow und mcp).
Im folgenden Beispiel wird ein Web Security Incident Responder-Agent erstellt, der direkt mit dem Dataset kibana_sample_data_logs arbeitet. Bei einem Prompt in natürlicher Sprache geht der Agent so vor:
- Führt ein benutzerdefiniertes ES|QL-Tool (
investigate_suspicious_web_clients) aus, um Nicht-200-HTTP-Antworten inkibana_sample_data_logsnach Client-IP zu aggregieren. - Unterscheidet schädliche Aufklärungs- und Exploiting-Aktivitäten (
30.156.16.164) von harmlosen Downloadfehlern. - Ruft ein benutzerdefiniertes Kibana-Workflow-Tool (
create_security_case) auf, um automatisch einen strukturierten Kibana-Sicherheitsfall mit den Ergebnissen und Abhilfemaßnahmen zu öffnen.
Benutzerdefinierte ES|QL- und Fallerstellungstools erstellen
Erstellen Sie ein benutzerdefiniertes
esql-Tool mit dem Nameninvestigate_suspicious_web_clients, daskibana_sample_data_logsnach den wichtigsten Client-IP-Adressen abfragt, die HTTP-Statuscodes ungleich200generieren, zusammen mit ihren Statuscodes, dem Ursprungsland (geo.src), den User Agents (agent) und den angeforderten URLs (request):Option 1: Über die Kibana-Benutzeroberfläche:
- Öffnen Sie in Kibana das Hauptnavigationsmenü und rufen Sie Elasticsearch > Agents auf. Klicken Sie dann auf Alle Tools verwalten (oder rufen Sie direkt
https://${KIBANA_IP}:5601/app/agent_builder/toolsauf) und klicken Sie auf Neues Tool. Konfigurieren Sie die Tool-Felder:
- Tool-ID:
investigate_suspicious_web_clients - Typ: ES|QL
- Description:
Finds the top client IP addresses generating non-200 HTTP error responses in kibana_sample_data_logs, returning their error count, status codes, source country, user agents, and requested URL paths. - Labels:
security,logs ES|QL-Abfrage:
FROM kibana_sample_data_logs | WHERE response != "200" | STATS error_count = COUNT(*), status_codes = VALUES(response), country = VALUES(geo.src), user_agents = VALUES(agent), sample_requests = VALUES(request) BY clientip | SORT error_count DESC | LIMIT 5
- Tool-ID:
Klicken Sie auf Speichern.
- Öffnen Sie in Kibana das Hauptnavigationsmenü und rufen Sie Elasticsearch > Agents auf. Klicken Sie dann auf Alle Tools verwalten (oder rufen Sie direkt
Option 2: Über die Befehlszeile:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/agent_builder/tools" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d '{ "id": "investigate_suspicious_web_clients", "type": "esql", "description": "Finds the top client IP addresses generating non-200 HTTP error responses in kibana_sample_data_logs, returning their error count, status codes, source country, user agents, and requested URL paths.", "tags": ["security", "logs"], "configuration": { "query": "FROM kibana_sample_data_logs | WHERE response != \"200\" | STATS error_count = COUNT(*), status_codes = VALUES(response), country = VALUES(geo.src), user_agents = VALUES(agent), sample_requests = VALUES(request) BY clientip | SORT error_count DESC | LIMIT 5", "params": {} } }' | jq '{id: .id, type: .type}'
Da das integrierte
platform.core.cases-Tool von Agent Builder schreibgeschützt ist (zum Suchen und Abrufen vorhandener Fälle), erstellen Sie einen Kibana-Workflow (create-security-case), der den nativencases.createCase-Schritt von Kibana aufruft, und registrieren Sie ihn alsworkflow-Tool mit dem Namencreate_security_case:Option 1: Über die Kibana-Benutzeroberfläche:
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Verwaltung > Workflows auf (oder rufen Sie direkt
https://${KIBANA_IP}:5601/app/workflowsauf) und klicken Sie dann auf Neuen Workflow erstellen. Fügen Sie im YAML-Editor die folgende Workflowdefinition ein und klicken Sie auf Speichern:
version: "1" name: Create Security Case description: Creates a new Kibana Case in Elastic Security enabled: true triggers: - type: manual inputs: - name: title type: string required: true description: Title of the security case - name: description type: string required: true description: Detailed markdown description of the incident findings - name: severity type: string default: high description: Severity of the case (low, medium, high, critical) steps: - name: create_case type: cases.createCase with: title: ${{ inputs.title }} description: ${{ inputs.description }} severity: ${{ inputs.severity }} owner: securitySolution tags: - agent-builder - web-logsKehren Sie zur Seite Tools im Agent Builder zurück (
https://${KIBANA_IP}:5601/app/agent_builder/toolsoder rufen Sie Elasticsearch > Agenten auf und klicken Sie auf Alle Tools verwalten) und klicken Sie auf Neues Tool.Konfigurieren Sie die Felder des Workflow-Tools und klicken Sie auf Speichern:
- Tool-ID:
create_security_case - Typ: Workflow
- Workflow: Wählen Sie Create Security Case (
create-security-case) aus. - Description:
Creates a new Kibana Case in Elastic Security with a title, markdown description of the incident findings, and severity (low, medium, high, critical). - Labels:
security,cases
- Tool-ID:
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Verwaltung > Workflows auf (oder rufen Sie direkt
Option 2: Über die CLI:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/workflows" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d '{ "workflows": [ { "yaml": "version: \"1\"\nname: Create Security Case\ndescription: Creates a new Kibana Case in Elastic Security\nenabled: true\ntriggers:\n - type: manual\ninputs:\n - name: title\n type: string\n required: true\n description: Title of the security case\n - name: description\n type: string\n required: true\n description: Detailed markdown description of the incident findings\n - name: severity\n type: string\n default: high\n description: Severity of the case (low, medium, high, critical)\nsteps:\n - name: create_case\n type: cases.createCase\n with:\n title: ${{ inputs.title }}\n description: ${{ inputs.description }}\n severity: ${{ inputs.severity }}\n owner: securitySolution\n tags:\n - agent-builder\n - web-logs\n" } ] }' | jq '.created[] | {id: .id, valid: .valid}' curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/agent_builder/tools" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d '{ "id": "create_security_case", "type": "workflow", "description": "Creates a new Kibana Case in Elastic Security with a title, markdown description of the incident findings, and severity (low, medium, high, critical).", "tags": ["security", "cases"], "configuration": { "workflow_id": "create-security-case" } }' | jq '{id: .id, type: .type}'
Benutzerdefinierten Incident Responder-Agenten erstellen
Erstellen Sie den KI-Agenten web-security-incident-responder und weisen Sie ihm die Tools investigate_suspicious_web_clients, create_security_case und platform.core.cases zu:
Option 1: Über die Kibana-Benutzeroberfläche:
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Elasticsearch > Agents auf (oder rufen Sie direkt
https://${KIBANA_IP}:5601/app/agent_builder/agentsauf) und klicken Sie dann auf New agent (Neuer Agent). Konfigurieren Sie die Agentendetails:
- Agenten-ID:
web-security-incident-responder - Display name (Anzeigename):
Web Security Incident Responder. - Display description (Anzeigename):
Investigates suspicious HTTP error activity in web access logs and opens Kibana Security Cases with the findings. - Labels:
security,incident-response Benutzerdefinierte Anweisungen:
You are an automated Web Security Incident Responder. When asked to investigate suspicious web traffic: 1. Call the `investigate_suspicious_web_clients` tool to inspect the top client IPs generating non-200 HTTP responses in `kibana_sample_data_logs`. 2. Identify any client IP exhibiting malicious reconnaissance or exploitation behavior (such as Nmap scans, WordPress login probing, `/etc/passwd` path traversal, or `/level/15/exec` command execution attempts) versus benign download errors. 3. Call the `create_security_case` tool to open a new Kibana Security Case for the malicious client IP. Set an appropriate `title`, `severity` (`high`), and a well-structured Markdown `description` summarizing the source IP, geolocation, total failed requests, observed attack categories (mapped to MITRE ATT&CK where applicable), sample malicious URLs, and recommended remediation steps. 4. Return a concise summary of your investigation and confirm the created Kibana Case details.Tools: Wählen Sie
investigate_suspicious_web_clients,create_security_caseundplatform.core.casesaus.
- Agenten-ID:
Klicken Sie auf Speichern.
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Elasticsearch > Agents auf (oder rufen Sie direkt
Option 2: Über die CLI:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/agent_builder/agents" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d '{ "id": "web-security-incident-responder", "name": "Web Security Incident Responder", "description": "Investigates suspicious HTTP error activity in web access logs and opens Kibana Security Cases with the findings.", "labels": ["security", "incident-response"], "avatar_color": "#E7664C", "avatar_symbol": "IR", "configuration": { "instructions": "You are an automated Web Security Incident Responder. When asked to investigate suspicious web traffic:\n1. Call the `investigate_suspicious_web_clients` tool to inspect the top client IPs generating non-200 HTTP responses in `kibana_sample_data_logs`.\n2. Identify any client IP exhibiting malicious reconnaissance or exploitation behavior (such as Nmap scans, WordPress login probing, `/etc/passwd` path traversal, or `/level/15/exec` command execution attempts) versus benign download errors.\n3. Call the `create_security_case` tool to open a new Kibana Security Case for the malicious client IP. Set an appropriate `title`, `severity` (`high`), and a well-structured Markdown `description` summarizing the source IP, geolocation, total failed requests, observed attack categories (mapped to MITRE ATT&CK where applicable), sample malicious URLs, and recommended remediation steps.\n4. Return a concise summary of your investigation and confirm the created Kibana Case details.", "tools": [ { "tool_ids": [ "investigate_suspicious_web_clients", "create_security_case", "platform.core.cases" ] } ] } }' | jq '{id: .id, name: .name}'
Agenten ausführen und Kibana-Fall prüfen
So führen Sie eine Unterhaltung mit dem Web Security Incident Responder-Agenten:
Option 1: Über die Kibana-Benutzeroberfläche:
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Elasticsearch > Agents auf oder rufen Sie direkt
https://${KIBANA_IP}:5601/app/agent_builderauf. - Wählen Sie in der Agentenauswahl Web Security Incident Responder aus und achten Sie darauf, dass Ihr LLM-Connector (
${LLM_CONNECTOR_NAME}) ausgewählt ist. Geben Sie den folgenden Prompt ein:
Investigate the top client IPs generating HTTP errors in our web logs, identify any attacker performing reconnaissance or exploitation, and open a high-severity Kibana Security Case with your findings.
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Elasticsearch > Agents auf oder rufen Sie direkt
Option 2: Über die CLI:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/agent_builder/converse" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d "{ \"agent_id\": \"web-security-incident-responder\", \"connector_id\": \"${CONNECTOR_ID}\", \"input\": \"Investigate the top client IPs generating HTTP errors in our web logs, identify any attacker performing reconnaissance or exploitation, and open a high-severity Kibana Security Case with your findings.\" }" | jq '{ status: .status, tools_called: [.steps[] | select(.type == "tool_call") | .tool_id], response: .response.message }'Die Ausgabe sollte in etwa so aussehen:
{ "status": "completed", "tools_called": [ "investigate_suspicious_web_clients", "create_security_case" ], "response": "I have completed the investigation into the web logs. \n\nThe analysis identified client IP **`30.156.16.164`** (located in the US) as a malicious actor. This IP generated 100 failed requests (HTTP 404) exhibiting clear patterns of reconnaissance and exploitation:\n\n* **Reconnaissance:** Extensive probing for WordPress installations and plugins, as well as Nmap scan signatures (e.g., `/nmaplowercheck...`).\n* **Path Traversal:** Attempts to access sensitive system files via `/etc/passwd`.\n* **Remote Command Execution (RCE):** Attempts to execute commands through paths such as `/level/15/exec`.\n* **Application Probing:** Targeting common management interfaces including Tomcat, Axis2, and JMX consoles.\n\nAs a result, I have opened a **high-severity** Kibana Security Case to track this incident:\n\n* **Case ID:** `1f0e00a5-cc89-4f62-b305-f286fae3d70e`\n* **Title:** Malicious Reconnaissance and Exploitation Attempt from 30.156.16.164\n* **Recommended Action:** Immediately block the IP at the firewall/WAF and verify that no unauthorized access was achieved." }
Prüfen Sie den neu erstellten Kibana-Sicherheitsfall:
Option 1: Über die Kibana-Benutzeroberfläche:
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Sicherheit > Fälle auf (oder rufen Sie direkt
https://${KIBANA_IP}:5601/app/security/casesauf). - Klicken Sie auf Malicious Reconnaissance and Exploitation Attempt from 30.156.16.164, um die formatierte Markdown-Zusammenfassung des Vorfalls, die MITRE ATT&CK-Analyse, Beispiele für schädliche URLs und die Checkliste zur Problembehebung aufzurufen.
- Öffnen Sie das Hauptnavigationsmenü und rufen Sie Sicherheit > Fälle auf (oder rufen Sie direkt
Option 2: Über die Befehlszeile:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ "https://${KIBANA_IP}:5601/api/cases/_find" \ -H "kbn-xsrf: true" \ | jq '.cases[0] | {id: .id, title: .title, severity: .severity, status: .status, tags: .tags, description: .description}'Die Ausgabe sollte in etwa so aussehen:
{ "id": "1f0e00a5-cc89-4f62-b305-f286fae3d70e", "title": "Malicious Reconnaissance and Exploitation Attempt from 30.156.16.164", "severity": "high", "status": "open", "tags": [ "agent-builder", "web-logs" ], "description": "### Incident Summary\n**Source IP:** `30.156.16.164`\n**Geolocation:** US\n**Total Failed Requests:** 100\n**Status Codes Observed:** 404\n\n### Analysis\nThe client IP exhibited clear patterns of malicious reconnaissance and exploitation attempts:\n\n- **Reconnaissance (MITRE ATT&CK T1595):** Extensive probing for WordPress installations (`/wp-login.php`, various plugin paths) and Nmap scan signatures (`/nmaplowercheck...`).\n- **Path Traversal (MITRE ATT&CK T1083):** Attempted to access sensitive system files via `/cgi-bin/mj_wwwusr?passw=&list=GLOBAL&user=&func=help&extra=/../../../../../../../../etc/passwd`.\n- **Remote Command Execution (MITRE ATT&CK T1203):** Attempts to execute commands via paths like `/level/15/exec/-/configure/http`.\n- **Application Probing:** Targeted common management interfaces such as `/tomcat/manager/html/`, `/axis2/axis2-admin/`, and `/jmx-console/`.\n\n### Sample Malicious URLs\n- `/cgi-bin/mj_wwwusr?passw=&list=GLOBAL&user=&func=help&extra=/../../../../../../../../etc/passwd`\n- `/level/15/exec/-/configure/http`\n- `/nmaplowercheck1331872976`\n- `/wp-login.php`\n\n### Recommended Remediation\n1. **Block IP:** Immediately block `30.156.16.164` at the network firewall/WAF.\n2. **Log Review:** Verify that all requests from this IP resulted in 404 errors and no unauthorized access was gained.\n3. **Hardening:** Ensure that sensitive directories (e.g., `/cgi-bin/`, `/manager/`) are properly restricted." }
Angriffserkennung
Attack Discovery ist eine KI-Funktion in Elastic Security, die offene Sicherheitswarnungen analysiert, sie dem MITRE ATT&CK-Framework zuordnet und zugehörige Warnungen, IP-Adressen und Nutzerkonten in visuelle Angriffsketten korreliert. Da für Attack Discovery ein großes Modell erforderlich ist, um strukturierte JSON-Ausgaben mit mehreren Benachrichtigungen zuverlässig zu synthetisieren, sollten Sie ein Modell der 30B-Klasse oder größer (z. B. gemma4:31b) verwenden.
Sicherheitswarnungen aus den Beispielprotokollen generieren
Standardmäßig enthält das Dataset kibana_sample_data_logs Rohprotokolle für den Webzugriff und füllt nicht den Elastic Security-Warnungsindex (.alerts-security.alerts-default) aus. Darüber hinaus weist der Beispieldatengenerator von Kibana den 100 Scan- und Exploitanfragen von 30.156.16.164 zukünftige @timestamp-Werte (bis zu 30 Tage im Voraus) zu, sodass sie außerhalb des Zeitfensters von now-30d bis now liegen, das von den Elastic Security-Erkennungsregeln abgefragt wird.
Wenn Sie die Angriffserkennung mit den Beispielprotokollen demonstrieren möchten, verschieben Sie die @timestamp der Datensätze von 30.156.16.164 um 30 Tage zurück, reichern Sie sie mit den Elastic Common Schema (ECS)-Feldern source.ip und user.name an und erstellen Sie zwei Erkennungsregeln, die Sicherheitswarnungen aus diesen Ereignissen generieren:
Ordnen Sie
clientipsource.ipzu, legen Sieuser.name(www-data) fest und verschieben Sie@timestampfür die30.156.16.164-Einträge inkibana_sample_data_logs*um 30 Tage zurück:curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${ELASTICSEARCH_IP}:9200/kibana_sample_data_logs*/_update_by_query?conflicts=proceed&refresh=true" \ -H "Content-Type: application/json" \ -d '{ "query": { "term": { "clientip": "30.156.16.164" } }, "script": { "source": "ctx._source.source = [\"ip\": ctx._source.clientip]; ctx._source.user = [\"name\": \"www-data\"]; ctx._source[\"@timestamp\"] = ZonedDateTime.parse(ctx._source[\"@timestamp\"]).minusDays(30).toString();", "lang": "painless" } }' | jq '{updated: .updated, failures: .failures}'Erstellen Sie zwei Elastic Security-Erkennungsregeln für
kibana_sample_data_logs*. Die erste Regel erkennt Nmap- und WordPress-Anmeldeversuche (Reconnaissance) und die zweite Regel erkennt/etc/passwd-Pfaddurchlauf- und Remote-Befehlsausführungsversuche (Initial Access):curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/detection_engine/rules" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d '{ "name": "Suspicious Web Reconnaissance and Vulnerability Scanning", "description": "Detects Nmap active scanning and WordPress login/plugin probing in web access logs.", "risk_score": 47, "severity": "medium", "type": "query", "language": "kuery", "query": "clientip: \"30.156.16.164\" and (request: *nmap* or request: *wp-login*)", "index": ["kibana_sample_data_logs*"], "from": "now-30d", "interval": "1h", "max_signals": 2, "enabled": true, "threat": [ { "framework": "MITRE ATT&CK", "tactic": { "id": "TA0043", "name": "Reconnaissance", "reference": "https://attack.mitre.org/tactics/TA0043/" }, "technique": [ { "id": "T1595", "name": "Active Scanning", "reference": "https://attack.mitre.org/techniques/T1595/" } ] } ] }' | jq '{id: .id, name: .name, enabled: .enabled}' curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ -X POST "https://${KIBANA_IP}:5601/api/detection_engine/rules" \ -H "kbn-xsrf: true" \ -H "Content-Type: application/json" \ -d '{ "name": "Web Path Traversal and Remote Command Execution Attempt", "description": "Detects path traversal attempts targeting /etc/passwd and Cisco IOS privilege level 15 remote command execution (/level/15/exec).", "risk_score": 73, "severity": "high", "type": "query", "language": "kuery", "query": "clientip: \"30.156.16.164\" and (request: *passwd* or request: *exec*)", "index": ["kibana_sample_data_logs*"], "from": "now-30d", "interval": "1h", "max_signals": 2, "enabled": true, "threat": [ { "framework": "MITRE ATT&CK", "tactic": { "id": "TA0001", "name": "Initial Access", "reference": "https://attack.mitre.org/tactics/TA0001/" }, "technique": [ { "id": "T1190", "name": "Exploit Public-Facing Application", "reference": "https://attack.mitre.org/techniques/T1190/" } ] } ] }' | jq '{id: .id, name: .name, enabled: .enabled}'Warten Sie etwa 60 Sekunden, bis die erste Regelausführung abgeschlossen ist, und prüfen Sie dann, ob 4 Benachrichtigungen in
.alerts-security.alerts-defaultindexiert wurden:curl -sk -u "elastic:${ELASTIC_PASSWORD}" \ "https://${ELASTICSEARCH_IP}:9200/.alerts-security.alerts-default/_search?size=4" \ | jq '.hits.hits[]._source | {rule: .["kibana.alert.rule.name"], source_ip: .source.ip, user_name: .user.name, request: .request}'Die Ausgabe sollte in etwa so aussehen:
{ "rule": "Web Path Traversal and Remote Command Execution Attempt", "source_ip": "30.156.16.164", "user_name": "www-data", "request": "/cgi-bin/mj_wwwusr?passw=&list=GLOBAL&user=&func=help&extra=/../../../../../../../../etc/passwd" } { "rule": "Web Path Traversal and Remote Command Execution Attempt", "source_ip": "30.156.16.164", "user_name": "www-data", "request": "/cgi-bin/mj_wwwusr?passw=&list=GLOBAL&user=&func=help&extra=/../../../../../../../../etc/passwd" } { "rule": "Suspicious Web Reconnaissance and Vulnerability Scanning", "source_ip": "30.156.16.164", "user_name": "www-data", "request": "/nmaplowercheck1331872976" } { "rule": "Suspicious Web Reconnaissance and Vulnerability Scanning", "source_ip": "30.156.16.164", "user_name": "www-data", "request": "/nmaplowercheck1331873003" }
Angriffserkennung ausführen
- Öffnen Sie in Kibana das Hauptnavigationsmenü und rufen Sie Sicherheit > Angriffserkennung auf oder rufen Sie direkt
https://${KIBANA_IP}:5601/app/security/attack_discoveryauf. - Wählen Sie im Connector-Menü oben auf der Seite Ihren LLM-Connector (
${LLM_CONNECTOR_NAME}) aus. - Klicken Sie auf Generieren, um die offenen Benachrichtigungen in
.alerts-security.alerts-defaultzu analysieren.
Sie können Attack Discovery auch über die Befehlszeile auslösen und prüfen:
export EXECUTION_UUID=$(curl -sk -u "elastic:${ELASTIC_PASSWORD}" \
-X POST "https://${KIBANA_IP}:5601/api/attack_discovery/_generate" \
-H "kbn-xsrf: true" \
-H "elastic-api-version: 2023-10-31" \
-H "Content-Type: application/json" \
-d "{
\"alertsIndexPattern\": \".alerts-security.alerts-default\",
\"anonymizationFields\": [
{\"id\": \"_id\", \"field\": \"_id\", \"allowed\": true},
{\"id\": \"@timestamp\", \"field\": \"@timestamp\", \"allowed\": true},
{\"id\": \"kibana.alert.original_time\", \"field\": \"kibana.alert.original_time\", \"allowed\": true},
{\"id\": \"message\", \"field\": \"message\", \"allowed\": true},
{\"id\": \"kibana.alert.rule.name\", \"field\": \"kibana.alert.rule.name\", \"allowed\": true},
{\"id\": \"kibana.alert.rule.description\", \"field\": \"kibana.alert.rule.description\", \"allowed\": true},
{\"id\": \"kibana.alert.severity\", \"field\": \"kibana.alert.severity\", \"allowed\": true},
{\"id\": \"kibana.alert.risk_score\", \"field\": \"kibana.alert.risk_score\", \"allowed\": true},
{\"id\": \"kibana.alert.rule.threat.tactic.id\", \"field\": \"kibana.alert.rule.threat.tactic.id\", \"allowed\": true},
{\"id\": \"kibana.alert.rule.threat.tactic.name\", \"field\": \"kibana.alert.rule.threat.tactic.name\", \"allowed\": true},
{\"id\": \"kibana.alert.rule.threat.technique.id\", \"field\": \"kibana.alert.rule.threat.technique.id\", \"allowed\": true},
{\"id\": \"kibana.alert.rule.threat.technique.name\", \"field\": \"kibana.alert.rule.threat.technique.name\", \"allowed\": true},
{\"id\": \"source.ip\", \"field\": \"source.ip\", \"allowed\": true},
{\"id\": \"user.name\", \"field\": \"user.name\", \"allowed\": true}
],
\"apiConfig\": {
\"actionTypeId\": \".gen-ai\",
\"connectorId\": \"${CONNECTOR_ID}\"
},
\"replacements\": {},
\"size\": 20,
\"subAction\": \"invokeAI\"
}" | jq -r '.execution_uuid')
echo "Attack Discovery execution UUID: ${EXECUTION_UUID}"
Sobald die Generierung abgeschlossen ist (ca. 60–90 Sekunden), rufen Sie die erkannte Angriffskette ab:
curl -sk -u "elastic:${ELASTIC_PASSWORD}" \
"https://${KIBANA_IP}:5601/api/attack_discovery/_find" \
-H "kbn-xsrf: true" \
-H "elastic-api-version: 2023-10-31" \
| jq '.data[0]'
Die generierte Angriffserkennung korreliert die vier Warnungen zu einem einzigen Vorfall mit verknüpfter Quell-IP, Nutzerkonto und MITRE ATT&CK-Taktiken:
{
"alert_ids": [
"05c30118398ea2a8b70c55ce81fdb559dbe14c460a8a95253bd81719415a28b5",
"73ebaeca440b463ffa5812da5b68a2485d465a648ffaf16385a54d8bae9a53d2",
"60ae9f16b40cec1bdc27674ade0e5eb69680ccca3d956fbf2a75418843799987",
"de503ae52444db7712d062c54750f413b90a75521cdfff0de9bdf41a64141346"
],
"alert_rule_uuid": "attack_discovery_ad_hoc_rule_id",
"alert_start": "2026-10-03T01:05:00.384Z",
"alert_updated_at": "2026-10-03T01:05:03.460Z",
"alert_workflow_status": "open",
"alert_workflow_status_updated_at": "2026-10-03T01:05:03.460Z",
"connector_id": "<GENERATED_CONNECTOR_ID>",
"connector_name": "<GENERATED_CONNECTOR_ID>",
"details_markdown": "- The attack sequence began at `2026-10-01T12:43:41.756Z` when an actor using IP `30.156.16.164` performed active reconnaissance scanning against the server.\n- Following the initial scan, the attacker attempted to exploit a path traversal vulnerability at `2026-10-01T12:43:51.756Z` and again at `2026-10-01T12:44:02.756Z`, specifically targeting the `/etc/passwd` file via the `mj_wwwusr` CGI endpoint.\n- The activity concluded with further reconnaissance scanning at `2026-10-01T12:44:21.756Z` from the same source IP `30.156.16.164`.\n- All requests were associated with the user `www-data` and resulted in 404 errors, suggesting the attempts were unsuccessful.",
"entity_summary_markdown": "Activity targeting user `www-data` from source IP `30.156.16.164`.",
"generation_uuid": "<EXECUTION_UUID>",
"id": "1f71ed004c7340d5088d242ca2483525a164a9ea9a80a3f90bd1f514d43231bc",
"mitre_attack_tactics": [
"Reconnaissance",
"Initial Access"
],
"risk_score": 240,
"summary_markdown": "An attacker from `30.156.16.164` performed reconnaissance and path traversal attempts against the system.",
"timestamp": "2026-10-03T01:05:00.384Z",
"title": "Web Reconnaissance and Exploitation Attempt",
"user_id": "elastic",
"user_name": "elastic",
"users": [
{
"id": "elastic",
"name": "elastic"
}
],
"index": ".internal.adhoc.alerts-security.attack.discovery.alerts-default-000001"
}