TECH PLAY

サイオステクノロジー((DXSL))

サイオステクノロジー((DXSL)) の技術ブログ

77

Jina v5 Omni × Agent Builder × MCP で組み立てるマルチモーダル画像検索 PoC 📦 ソースコード : GitHub リポジトリ 14 枚の写真を Elastic に登録するだけで、Kibana のチャットから 「青い椅子の写真を見せて」 と日本語で問いかけると、本当に青い椅子が写った写真が返ってくる。 しかも フロントエンドコードはゼロ行 。Python 300 行と Elastic Cloud のクリック数回で完成します。 このブログでは、その PoC をどう組み立てたか、ステップ・バイ・ステップで紹介します。 目次 1. 実装する 3 つの検索モード 完成形の応答イメージ 想定読者 所要時間の目安 2. なぜ作ったか 自前構成と Serverless で、どこに差が出るのか 3. 全体アーキテクチャ 3-1. コンポーネントの全体図 3-2. 5 つのコンポーネントの役割 4. 準備するもの アカウント (すべて無料枠で OK) ローカル環境 (macOS 想定) 画像 Phase 0 — 環境準備 0-1. プロジェクトの構成 0-2. Elastic Cloud Serverless プロジェクトを作る 0-3. ELASTIC_URL を取得する 0-4. ELASTIC_API_KEY を作る 0-5. AWS IAM ユーザーを準備 0-6. .env を作る 0-7. 環境チェック Phase 1 — S3 バケットを作る ここで押さえたいキーワード: SSE-S3 とは Phase 2 — Elastic インデックスを作る マッピング (フィールド定義) ここで押さえたいキーワード ① — dense_vector ここで押さえたいキーワード ② — alias Phase 3 — 画像を ingest する ここで押さえたいキーワード ① — embedding (埋め込み) ここで押さえたいキーワード ② — content block 形式 Python の実装 ⚠️ よくある罠 — 画像 URL を文字列として送る Phase 4 — CLI で検索を試す ここで押さえたいキーワード ① — kNN (k-Nearest Neighbors) ここで押さえたいキーワード ② — query_vector_builder query_vector_builder.lookup — 画像 → 類似画像検索 ここで押さえたいキーワード ③ — Pre-signed URL Phase 5 — Agent Builder + MCP でチャット化 ここで押さえたいキーワード ① — Agent Builder ここで押さえたいキーワード ② — MCP (Model Context Protocol) Agent Builder のツールの 4 種類 5-1. MCP server を書く 5-2. ngrok でトンネルを開く 5-3. 2 ターミナル運用 ターミナル A: ngrok を起動 ターミナル B: MCP server を起動 (コード変更ごと) 5-4. Kibana 側: エージェントを作る 5-5. Kibana 側: MCP コネクタを登録 Authorization の値の作り方 ngrok-skip-browser-warning が必要な理由 5-6. ツールをエージェントに有効化 5-7. チャットで動作確認 ハマったところ TOP 4 罠 ①. 画像 URL をテキストとして送って 3 時間溶かした 罠 ②. semantic_text フィールドに画像を入れたら大失敗 罠 ③. Kibana チャットで画像がインライン表示できない 罠 ④. ngrok を再起動したら「Failed to load tools」が再発した 運用 — 起動と停止のステップ 始めるとき コードを編集したら 仕事終わり 次のステップ 5-1. データセットに無い画像から類似画像を探す (リバース画像検索) 5-2. OCR と組み合わせて「画像内文字」検索の精度を上げる 5-3. その他 まとめ ソースコード・詳細手順 参考リンク 1. 実装する 3 つの検索モード ユーザーが入力する言葉 動き 「青い椅子の写真」 意味的に近い画像 上位 3 件 「IMG_8133.jpeg に似た画像」 既存画像から視覚的に似た画像 上位 3 件 「’RIDE’ と書かれた画像」 画像内の文字が一致するっぽい画像 上位 3 件 完成形の応答イメージ ⚠️ スコア表示の読み方について — 「類似度 60.60%」は確率ではありません 応答例とスクリーンショットでは 「類似度 60.60%」 のように % 付きで表示されていますが、これは見た目の都合でそうしているだけで、AI の正解確率や信頼度ではありません。 これは Elasticsearch の kNN が、選んだ similarity metric (本 PoC では cosine ) から計算する ランキング用のスコア です。 cosine similarity の場合、内部的には次のように正規化されます。 _score = (1 + cos(θ)) / 2 ← 範囲 [0, 1] 表示値 = _score × 100 ← 0〜100 の数字 想定読者 Python と HTTP API に慣れている開発者 Elasticsearch の基本 (index, search) は知っていても OK / 知らなくても OK ベクトル検索やマルチモーダル AI に「触ってみたい」と思っている人 技術用語は登場する順に、その場で説明する形にしてある。 所要時間の目安 環境準備 (アカウント・キー作成) … 30〜60 分 実装と動作確認 … 2〜3 時間 Agent Builder のセットアップ … 2〜3 時間 合計 半日〜1 日 で動かせます。 2. なぜ作ったか きっかけは 3 つありました。 以前試していた画像検索を、今度は Jina の Omni モデルでどう作れるか見てみたかった。 Agent Builder にこの検索ロジックを乗せられるかを知りたかった。 日本語の指示も理解してくれるか、本当に試したかった。 この 3 つを一気に検証できる最小構成として、本 PoC を作りました。結果としては、 Jina v5 Omni + query_vector_builder + Agent Builder + MCP の組み合わせで、 フロントエンドコード 0 行・Python 約 300 行 で日本語チャット画像検索が成立することを確認できました。 自前構成と Serverless で、どこに差が出るのか この構成を自前で作ると、何が大変になるのか ここで比較したいのは、単純な「OSS か、有料か」ではありません。もう少し正確に言うと、次の 3 つの違いです。 自前サーバー + 無償中心の Elastic 自前サーバー + Elastic の有償エディション / サブスクリプション Elastic Cloud Serverless 検索クエリの考え方だけを見ると、 dense_vector 、kNN、Inference API、 query_vector_builder  などを組み合わせる構成は、どの方式でも近い形にできます。 ただし、本当に差が出るのは「検索クエリを書けるか」ではありません。 差が出るのは、モデル、エージェント、UI、アップグレード、運用責任を誰が持つか です。 違いを整理すると、次のようになります。 ※ Elastic Cloud Hosted については説明を省略します 観点 自前サーバー + 無償中心の Elastic 自前サーバー + 有償エディション / サブスクリプション Elastic Cloud Serverless Elasticsearch / Kibana の運用 サーバー、OS、Docker / VM、Elasticsearch、Kibana、証明書、バックアップ、監視、アップグレードを自分で管理する 基本的なサーバー運用は自分で行う。ただし、有償機能やサポート、Cloud Connect などを使える選択肢が増える Elastic が基盤を管理する。ユーザーはノード数、シャード設計、クラスタアップグレードなどを強く意識せずに使える Jina v5 Omni などの AI モデル利用 外部推論サービスを別途使う、または自分でモデルをホストする必要がある。自前ホストの場合は GPU / CPU、推論サーバー、ライブラリ、モデル更新も自分で管理する Enterprise などの条件を満たせば、Cloud Connect 経由で Elastic Inference Service を使える選択肢がある。ただし self-managed cluster 自体の運用責任は残る Elastic Cloud 側で用意された Elastic Inference Service を zero setup で使える。今回のような PoC では、GPU や推論サーバーを自分で用意しなくてよい LLM チャット / エージェント LangChain、LlamaIndex、自作アプリなどでエージェントランタイムを作る必要がある。UI も Streamlit / Gradio / React などで自作することになる 有償機能により Agent Builder や EIS 連携を使える可能性があるが、構成やライセンス条件の確認が必要 Agent Builder と Kibana のチャット UI を使える。今回の PoC では、フロントエンドコードを書かずにチャット型の画像検索を作れた MCP server の接続 MCP client 側の実装、認証、エラーハンドリング、ツール呼び出し制御を自分で作る必要がある Agent Builder が使える構成なら、MCP 連携を Elastic 側の UI に寄せられる Manage MCP の画面から URL と HTTP ヘッダーを設定し、MCP server のツールを Agent Builder に取り込める アップグレード対応 Elasticsearch / Kibana、推論サーバー、AI モデル、Python ライブラリ、アプリ UI を自分で追いかける必要がある。AI モデルの進化が速いほど、継続的な検証と更新が重くなる 有償サポートや Cloud Connect によって一部の負担は減らせるが、self-managed cluster のアップグレード計画や検証は基本的に自分側に残る Serverless では Elastic が管理する基盤やプロジェクトコンポーネントのアップグレードを担当するため、アップデート追従の負担を大きく減らせる。ただし、自分で作った MCP server、Python コード、外部アプリ、ingest コンポーネントは自分で更新する必要がある 向いている使い方 技術検証、学習、コストを抑えた小規模 PoC 自社インフラ要件があるが、有償機能やサポートも使いたい場合 すばやく PoC を作り、その後も運用負荷を抑えながら AI 機能を使いたい場合 AI モデルの進化は非常に速いため、この差は大きいです。一度 PoC を作るだけなら、自前構成でも十分可能です。しかし、継続的に使い続ける場合は、モデル更新、互換性確認、再 embedding、検索品質の再評価、クラスタアップグレード、UI 保守などが積み重なります。 つまり、有償スタックや Elastic Cloud Serverless の価値は、主に次の 4 つにあります。 モデルのホスト先を自分で持たなくてよいこと LLM チャットの土台を自分で作らなくてよいこと アップデート対応の負担を減らせること 検索サービスを Observability / Security に広げやすいこと 今回のような画像検索 PoC は、最初は「検索できるか」が中心です。しかし、社内サービスや顧客向けサービスに近づくほど、「遅くなったときに原因を追えるか」「誰が何を検索したかを確認できるか」「認証情報や画像 URL が悪用されていないか」を見る必要が出てきます。 Elastic Cloud Serverless や有償スタックの価値は、検索機能そのものだけでなく、その周辺にある運用・監視・セキュリティまで、同じ Elastic の考え方で拡張できる点にもあります。 3. 全体アーキテクチャ 3-1. コンポーネントの全体図 3-2. 5 つのコンポーネントの役割 コンポーネント 役割 (一言で) Elasticsearch 画像の数値ベクトル (1024 次元) を保存し、近いベクトルを高速検索 EIS (Jina v5 Omni) 画像とテキストを 同じベクトル空間 に変換する AI モデル。Elastic 内部にホスト済み S3 (AWS) 画像本体の保管庫。private に保ち、表示用には pre-signed URL を都度生成 MCP server (Python) チャットから呼ばれる検索ロジック本体。Elastic に kNN を投げ、S3 の URL を作って返す ngrok ローカルの MCP server にインターネットから (Elastic Cloud から) 到達できるようにする一時トンネル データの流れ図 (ingest / search のシーケンス図) はリポジトリの README.md に詳しく載せています。気になる方はそちらをどうぞ。 4. 準備するもの アカウント (すべて無料枠で OK) AWS アカウント (S3 用) Elastic Cloud アカウント — https://cloud.elastic.co ngrok アカウント — https://dashboard.ngrok.com ローカル環境 (macOS 想定) Python 3.11 以上 AWS CLI … brew install awscli ngrok … brew install ngrok 画像 jpg / jpeg / png 形式で 10〜20 枚程度。スマホで撮った写真でも、フリー素材でも OK です。 Phase 0 — 環境準備 0-1. プロジェクトの構成 test-jina-image/ ├── .env / .env.example          # 認証情報 ├── setup/                       # 一度だけ走らせる初期化スクリプト │   ├── check_prerequisites.sh │   ├── create_s3_bucket.py │   └── create_elastic_index.py ├── ingest/ │   └── upload_and_index.py      # 画像アップロード + 埋め込み生成 ├── tools/ │   └── search_tools.py          # 検索ロジック本体 └── agent/     ├── system_prompt.md     ├── mcp_server.py     ├── start_ngrok.sh     └── start_mcp.sh 0-2. Elastic Cloud Serverless プロジェクトを作る https://cloud.elastic.co を開く 「Create project」 → タイプは Elasticsearch を選ぶ リージョン: Tokyo (ap-northeast-1) 名前: image-search-poc 2〜3 分待つ 0-3. ELASTIC_URL を取得する ここでよくある落とし穴があります。Cloud Console には「Endpoint」と書かれた欄が見つからないことが多いです。 最短の手順 : Kibana のブラウザ URL の .kb. を .es. に書き換えるだけ。 Kibana の URL:  https://image-search-poc-xxxxxx. kb .ap-northeast-1.aws.elastic.cloud/app/...                                                ↑ ここを変える ELASTIC_URL:    https://image-search-poc-xxxxxx. es .ap-northeast-1.aws.elastic.clo ud 0-4. ELASTIC_API_KEY を作る Kibana → Stack Management → API keys → Create API key 名前: image-search-poc、権限はデフォルト(PoC では簡略化のため) 表示された Encoded の値を必ずコピー (この画面でしか見られません) 0-5. AWS IAM ユーザーを準備 詳しい手順は長いので、 GitHub リポジトリの README に分けて書いてあります。要点だけ書くと: 専用の IAM ユーザー elastic-poc-user を作る (Console ログインなし) アクセスキー (Access Key ID + Secret) を発行する バケット名で Resource ARN を絞ったインラインポリシーを付ける (s3:CreateBucket, s3:PutObject, s3:GetObject, など最小権限のみ) ⚠️ 絶対にやらないこと : root アカウントのアクセスキーを使わない。AdministratorAccess ポリシーを付けない。”Resource”: “*” も避ける。 0-6. .env を作る プロジェクトルートに .env ファイルを作り、次のように埋めます。 ELASTIC_URL=https://image-search-poc-xxxxxx.es.ap-northeast-1.aws.elastic.cloud ELASTIC_API_KEY=<Encoded 値> AWS_ACCESS_KEY_ID=AKIA... AWS_SECRET_ACCESS_KEY=... AWS_REGION=ap-northeast-1 S3_BUCKET_NAME=image-search-poc-yourname-20260524 S3_UPLOAD_PREFIX=poc-uploads INDEX_NAME=image-search-poc そして自分以外読めないように権限を絞ります。→ chmod 600 .env 0-7. 環境チェック bash setup/check_prerequisites.sh このスクリプトは Python・pip・AWS CLI を確認し、venv を作り、必要なライブラリ (elasticsearch, boto3, python-dotenv, requests) をインストールし、最後に .env の中身が揃っているかを確認します。 Phase 1 — S3 バケットを作る ./venv/bin/python setup/create_s3_bucket.py このスクリプトが裏でやることは 4 つ。 バケットを東京リージョンに作成 Block Public Access を 4/4 すべて有効化 SSE-S3 暗号化 を有効化 バージョニング を有効化 実行後、AWS Console でバケットを開いて、上記 3 つの設定がすべて緑色になっているか確認します。 ここで押さえたいキーワード: SSE-S3 とは 「暗号化」と聞くと TLS / HTTPS と混同しがちですが、 SSE-S3 はディスクに書き込む時の暗号化 (encryption at rest) です。 物理的にディスクが盗まれても中身が読めない、というのが SSE-S3 の役割です。アクセス権限は IAM の仕事、通信の盗聴は TLS の仕事と分かれています。 Phase 2 — Elastic インデックスを作る ./venv/bin/python setup/create_elastic_index.py このスクリプトは 2 つのことをします。 実体インデックス image-search-poc-v1 を作る alias image-search-poc を -v1 に紐付ける マッピング (フィールド定義) {   "image_key":   { "type": "keyword" },   "name":        { "type": "text" },   "description": { "type": "text" },          // ← 今回は未使用、将来のキャプション保存用に予約   "image_embedding": {     "type": "dense_vector",     "dims": 1024,     "index": true,     "similarity": "cosine",     "index_options": { "type": "int8_hnsw" }   } } ここで押さえたいキーワード ① — dense_vector まずはシンプルに考えると、 dense_vector とは「数値の配列を 1 件分のドキュメントに保存できるフィールド型」です。 今回は 1024 個の数値 (= 1024 次元のベクトル) を 1 枚の画像につき 1 つ保存します。Jina v5 Omni のモデルが出力する次元数が 1024 なので、それに合わせています。 “ image_embedding “: [0.12, -0.34, 0.55, ..., 0.08]   # 1024 個の数値 similarity: "cosine" … 「似ている度合い」をベクトルの 向き で測る。Jina 推奨 index_options.type: "int8_hnsw" … 1 次元あたり 32bit → 8bit に量子化してメモリを 約 1/4 に。精度はほぼ変わらず、検索も速い 12 枚だと量子化の効果は実感しにくいですが、画像が 100 万件レベルになると検索コスト (latency / メモリ) にはっきり効いてきます。 ここで押さえたいキーワード ② — alias Elasticsearch のインデックスには 「マッピングは一度作ったら基本変えられない」 という制約があります。次元数を変えたい、フィールドの型を変えたい、というときは新しいインデックスを作り直すしかありません。 そのとき困るのが「アプリのコードに image-search-poc-v1 というインデックス名を直接書いてしまっていると、毎回アプリも修正する必要がある」点です。 そこで alias (エイリアス) を使います。 一言でいうと、alias は「インデックスのあだ名」です。アプリ側は alias 名で読み書きを行い、Elasticsearch 側で裏の実体を差し替えられます。Twitter のユーザー名 (@handle) を変えずに中身のアカウント ID を移転するイメージです。 将来 Jina v6 が出て次元数が変わったときも、新しいインデックスを作って alias を切り替えるだけで、アプリ側のコードは触らなくて済みます。 Phase 3 — 画像を ingest する ./venv/bin/python ingest/upload_and_index.py /path/to/poc-images このスクリプトが各画像に対して 4 つのことをします。 ローカルファイルを S3 にアップロード (poc-uploads/<filename> として) 同じファイルを base64 にエンコード し、data:image/jpeg;base64,… という data URI 形式の文字列を作る Elastic の _inference API を 公式の content block 形式 で呼ぶ 返ってきた 1024 次元ベクトルを image_embedding フィールドに入れて index ここで押さえたいキーワード ① — embedding (埋め込み) まずはシンプルに考えると 、embedding とは「テキストや画像を、意味を保ったまま高次元の数値ベクトルに変換すること」です。 近い意味のものは数学的に近いベクトルになります。 “青い椅子”      →  [0.12, -0.34, 0.55, …, 0.08] “red chair”     →  [0.13, -0.32, 0.56, …, 0.07]   ← 上とほぼ同じ “taxi”          →  [-0.45, 0.71, -0.02, …, 0.31]   ← 全然違う <青い椅子の写真> →  [0.10, -0.31, 0.58, …, 0.05]   ← “青い椅子” のテキストに近い これがマルチモーダルモデルの肝です。「テキストの青い椅子」と「青い椅子の写真」が 同じベクトル空間で近い場所 に置かれるので、テキストで画像を引っ張れます。 ここで押さえたいキーワード ② — content block 形式 content block とは、API に「これは何の入力か (テキスト? 画像? 音声?)」を明示的に伝えるための構造化データのことです。HTTP の Content-Type: image/jpeg ヘッダーと同じ感覚で、「これから渡すデータの種類はこれだよ」と先に宣言します。 画像の embedding を取りたいときは、次の JSON 構造で送ります。 POST _inference/.jina-embeddings-v5-omni-small {   "input": [     {       "content": {         "type": "image",         // ① これは画像         "format": "base64",      // ② base64 でエンコード済み         "value": "data:image/jpeg;base64,<RAW_BASE64>"   // ③ 実データ       }     }   ] } 守るべきポイントは 3 つ: content は 単一オブジェクト (配列ではない) value には data:image/jpeg;base64, という data URI プレフィックスを付ける 入力は base64 された画像データ本体 (S3 の URL ではない) Python の実装 ingest/upload_and_index.py から抜粋。 import base64 b64 = base64.b64encode(image_path.read_bytes()).decode("ascii") data_uri = f"data:{mime};base64,{b64}" response = es.inference.inference(     inference_id=".jina-embeddings-v5-omni-small",     input=[         {             "content": {                 "type": "image",                 "format": "base64",                 "value": data_uri,             }         }     ], ) # レスポンスの key は “embeddings” (複数形) # ただし Elastic バージョンによっては “text_embedding” や “embedding” のこともあるので、 embedding = None for key in ("embeddings", "text_embedding", "embedding"): # 複数の key を順に試すフォールバックを書いておくと安全     if key in response and len(response[key]) > 0:         first = response[key][0]         embedding = first["embedding"] if isinstance(first, dict) else first         break es.index(     index="image-search-poc",   # alias 経由で書く     id=image_key,     document={         "image_key": image_key,         "name": image_path.stem,         "image_embedding": embedding,     },     refresh="wait_for", ) ⚠️ よくある罠 — 画像 URL を文字列として送る ここが 一番の落とし穴 です。「_inference の入力に画像 URL の文字列を渡せば、Elastic が裏でダウンロードして画像として処理してくれるのでは?」と思いがちですが、実際は次のように動きます。 # ❌ これは「URL の文字列」を embedding するだけ — 画像は読まれない es.inference.inference(     inference_id=".jina-embeddings-v5-omni-small",     input=["https://my-bucket.s3.amazonaws.com/poc-uploads/IMG_8133.jpeg?..."] ) その結果、https, amazonaws, poc-uploads のような URL の単語が embedding に反映され、 どの画像も似たようなベクトル になります。検索結果はランダムに見えるくらい滅茶苦茶になります。 詳しい失敗体験は「ハマったところ TOP 3」で書きます。 Phase 4 — CLI で検索を試す ./venv/bin/python tools/search_tools.py text "青い椅子" ./venv/bin/python tools/search_tools.py filename "IMG_8133.jpeg" ./venv/bin/python tools/search_tools.py text_in_image "RIDE" このスクリプトは後で MCP server から呼ばれるロジック本体でもあります。CLI で正しい結果が返ってくれば、ロジックは OK ということです。 ここで押さえたいキーワード ① — kNN (k-Nearest Neighbors) まずはシンプルに考えると 、kNN とは「ベクトル空間でクエリベクトルに最も近い k 個を見つける」アルゴリズムです。 「青い椅子」というクエリのベクトルから、保存されている画像ベクトルの中で 最も近い 3 つ を返してください、というのが kNN 検索の中身です。 クエリ "青い椅子" → ベクトル化 → [0.12, -0.34, ...] ↓ 12 枚の画像ベクトルの中で 最も近い 3 つを返す Elasticsearch の dense_vector フィールドはこれをネイティブにサポートしています。 ここで押さえたいキーワード ② — query_vector_builder 普通に書くと、「青い椅子」というクエリで検索するには 2 ステップが必要です。 A . テキスト → ベクトルに変換 (_inference を呼ぶ) B . そのベクトルで kNN 検索 (_search を呼ぶ) つまり Python から見ると 2 ラウンドトリップ 。 ところが Elastic の _search には query_vector_builder という仕組みがあって、 ベクトル化を _searchリクエストの中で Elastic 側に肩代わりさせられます 。 result = es.search(     index="image-search-poc",   # alias 経由     query={         "knn": {             "field": "image_embedding",             "k": 3,             "num_candidates": 50,             "query_vector_builder": {                 "embedding": {                     "inference_id": ".jina-embeddings-v5-omni-small",                     "input": {"type": "text", "value": "青い椅子"}                 }             }         }     },     size=3,     source=["image_key", "name"], ) クライアントから Elasticsearch へのリクエスト回数を 2 回から 1 回に減らせます。実際の latency は inference endpoint の応答時間や検索対象件数に依存しますが、クライアントコードと通信設計はかなりシンプルになります。 query_vector_builder.lookup — 画像 → 類似画像検索 「IMG_8133.jpeg に似た画像」のように、 既にインデックスにある画像のベクトル をクエリとして使いたいときは lookup を使います。 {   "knn": {     "field": "image_embedding",     "k": 4,     "query_vector_builder": {       "lookup": {         "index": "image-search-poc",         "id": "poc-uploads/IMG_8133.jpeg",         "path": "image_embedding"       }     }   } } 「インデックスから別 doc の embedding を取り出して、それを query vector に使え」という意味です。「画像 → 類似画像」検索が 1 リクエストで完結します。 ここで押さえたいキーワード ③ — Pre-signed URL S3 のプライベートオブジェクトに、 期限付き でアクセスできる URL です。AWS のシークレットキーで署名されており、有効期限を秒数で指定できます。 本 PoC では 10 分有効 の pre-signed URL をチャット表示用に生成します (tools/search_tools.py の ExpiresIn=600)。 url = s3.generate_presigned_url(     "get_object",     Params={         "Bucket": S3_BUCKET_NAME,         "Key": "poc-uploads/IMG_8133.jpeg",         "ResponseContentType": "image/jpeg",     },     ExpiresIn=600,   # 10 分 ) 生成された URL の例 (boto3 デフォルトの AWS Signature v4 形式): ?response-content-type=image%2Fjpeg   &X-Amz-Algorithm=AWS4-HMAC-SHA256   &X-Amz-Credential=AKIA.../20260528/ap-northeast-1/s3/aws4_request   &X-Amz-Date=20260528T120000Z   &X-Amz-Expires=600   &X-Amz-SignedHeaders=host   &X-Amz-Signature=... X-Amz-Signature は秘密鍵で計算されています。URL を改ざんすると署名が合わなくなり、S3 は 403 を返します。 Phase 5 — Agent Builder + MCP でチャット化 ここからは Kibana の UI 操作と、ローカルの MCP server 起動の組み合わせです。 ここで押さえたいキーワード ① — Agent Builder Kibana の中で LLM チャットエージェントを作る機能です。「カスタム指示 (system prompt)」と「ツール」を組み合わせて、エージェントが何をするかを決めます。 エージェントの仕事は 4 ステップ: ユーザーの質問を受け取る 質問の内容を見て、どのツールを呼ぶか LLM が決定 ツールを呼んで結果を受け取る 結果を整形してユーザーに返す ここで押さえたいキーワード ② — MCP (Model Context Protocol) LLM エージェントが外部のツールを呼ぶ ための、Anthropic が提唱したオープンプロトコルです。Agent Builder もネイティブにサポートしています。 MCP server を立てると、その server に登録された関数が Agent Builder のツールとして見えるようになります。Python で書いた検索ロジックを、そのままチャットの中で呼べるという仕組みです。 Agent Builder のツールの 4 種類 Agent Builder では、エージェントが呼べるツールを 4 つのタイプで作れます。 Type できること 適している用途 ES|QL 固定の ES|QL クエリにユーザー入力をパラメータとして渡す 集計・フィルタ・テキスト検索 Index search LLM が自然言語からその場で ES|QL を生成 構造化データの探索的検索 Workflow 複数ステップの workflow を呼ぶ 入力 → 処理 A → 処理 B のような連鎖 MCP 外部の MCP server を呼ぶ。Python など任意言語のロジック カスタム検索ロジック、外部 API 連携 query_vector_builder を含む DSL クエリは ES|QL では表現できないため、本 PoC では MCP を選びました。 5-1. MCP server を書く # agent/mcp_server.py from fastmcp import FastMCP from tools.search_tools import (     search_by_text, search_by_filename, search_by_text_in_image, ) mcp = FastMCP("image-search-poc") @mcp.tool() def search_images_by_text(query: str) -> list:     """画像を自然言語で意味検索する"""     return search_by_text(query) @mcp.tool() def search_images_by_filename(filename: str) -> list:     """既存ファイル名から類似画像を検索する"""     return search_by_filename(filename) @mcp.tool() def search_images_by_visible_text(visible_text: str) -> list:     """画像内の文字で検索する"""     return search_by_text_in_image(visible_text) mcp.run(     transport="streamable-http",     host="127.0.0.1",   # ← LAN からの直接アクセスを遮断 (セキュリティ)     port=8080, ) @mcp.tool() というデコレータを付けるだけで関数が MCP ツールとして公開されます。これが FastMCP の便利なところです。 5-2. ngrok でトンネルを開く Elastic Cloud (インターネット側) は、ローカル開発機の localhost:8080 を直接見ることはできません。localhost は文字通り「自分の中だけのアドレス」だからです。 そこで ngrok を使います。ngrok は「インターネット側の公開 URL と、ローカルで動くサーバーをつなぐトンネル」を作るサービスです。 ここで大事なのは、ローカル側は何のポートも外部に開けないという点。ngrok エージェントがローカルから ngrok server に接続 (outbound) しているので、インターネット → ローカルの方向はその既存トンネルの中を逆流するように流れます。 5-3. 2 ターミナル運用 最初は ngrok と MCP server を 1 つのスクリプトで両方起動していました。しかし MCP server のコードを直して再起動するたびに ngrok の URL も変わってしまい(有料アカウントが違う)、その都度 Kibana 側のコネクタ設定を直す必要がありました。 解決策は 役割ごとにターミナルを分ける こと。 ターミナル 動かすもの 再起動頻度 A ngrok だけ 1 日 1 回 B MCP server だけ 必要に応じて何度でも ngrok を立てっぱなしにすれば URL が変わらないので、Kibana 側の設定はそのまま使い続けられます。 ターミナル A: ngrok を起動 NGROK_AUTH="myuser:mypassword2026" bash agent/start_ngrok.sh 引数の意味: NGROK_AUTH=”myuser:mypassword2026″ … Basic 認証の「ユーザー名:パスワード」を環境変数で渡す パスワードは 8 文字以上 が必須 (ngrok の制約) 省略するとスクリプトがランダムな 16 文字のパスワードを生成する 起動後の出力例: 🔐 Basic auth: myuser:mypassword2026 💾 認証情報は /tmp/mcp_demo_auth.txt に保存 (chmod 600) Forwarding   https://abc123-xyz.ngrok-free.app -> http://localhost:8080 ここで https://abc123-xyz.ngrok-free.app という URL をメモ します。後で Kibana の MCP コネクタ設定に貼り付けます。 ターミナル B: MCP server を起動 (コード変更ごと) bash agent/start_mcp.sh 起動後の出力例: 📡 MCP server starting on http://127.0.0.1:8080/mcp INFO:     Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit) これで http://127.0.0.1:8080/mcp で MCP server が待ち受け、ngrok 経由で https://abc123-xyz.ngrok-free.app/mcp から到達できるようになります。 5-4. Kibana 側: エージェントを作る Kibana 左メニュー → Agents → New Agent Agent ID : image-search-agent Custom Instructions に agent/system_prompt.md の中身をコピペ Elastic capabilities : OFF (本 PoC では Kibana ビルトインの機能は使わない) Visibility : Private Save system_prompt.md には、「ユーザーが何を入力したらどのツールを呼ぶか」「結果をどう整形するか」を細かく書いてあります。Kibana の CSP の関係で 画像は インライン埋め込みではなくクリッカブルリンクで出す という指示もここで入れています (詳細は後述のハマったところ参照)。 5-5. Kibana 側: MCP コネクタを登録 Kibana → Tools library → Manage MCP → Add a new MCP server 次の値を入れる: 項目 値 意味 Connector name Image Search PoC 表示名 (日本語 OK) Connector ID image-search-poc 一意の識別子 (半角英数字とハイフンのみ) Server URL https://<NGROK_URL>.ngrok-free.app/mcp ngrok の URL + /mcp suffix 「Additional settings」を展開し、 Add header を 2 回クリックして次の 2 行を追加: Key Value 意味 Authorization Basic bXl1c2Vy ***GFzc***mQyMDI2 ngrok の basic auth を通すため ngrok-skip-browser-warning true ngrok の警告ページをスキップするため Authorization の値の作り方 HTTP の Basic 認証は 「ユーザー名:パスワード」を base64 でエンコードした文字列 をヘッダーに入れます。 printf 'myuser:mypassword2026' | base64 # 出力: bXl1c2VyOm15cGFzc3dvcmQyMDI2 注意: echo ではなく printf を使うこと。echo は末尾に改行を付けるので、計算結果が変わります。 完成形: Authorization: Basic bXl1c2Vy***cGFzc***mQyMDI2 Basic の後に 半角スペース 1 つ が必要です。 ngrok-skip-browser-warning が必要な理由 ngrok の無料版は abuse 防止のため、ブラウザっぽい User-Agent からのリクエストに対して HTML の警告ページ (“You are about to visit:”) を返すことがあります。Elastic の MCP クライアントがこれを受け取ると、JSON ではなく HTML が来てしまい「Failed to load tools」エラーになります。 このヘッダーを付けると、ngrok は警告ページをスキップして直接 MCP server のレスポンスを返してくれます。値は何でも OK (true, 1, yes など、空でなければ通る)。 5-6. ツールをエージェントに有効化 Save 後、ドロップダウンで Image Search PoC を選ぶ 3 つのツールが表示される (search_images_by_text 他 2 つ) すべてチェック → Namespace に image_search を入れて → Import tools Agents → image-search-agent → Tools タブで image_search.search_images_by_* を 3 つ有効化 (推奨) デフォルトのビルトインツール 6 つは無効化 Save 5-7. チャットで動作確認 エージェント画面の右上「Save and chat」を押します。 👤 青い椅子の写真を見せて 期待される応答: 3 件の結果カード 各カードに 🖼 画像を新しいタブで開く → というクリッカブルリンク 類似度スコア + マッチ理由 リンクをクリックすると別タブで画像が開きます。 ハマったところ TOP 4 「正しいやり方」だけを上で書きましたが、実際にはいくつもハマりました。記憶に残った 4 つを共有します。 罠 ①. 画像 URL をテキストとして送って 3 時間溶かした 症状 : 異なる画像同士の embedding が cosine 0.94 (ほぼ同じ)、検索結果がランダム。「sea」で検索すると椅子と PC の写真が出てくる。 原因 : S3 の pre-signed URL を _inference に 文字列として 渡していた。 # ❌ 悪い例 es.inference.inference(     inference_id=".jina-embeddings-v5-omni-small",     input=["https://my-bucket.s3.amazonaws.com/poc-uploads/IMG_8133.jpeg?..."] ) Elastic はこの URL を テキスト として embedding 化していました。Jina v5 omni の画像エンコーダ経路には入っておらず、URL の単語 (https, amazon, poc-uploads, …) が embedding に反映されていました。結果、どの画像も似たベクトルになります。 対策 : 必ず base64 + content block 形式 で送る (Phase 3 のコード例参照)。 罠 ②. semantic_text フィールドに画像を入れたら大失敗 「semantic_text フィールドに base64 を入れれば自動で embedding できるはず」と仮説検証しました。しかし semantic_text は テキスト用のフィールド で、内部で base64 文字列を チャンク分割 してしまいます。 結果として、すべての画像が JPEG のヘッダーバイト列の共通性で似たベクトルになり、検索精度が壊滅しました。 学び : 今回のように画像そのものを multimodal embedding として扱う場合は、 semantic_text  に base64 文字列を入れるのではなく、embedding API で画像 embedding を作り、 dense_vector  に保存する構成が分かりやすく安全でした。 罠 ③. Kibana チャットで画像がインライン表示できない 症状 : Markdown ![](url) で画像を埋めようとすると、チャットでは壊れた画像アイコンになる。新しいタブで開けば見られる。 原因 : Kibana の Content Security Policy (CSP) が、外部ドメイン (s3.amazonaws.com) からの <img> をブロック。Elastic Cloud Serverless では CSP のカスタマイズが許可されていません。 対策 : System Prompt で 「インライン埋め込みではなくクリッカブルリンク [label](url) を出す」 と指示する。本 PoC の agent/system_prompt.md はその指示込みになっています。 罠 ④. ngrok を再起動したら「Failed to load tools」が再発した これは翌日に作業を再開したときによく起こります。 症状 : 前日まで普通に動いていたのに、ngrok を一度落として再起動した直後、Kibana の Bulk import で 「Failed to load tools from the selected MCP server」 が表示される。MCP server も ngrok もログ上は正常。 原因 : agent/start_ngrok.sh は環境変数 NGROK_AUTH が無いと 毎回ランダムな 16 文字のパスワード を生成します。前日に登録した Kibana の Authorization ヘッダーは 昨日のパスワード の base64 のままなので、ngrok 側で 401 Unauthorized → Elastic は HTML のエラーページを受け取り MCP プロトコルとして解析失敗、というカスケード。 対策 : 2 つあります。お好みでどうぞ。 (a) パスワードを固定する ⭐ (おすすめ) ngrok 起動時に毎回同じ NGROK_AUTH を渡せば、Kibana 側のヘッダーは触らなくて済みます。 NGROK_AUTH="myuser:mypassword2026" bash agent/start_ngrok.sh (b) 起動のたびに base64 を再計算する ランダムパスワードのままにする場合、起動後にスクリプトが生成した認証情報を確認して、新しい base64 を Kibana に貼り直します。 cat /tmp/mcp_demo_auth.txt                       # 今回のパスワードを確認 printf "$(cat /tmp/mcp_demo_auth.txt)" | base64  # base64 を計算 出力を Basic <新しい base64> に直して Kibana の Authorization ヘッダーを更新 → Save。 診断のコツ : 「Failed to load tools」が出たら、ターミナルから直接 curl で叩いてみると原因が切り分けられます。 curl -i -u "$(cat /tmp/mcp_demo_auth.txt)" \   -H "ngrok-skip-browser-warning: true" \ https://.ngrok-free.app/mcp .ngrok-free.app 401 Unauthorized → 認証情報が違う (この罠 ④) 404 Not Found → URL の末尾が /mcp になっていない HTML が返る → ngrok-skip-browser-warning ヘッダー漏れ 接続拒否 → MCP server が動いていない 運用 — 起動と停止のステップ PoC が動くようになったら、次に気になるのは「どう起動するの? どう止めるの?」です。 📌 起動コマンド・出力例の詳細は §5-3 「2 ターミナル運用」 を参照。ここでは時間軸の流れと、Kibana 側で必要な操作に絞って整理します。 始めるとき ターミナル A で start_ngrok.sh を起動 (つけっぱなし) → 表示された ngrok URL をメモ NGROK_AUTH を固定値にしておくと、Kibana のヘッダーを毎回触らなくて済みます (罠 ④ 参照) ターミナル B で start_mcp.sh を起動 Kibana → Tools library → Manage MCP → 既存の Image Search PoC コネクタを開く: Server URL を新しい ngrok URL に書き換え (free 版はセッションごとに変わるため) Authorization ヘッダーは NGROK_AUTH を固定値にしている限り 書き換え不要 Save Kibana のチャット画面を開いて使う 🎉 コードを編集したら Python の検索ロジックを直したり、MCP ツールを追加したいときは ターミナル B だけ Ctrl+C → start_mcp.sh を再実行。ngrok URL は変わらないので Kibana 側は何も触らなくて OK。再起動の間、ngrok は一瞬 502 Bad Gateway を返しますが、再起動が終われば自動で復活します。 仕事終わり ターミナル B で Ctrl+C → MCP server 停止 ターミナル A で Ctrl+C → ngrok トンネル停止 スクリプトのクリーンアップ処理で /tmp/mcp_demo_auth.txt も自動削除されます 💡 ngrok の有料プランに切り替えれば 固定の URL が使えるため、URL の付け替え作業自体が不要になります。チーム運用や本番に近い構成では Cloudflare Tunnel + Access への移行も選択肢です。 次のステップ PoC が動いたら、次のことを試すと面白いです。 5-1. データセットに無い画像から類似画像を探す (リバース画像検索) 現状の search_by_filename は「既にインデックスにある画像のファイル名」からしか動きません。次のステップとして、 「ユーザーが今撮った写真」をその場でアップロードして、データセット内の似た画像を返す フローが作れます。 新しい MCP ツール search_by_uploaded_image(image_base64: str) を追加し、内部で _inference を呼んでベクトル化 → kNN するだけです。 5-2. OCR と組み合わせて「画像内文字」検索の精度を上げる 現状の search_by_text_in_image は Jina のマルチモーダル能力に依存しています。「RIDE」というプロンプトを Jina に投げて視覚的に近い画像を探しているだけで、 実際に画像の文字を読んでいるわけではありません 。 OCR (AWS Textract / Tesseract) を ingest 時に走らせて extracted_text フィールドに保存し、 RRF (Reciprocal Rank Fusion) で BM25 と kNN を統合すると、「本当に RIDE と書かれた画像」を確実に上位に出せます。 5-3. その他 Cloudflare Tunnel + Access に移行 — チームで共有するなら、ngrok 個人運用から脱却 AWS Lambda にデプロイ — Mac を起動しなくても 24/7 動く構成へ 画像のキャプション自動生成 — GPT-4V / Claude Vision でキャプションを description に保存 まとめ このブログでは: マルチモーダル画像検索 を Elastic Cloud Serverless + Jina v5 Omni で実装 query_vector_builder で Python のコードをシンプルに保ちつつ kNN を実行 Agent Builder + MCP server で Kibana チャットからカスタム関数を呼べるように ngrok の 2 ターミナル運用 で日々の開発をスムーズに PoC のコード総量は Python で 300 行強、構築時間は 2〜3 営業日でした。「ベクトル検索やマルチモーダルをやってみたい」という案件があれば、まずこの組み合わせを試すのが最短ルートだと思います。 ソースコード・詳細手順 GitHub リポジトリ : test-jina-image 完全な手順書 : リポジトリの README.md 設計の背景・経緯 : リポジトリの WALKTHROUGH.md — 何にハマって何を学んだかを時系列で記録 参考リンク Elastic Search Labs — jina-embeddings-v5-omni for text, images, video, audio Elastic Docs — Inference embedding API Elastic Docs — Agent Builder Tools Model Context Protocol (MCP) 仕様 FastMCP (Python MCP server framework) Elasticsearch × CLIP × GPTで画像検索システムを作ってみた この記事は Elastic Cloud Serverless 9.5 / Jina v5 Omni small (2026-05-11 GA) / FastMCP 3.3.x / ngrok 3.x を使用した PoC に基づいています。質問・改善提案あれば気軽にどうぞ。 The post Elastic Cloud で「言葉で画像を探す」を作る first appeared on Elastic Portal .
みなさん、Elastic Cloudを運用していて 「今月はどれくらいコストがかかっているだろう…」 「気づかないうちに予算を使い切っていたらどうしよう」 と不安になったことはありませんか? Elastic Cloudには、コストの使いすぎを防ぎ、現在の利用状況を可視化するための「Budgets and notifications(予算と通知)」という非常に便利な機能が用意されています。 今回は、Elastic公式ドキュメントをベースに、この通知機能の仕組みと具体的な設定手順をわかりやすく解説します! 目次 前提条件 1. Elastic Cloudの「予算(Budgets)通知」とは? 2. 予算アラートを設定する5つのステップ ステップ1:設定画面へ移動 ステップ2:適用範囲(Scope)の選択 ステップ3:予算額(Configuration)の入力 ステップ4:通知メールの受信者の選択 ステップ5 : Budget の保存 3. 作成した予算の管理方法 4. 【注意】プリペイド契約向け:クレジット消費の自動通知 まとめ:早めの予算設定で、安心なElastic運用を! 前提条件 2026年5月時点の Elastic Cloud の管理画面で動作検証しています。 Elastic Cloud の 予算管理機能は、Organization owner(組織のオーナー)または Billing admin (請求管理者)のみアクセス可能です。 1. Elastic Cloudの「予算(Budgets)通知」とは? Elastic Cloudの予算機能を使うと、当月(月内累積)の利用コストが、あらかじめ設定した目標額(しきい値)に達した際、 自動的にEメールでアラート通知を受け取ることができます。 この機能の大きな特徴は、以下の2つの単位で予算を管理できる点です。 組織(Organization)全体: 今後新しく作成するリソースも含め、アカウント全体の合算コストを追跡 特定のクラウドリソース(Cloud resource): 特定の「Hosted deployment」や「Serverless project」、「Connected cluster」など、プロジェクトやシステム単位で個別にコストを追跡(複数選択も可能) 予算の通貨単位には、Elasticの共通コスト単位である ECU(Elastic Consumption Units) が使用されます。 2. 予算アラートを設定する5つのステップ 設定はElastic Cloudのコンソールから、簡単に行えます。 ステップ1:設定画面へ移動 Elastic Cloudにログイン後、メニューから [Billing] > [Budgets and notifications] を選択し、[Add budget] をクリックします。 ステップ2:適用範囲(Scope)の選択 予算を適用する範囲を、先ほど紹介した「Organization(組織全体)」か「Cloud resource(特定のリソース)」から選びます。 最近追加された EIS で使用される Cloud Connect の料金(LLMの利用料金を含む)の予算を決めたい場合は、Scope に Cloud resource を選択し、さらに Cloud Connect のリソースを選択してください。 複数のリソースの合算で予算を決めたい場合、リソースを複数指定してください。 ステップ3:予算額(Configuration)の入力 Name 管理しやすい予算の名前を入力します。 Time range 予算の期間は「月単位(Monthly)」固定です。毎月1日に累積使用量がリセットされます。 Target amount (ECU) 目標とする予算額(ECU)を入力します。 💡 ここが便利! 予算入力フォームの横には、過去6ヶ月間の利用実績(履歴)を示したコストトレンドチャートが表示されます。 これを見ながら「今月はこれくらいが妥当かな」と現実的な目標額を決められます。 上記は、Scope:Organization で、Target amount: 100 とした場合の例です。 ステップ4:通知メールの受信者の選択 通知が飛ぶタイミング(しきい値)は、以下の 2段階で固定 されています。 通知タイプ トリガーされるタイミング 警告(Warning)メール 当月の利用額が、目標額の 75% に達したとき 超過(Overage)メール 当月の利用額が、目標額の 100% に達したとき 次に、通知メールを受け取る 受信者のロール(役割) を選択します。 組織全体の予算の場合 Organization owner(組織オーナー)や Billing admin(請求管理者) 特定リソースの予算の場合 そのリソースに対して Admin、Editor、Viewer の権限を持つユーザー ステップ5 : Budget の保存 最後に [Create budget] をクリックすれば設定完了です! 上記は、Scope: Organization で、受信者: Organization owner, Billing admin とした場合の例です。 3. 作成した予算の管理方法 予算を作成すると、一覧画面(テーブル)で「現在値 vs 予算額(ECU)」がひと目でわかるようになります。 一時停止と再開 通知を止めたいときは、アクションメニューから Deactivate(無効化)を選ぶだけです。いつでも Activate で再開できます。 リソース削除時の挙動 もし個別リソース向けに組んだ予算で、対象リソースが削除された場合は、自動的に選択リストから外れ、注意書き(コールアウト)で通知されます。 ※予算は、複数作成することが可能です。(リソースグループ1用の予算、リソースグループ2用の予算、など) 4. 【注意】プリペイド契約向け:クレジット消費の自動通知 もしあなたの組織が「プリペイド(前払い)クレジット」を利用してElastic Cloudを契約している場合、上記の予算設定とは別に、自動的なクレジット残量通知が機能します。 こちらはユーザー側での設定や変更は不可で、残量が少なくなると自動的に以下のタイミングでアラートメールが送信されます。 アクティブなクレジットの残量が 33%、25%、16%、0% になったとき 「気づいたらクレジットが切れていてオンデマンド請求(従量課金)になっていた!」という事態を防ぐための安心機能です。 まとめ:早めの予算設定で、安心なElastic運用を! Elastic Cloudは非常にスケーラブルで便利な反面、予期せぬ大量データ流入やLLMの利用量の急増などでコストが跳ね上がるリスクもゼロではありません。 今回紹介した「予算・通知機能」は、設定に5分もかかりません。まだ設定していない方は、まずは過去6ヶ月のトレンドを見ながら、組織全体または主要なデプロイメントに対して予算(75% / 100% アラート)を組んでおくことを強くおすすめします。 コストをスマートにコントロールして、快適なElasticライフを送りましょう! 本記事は、2026年5月時点のElastic公式ドキュメント(バージョン9.4)の情報を元に作成しています。最新の仕様は公式ドキュメントをご確認ください。 参考URL Manage budgets and notifications | Elastic Docs To help you understand costs and manage spending on Elastic Cloud, you can create budgets that track resource usage and … www.elastic.co User roles and privileges | Elastic Docs Within an Elastic Cloud organization, users can have one or more roles and each role grants specific privileges. You can… www.elastic.co The post 【Elastic Cloud】勝手な予算オーバーを防ぐ!「予算・請求通知機能」の設定方法とポイント解説 first appeared on Elastic Portal .
想定読者:SOC アナリスト、脅威ハンター、検知エンジニア。SIEM の経験はあるが Elastic / EQL は初めて、あるいは復習したい方。 読了時間:約 15 分 セキュリティ運用の現場では、毎日とんでもない量のログを見ます。Elasticsearch は「ログを保存して検索する」のはとても得意です。でも、 脅威の検出 となると話が一段難しくなります。 なぜか。攻撃は単独のイベントではなく、 複数のステップが時間軸の上で連なる流れ だからです。 たとえば、次のような流れを「ひとかたまり」として検出したいとします。 ファイルが Temp フォルダに作成された その直後にそのファイルが実行された さらにそのプロセスが外部に通信した 普通のクエリでは、これを 3 回別々に検索して、ID やタイムスタンプで突き合わせる必要があります。これがしんどい。 EQL(Event Query Language)は、この「流れ全体」を一度のクエリで捕まえるために作られた言語 です。本記事では、セキュリティエンジニアが EQL を実務で使えるようになるための最短ルートを紹介します。 目次 EQL とは何か EQL を動かすための前提 通常の検索クエリ(KQL/Lucene)と何が違うか Splunk SPL を使っている人へ:EQL との対応表 同じ検出を SPL と EQL で書き比べる EQL の SPL に対する優位点 EQL の基本構文 最小単位の形 例 1:PowerShell 実行の検出 例 2:複数条件の組み合わせ EQL の演算子チートシート == と : の使い分け(ハマりやすい) ECS:Elastic Common Schema を理解する ECS とは何か セキュリティで頻出する ECS フィールド タスク文を EQL に変換するフレームワーク 5 ステップ翻訳法 実演:タスク文を 5 ステップで翻訳する キーワード → ECS フィールドの早見表 sequence と時間制約:流れの検出 構文 by の力:複数フィールドで相関 イベント間で値を引き継ぐ:per-event by maxspan の選び方 実例:セキュリティ検出パターン 5 選 パターン 1:暗号化されていない通信の検出(コンプライアンス) パターン 2:PowerShell ダウンロードからの C2 接続 パターン 3:Office アプリからのプロセス起動(Living off the Land) パターン 4:マルウェア配置 → 実行 → C2 通信 パターン 5:横展開の検出(ラテラルムーブメント) よくあるミス と正しい書き方 ミス 1:ECS でないフィールド名を使う ミス 2:大文字小文字の罠 ミス 3:event.action と event.type の混同 ミス 4:sequence の順序逆転 ミス 5:maxspan の単位忘れ ミス 6:EQL 関数の大文字小文字を間違える ミス 7:関数の引数の大文字小文字でヒットしない 実際に動かす方法 方法 1:Kibana の Dev Tools で試す 方法 2:Elastic Security の Timeline 方法 3:Detection Rule として登録 まとめ 参考資料 EQL とは何か EQL は Elastic が開発した、 イベントベースのクエリ言語 です。SQL や KQL に少し似ていますが、決定的に違うのは「 複数のイベントの順序と関係性を表現できる 」点です。 ひとことで言うと: EQL は「A が起きて、その後に B が起きて、さらに C が起きた」を 1 つのクエリで書ける言語。 これは脅威検出と相性が抜群です。なぜなら、攻撃チェーン(MITRE ATT&CK で言うところの Tactics の連鎖)は、まさにそういう構造をしているからです。 EQL を動かすための前提 ここで先に伝えておきたいことがあります。EQL は ECS(Elastic Common Schema)を前提に設計されているため、 検索対象のデータには @timestamp と event.category フィールドが必要 です。Elastic 公式ドキュメントにも、EQL はデフォルトでこの 2 つのフィールドを使うと明記されています。 つまり、 process where process.name == "powershell.exe" の process は、実際には「event.category が process のイベント」を意味します。 Elastic Agent や Elastic Defend、Beats から取り込んだデータは ECS に準拠しているのでそのまま EQL が動きます。独自データの場合は、最低限この 2 フィールドをマッピングしておく必要があります。 通常の検索クエリ(KQL/Lucene)と何が違うか 特性 通常のクエリ (KQL) EQL 1 つのイベント検索 ✅ 得意 ✅ 得意 集計・統計 ✅ 得意 ⚠️ 限定的 複数イベントの順序関係 ❌ 自前で組み立て ✅ ネイティブ対応 時間窓での相関 ❌ 困難 ✅ maxspan で簡単 ECS フィールドの活用 ✅ ✅ 「単一イベントを検索したい」なら KQL でも十分です。 「攻撃の流れを検出したい」なら EQL です。 Splunk SPL を使っている人へ:EQL との対応表 SOC 経験者の多くは Splunk SPL の知識があるはずです。両者の対応関係を理解しておくと、EQL の学習速度が一気に上がります。 やりたいこと Splunk SPL Elastic EQL 単一イベント検索 search index=… process=”…” process where process.name == “…” 複数イベントの相関 transaction host maxspan=30s sequence by host.name with maxspan=30s ストリーミング相関 streamstats sequence データモデル / 正規化 CIM (Common Information Model) ECS (Elastic Common Schema) フィールド指定 process_name(CIM) process.name(ECS) 否定 NOT not / != ワイルドカード * * (: または like 演算子) ⚠️ これは厳密な機能対応ではなく、考え方を理解するための対応表です。 Splunk の transaction はイベントをまとめて後処理するイメージが強く、EQL の sequence は「順序あるイベント列」をネイティブに表現する処理です。考え方として近い、というレベルで捉えてください。 同じ検出を SPL と EQL で書き比べる シナリオ: PowerShell が実行され、30 秒以内に外部 HTTPS 接続が発生 Splunk SPL: (index=endpoint sourcetype=process process_name="powershell.exe")   OR (index=endpoint sourcetype=network dest_port=443) | transaction host maxspan=30s | where mvcount(sourcetype)>1 Elastic EQL: sequence by process.entity_id with maxspan=30s   [process where process.name == "powershell.exe"]   [network where destination.port == 443] EQL の方が「 意図がそのまま構文になっている 」のがわかります。「これが起きて、次にこれが起きる」と読める。(process.entityの代わりに広域な相関で host.name を使う事も可能です) EQL の SPL に対する優位点 実務でメリットになるのは、おおむね以下の点です。 構文が攻撃チェーンのメンタルモデルと一致 — sequence … [event A] [event B] という形が、そのままアナリストの思考順序になる 時間ウィンドウの指定が一行 — with maxspan=30s を足すだけ ECS により書いたクエリの再利用性が高い — process.name を含むデータであれば、Windows、Linux、各種 EDR を横断して同じクエリが使える 検知ルールにそのまま流用可能 — Elastic Security の Detection Engine が EQL をネイティブサポート オープンスタンダードに沿った設計 — ECS は OpenTelemetry の Semantic Conventions に統合される方向で進化している 逆に EQL が苦手なこと も正直に書いておきます。 大規模な統計集計(カウント、平均、グルーピング)→ ES|QL や Lens の方が向いている 複雑な条件分岐や後処理 → ES|QL を併用するのが現実的 フィールド同士の比較(例:「1 回目の host.name と 2 回目の host.name が違う」)→ EQL 単独では難しい。ES|QL での後続分析と組み合わせる EQL は「 順序ある脅威検出 」のためのツール。集計や複雑な比較が必要なら別のツールと組み合わせるのが Elastic 流です。 EQL の基本構文 ここから手を動かす段階に入ります。 最小単位の形 event_category where condition たったこれだけ。読むと: event_category:何のイベントを見るか(process、file、network、authentication、registry など。内部的には event.category の値) where:条件を続けますよ、という宣言 condition:実際の条件 例 1:PowerShell 実行の検出 process where process.name == "powershell.exe" 例 2:複数条件の組み合わせ process where process.name == "powershell.exe"   and process.command_line : "*DownloadString*" ここで重要な演算子を整理しておきます。 EQL の演算子チートシート 演算子 意味 使いどころ == 厳密一致(大文字小文字を区別) プロセス名、ポート番号など正確に一致させたい時 != 一致しない 除外条件 : 大文字小文字を区別しない文字列一致 (ワイルドカード *、? 対応) パス、コマンドライン、拡張子(実体は like~ と等価) like ワイルドカード一致(大文字小文字を 区別する ) パターンマッチ like~ ワイルドカード一致(大文字小文字を 区別しない ) : と同じ in リストのいずれか(区別あり) process.name in (“cmd.exe”, “powershell.exe”) in~ リストのいずれか(区別なし) 大文字小文字が揺れるデータに not 否定 not process.name == “explorer.exe” and / or 論理演算子 条件の組み合わせ 💡 メモ: : は「ワイルドカードが使える ==」と覚えると間違いません。文字列の比較で、== より柔軟(大文字小文字も吸収、* ? も使える)。 == と : の使い分け(ハマりやすい) # ❌ ハマるパターン:ファイル拡張子に == を使うと小文字限定 file where file.extension == "exe"   # .EXE は引っかからない # ✅ : を使えば大文字小文字の揺れを吸収 file where file.extension : "exe"    # .exe も .EXE もマッチ Windows の拡張子は大文字小文字が混在することがよくあります。ファイルパスや拡張子は基本的に : を使う方が安全です。 ECS:Elastic Common Schema を理解する EQL を本気で使うには、 ECS の理解が欠かせません。これは Splunk の CIM に相当する概念です。 ECS とは何か ECS は「 Elasticsearch にイベントデータを保存するときの共通フィールド仕様 」です。 セキュリティログは多種多様なソースから来ます。 Windows Sysmon Linux Auditd ファイアウォール EDR クラウドサービスの監査ログ これらが全部バラバラのフィールド名(proc_name、process_name、pname、Image…)だと、検索のたびにスキーマを覚え直す羽目になります。 ECS はこれを process.name のような共通名に統一する仕様です。 ECS 対応のデータであれば、同じ意味の情報を同じフィールド名で扱える ようになります。 ⚠️ 注意: ECS は「共通化のルール」であって「すべてのデータソースが必ず全フィールドを持つ」保証ではありません。たとえばネットワーク機器のログには通常 process.name がありません。実際にどのフィールドが入っているかは、データソースやインテグレーションによって異なるため、Kibana の Discover や Data Views で確認してから書く習慣をつけましょう。 セキュリティで頻出する ECS フィールド 実務でほぼ毎日使うフィールドを覚えておきましょう。 プロセス フィールド 内容 process.name プロセス名(例:powershell.exe) process.executable フルパス(例:C:\Windows\System32\powershell.exe) process.command_line コマンドライン全文 process.pid プロセス ID(OS が割り当てる数値) process.entity_id プロセスの一意識別子(Elastic Defend などが付与。 推奨 ) process.parent.name 親プロセス名 process.parent.entity_id 親プロセスの entity_id 💡 process.pid と process.entity_id の違い: PID は OS のプロセス識別子ですが、プロセス終了後に 再利用される ため、長い時間ウィンドウのクエリでは別プロセスのイベントが混ざる可能性があります。Elastic Defend や Sysmon が付与する process.entity_id はプロセスごとに一意な値なので、sequence の by 句では process.entity_id を優先 します。 ファイル フィールド 内容 file.path フルパス file.name ファイル名 file.extension 拡張子(. なし) file.size バイト数 file.hash.sha256 SHA256 ハッシュ ネットワーク フィールド 内容 destination.ip 接続先 IP destination.port 接続先ポート source.ip 送信元 IP network.protocol プロトコル network.direction 通信の向き。 ホスト視点 なら ingress / egress 、 ネットワーク観測点視点 なら inbound / outbound / internal / external 💡 network.direction の値はデータソースによって違う: Elastic Defend や endpoint 系(Auditbeat、Sysmon 経由)は ingress / egress を使う傾向、Packetbeat や Zeek のような observer 系(ネットワーク監視目線)は inbound / outbound を使う傾向です。クエリを書く前に Discover で実際の値を確認しましょう。 イベント / 主体 フィールド 内容 event.category イベント大分類(process、file、network 等)。 EQL の必須フィールド event.type ECS 標準のサブタイプ(creation、start、end、connection 等) event.action データソース固有のアクション名(ソースによって値が異なる) event.outcome success / failure user.name ユーザー名 host.name ホスト名 @timestamp イベント時刻。 EQL の必須フィールド 💡 event.type と event.action の違い: event.type は ECS が定義する 標準化されたサブタイプ (creation、deletion、start、connection など決められた値)。event.action は データソース固有のアクション名 (Windows なら file-created、Sysmon なら FileCreated など値がバラバラ)。 ポータブルなクエリを書くなら event.type を使うのが基本 です。 タスク文を EQL に変換するフレームワーク 検知エンジニアリングで一番難しいのは、「日本語の脅威シナリオを、ECS フィールドと EQL に翻訳すること」です。これさえ身につければ、新しい脅威ハンティングのアイデアをすぐクエリにできるようになります。 5 ステップ翻訳法 どんな日本語のシナリオも、次の 5 つの問いに答えれば EQL になります。 Step 1. 何のイベント?     → event.category     (process / file / network …) Step 2. どんなアクション?  → event.type        (creation / start / connection …) Step 3. 何に対して?       → file.* / process.* (オブジェクト) Step 4. 誰が引き起こした?  → process.* / user.* (主体) Step 5. 順序や時間制約?    → sequence / maxspan (流れ) 実演:タスク文を 5 ステップで翻訳する タスク: 「 実行ファイル が Word ドキュメント を 作成し 、30 秒以内に大量のデータ送信が起きたケースを検出したい」 誰が? → 実行ファイル 何を? → Word ドキュメント どうした? → 作成した EQL では、この「誰が・何を・どうした」を ECS フィールドに置き換えていきます。 誰が? → process.executable 何を? → file.extension どうした? → event.type つまり、今回の前半部分はこういう考え方になります。 .exe の実行ファイルが .doc / .docx の Word ドキュメントを 作成した file where event.type == "creation" and process.executable : "*.exe" and file.extension : ("doc", "docx") ここで大事なのは、 file.*  と  process.*  の見方です。 file.*  は、 作られたもの の情報です。 今回であれば、作られたものは Word ドキュメントなので、 file.extension : ("doc", "docx")  になります。 一方で、 process.*  は、 そのイベントを起こしたプログラム の情報です。 今回であれば、Word ドキュメントを作ったのは実行ファイルなので、 process.executable : "*.exe"  になります。 つまり、ファイル作成イベントでは、次のように考えるとわかりやすいです。 process が file を event.type した 今回なら、こうです。 .exe が .doc/.docx を creation した 次に、後半の条件「30 秒以内に大量のデータ送信が起きた」を見ます。 これはネットワークイベントです。大量のデータ送信は、たとえば  source.bytes  で表現できます。 「作成」→ 「30 秒以内」→ 「大量送信」、流れの検出 → sequence + maxspan sequence with maxspan=30s   [file where event.type == "creation"     and process.executable : "*.exe"     and file.extension : ("doc", "docx")]   [network where source.bytes > 1000000] 完成です。日本語から EQL までの距離が、思ったより近いのが伝わったでしょうか。 キーワード → ECS フィールドの早見表 翻訳作業でつまずきやすい「日本語キーワード」と「対応する ECS フィールド」の対応表です。 日本語キーワード 条件フィルター よく組み合わせるフィールド 実行された / 起動された event.type == "start" process.name 、 process.executable 作成された / 保存された event.type == "creation" file.name 、 file.path 、 file.extension 削除された event.type == "deletion" file.* 変更された event.type == "change" file.* 、 registry.* 外部に通信 / 接続 event.type == "connection" destination.ip 、 destination.port ログインした event.category == "authentication" event.outcome 、 user.name 、 source.ip sequence と時間制約:流れの検出 EQL の真骨頂は sequence です。詳しく見ていきます。 構文 sequence [by FIELD] [with maxspan=TIME]   [event_category where condition_1]   [event_category where condition_2]   [event_category where condition_3] by FIELD:イベント間を「何でつなぐか」(join key)。host.name、process.entity_id、user.name など with maxspan=TIME:「全体が何秒以内に起きたら検出するか」(s / m / h / d) […]:各ステップのイベント条件 by の力:複数フィールドで相関 sequence by host.name, user.name with maxspan=5m   [authentication where event.outcome == "failure"]   [authentication where event.outcome == "success"] 「同じホスト、同じユーザーで、ログイン失敗の後に成功」を 5 分以内で検出。 ブルートフォースの成功 を捕まえる典型パターンです。 イベント間で値を引き継ぐ:per-event by ここが少しトリッキーで、よく間違えるところです。 やりたいこと: ファイルが作られて、その 同じファイル名 のプロセスが起動した sequence by host.name with maxspan=1m   [file where event.type == "creation" and file.extension : "exe"] by file.name   [process where event.type == "start"] by process.name sequence by host.name で ホスト全体の相関 、各 […] の後の by file.name / by process.name で 値を引き継ぎ ます。これにより「file.name == process.name」という相関が成立。 ⚠️ 重要: by のキー数は 全イベントで揃える必要があります 。[eventA] には by を付けて [eventB] に付けない、という書き方はできません。全イベントに付けるか、付けないかのどちらかです。 maxspan の選び方 シナリオ 推奨 maxspan プロセス起動 → 即時通信 30s 〜 1m マルウェア配置 → 実行 1m 〜 5m ログイン → 横展開 5m 〜 30m 内部偵察 → 権限昇格 1h 〜 4h 持続化 → 後日の C2 1d 以上(要注意:誤検知も増える) 短すぎると正規の動作も誤検知、長すぎると無関係なイベントが混ざる。 ここは仮説に基づいてチューニングする 領域です。 実例:セキュリティ検出パターン 5 選 そのままルールとして登録できる形にしてあります。 パターン 1:暗号化されていない通信の検出(コンプライアンス) network where event.type == "connection"   and (     (destination.port == 80 and network.protocol == "http") or     (destination.port == 21 and network.protocol == "ftp")   )   and network.direction in ("egress", "outbound") 社内から外向きの HTTP/FTP を可視化。PCI-DSS や社内ポリシー違反の検出に使えます。 パターン 2:PowerShell ダウンロードからの C2 接続 sequence by process.entity_id with maxspan=30s /* * Step 1: * PowerShell が起動されたイベントを探す。 * process.entity_id で後続の network イベントと同じプロセスに紐づける。 */ [process where event.type == "start" and process.name : "powershell.exe" /* * PowerShell のコマンドラインに、 * ダウンロードやコード実行でよく使われる文字列が含まれているかを見る。 * IEX / Invoke-Expression は、文字列として取得したコードを実行する時によく使われる。 * DownloadString / Net.WebClient は、外部からスクリプトやペイロードを取得する時によく使われる。 */ and ( process.command_line : "*IEX*" or process.command_line : "*DownloadString*" or process.command_line : "*Invoke-Expression*" or process.command_line : "*Net.WebClient*" ) ] /* * Step 2: * 同じプロセスが 30 秒以内に HTTPS 通信しているかを見る。 * destination.port == 443 は HTTPS 通信の代表的なポート。 */ [network where event.type == "connection" and destination.port == 443 /* * 接続先がプライベート IP ではないことを確認する。 * つまり、社内ネットワークではなく外部サーバーへ通信している可能性を見る。 */ and not cidrmatch( destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" ) ] PowerShell が「ダウンロード系」のコマンドを実行して、直後にプライベート IP 以外 へ HTTPS 接続したケース。C2 ビーコンの典型形です。 ✅ ポイント: by process.entity_id で 同一プロセス内の流れ に限定しています。process.pid は再利用されるため誤検知の原因になりますが、process.entity_id は一意なので安全。 パターン 3:Office アプリからのプロセス起動(Living off the Land) process where event.type == "start"   and process.parent.name : ("winword.exe", "excel.exe", "powerpnt.exe", "outlook.exe")   and process.name : ("cmd.exe", "powershell.exe", "wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe") Office アプリがシェル系プロセスを起動するのは、ほぼマクロ起点の攻撃。 現代の標的型攻撃で最頻出のパターン で、誤検知も少なめ。検知ルールとしてまず入れたい一本です。 パターン 4:マルウェア配置 → 実行 → C2 通信 sequence by host.name with maxspan=2m /* * Step 1: * 同じホスト上で、Temp フォルダに実行可能ファイルが作成されたイベントを探す。 * Temp フォルダは、マルウェアやドロッパーが一時的にファイルを置く場所としてよく使われる。 */ [file where event.type == "creation" and file.path : "*\\Temp\\*" /* * exe / dll / scr は、攻撃で使われやすい実行可能ファイルの拡張子。 * exe は通常の実行ファイル、dll はライブラリ、scr はスクリーンセーバー形式だが実行可能。 */ and file.extension : ("exe", "dll", "scr") ] by file.name /* * Step 2: * 直後に、作成されたファイルと同じ名前のプロセスが起動されたかを見る。 * ここでは by file.name と by process.name を使い、 * 「作られたファイル名」と「起動したプロセス名」を結びつけている。 */ [process where event.type == "start"] by process.name /* * Step 3: * さらに、そのプロセスが外部通信でよく使われるポートへ接続したかを見る。 * 80 / 443 は HTTP / HTTPS、 * 8080 は代替 HTTP、 * 4444 は攻撃ツールやリバースシェルで使われることがある代表的なポート。 */ [network where event.type == "connection" and destination.port in (80, 443, 8080, 4444) ] by process.name Temp に実行ファイルが落ちて → そのファイルが起動して → 外部通信、までを 2 分以内に検出。 ドロッパー型マルウェアの典型挙動 です。 パターン 5:横展開の検出(ラテラルムーブメント) sequence by user.name with maxspan=30m /* * Step 1: * あるユーザーでログイン成功イベントが発生したかを見る。 * 横展開では、攻撃者が盗んだ認証情報を使って、 * まずどこかの端末やサーバーへログインすることがある。 */ [authentication where event.outcome == "success"] /* * Step 2: * 同じユーザーの操作として、横展開で使われやすいツールが起動されたかを見る。 * * psexec.exe: * Windows 環境でリモート端末上にコマンドを実行するためによく使われる。 * * wmic.exe: * WMI を使って、リモート端末の情報取得やコマンド実行に使われることがある。 * * winrm.exe: * Windows Remote Management を使ったリモート操作に関係する。 */ [process where event.type == "start" and process.name : ("psexec.exe", "wmic.exe", "winrm.exe")] /* * Step 3: * その後、同じユーザーで再びログイン成功イベントが発生したかを見る。 * これは、別の端末やサーバーへ移動した可能性を確認するためのステップ。 */ [authentication where event.outcome == "success"] 「同じユーザーで、ログイン成功 → 横展開系ツール実行 → ログイン成功」という流れを 30 分以内で検出。 侵入後の活動段階 を捕まえます。 ⚠️ EQL の限界: 「 別ホスト へのログイン」まで厳密に判定したい(1 回目と 2 回目の host.name が違う、という条件)場合、EQL の by 句では「値が等しい」しか表現できないため、これだけでは難しいです。実務では次のどちらかで対応します。 EQL でこのクエリを実行して候補を絞り、Detection Rule の Investigation Guide で host.name の違いを確認する ES|QL で後続分析する(同じユーザーが複数ホストにログインしているかを集計) よくあるミス と正しい書き方 実務でハマる典型パターンです。 ミス 1:ECS でないフィールド名を使う # ❌ process where proc_name == "powershell.exe" # ✅ process where process.name == "powershell.exe" 対策: Kibana の Data Views でフィールド名を確認するクセをつける。SPL からの移行者がいちばんやりがちなミス。 ミス 2:大文字小文字の罠 # ❌ 大文字の .EXE は引っかからない file where file.extension == "exe" # ✅ file where file.extension : "exe" ミス 3:event.action と event.type の混同 # ⚠️ 動くかもしれないが、データソース依存(値が "file-created" や "FileCreated" など揺れる) file where event.action == "creation" # ✅ ECS 標準化された値を使う file where event.type == "creation" ミス 4:sequence の順序逆転 sequence は 書いた順 = 起きた順 です。 # ❌ 通信が先、プロセス起動が後…と書いている sequence by process.entity_id   [network where destination.port == 443]   [process where process.name : "powershell.exe"] # ✅ 「PowerShell 起動 → 通信」のシナリオなら sequence by process.entity_id   [process where process.name : "powershell.exe"]   [network where destination.port == 443] シナリオを先に 日本語で書き下す と、順序ミスが減ります。 ミス 5:maxspan の単位忘れ # ❌ 単位なしはエラー with maxspan=30 # ✅ with maxspan=30s s(秒)/ m(分)/ h(時間)/ d(日)を必ずつける。 ミス 6:EQL 関数の大文字小文字を間違える EQL の 関数名は大文字小文字を区別 します。これでハマる人は多いです。 # ❌ Unknown function エラーになる not cidrmatch(destination.ip, "10.0.0.0/8") # ✅ camelCase が正解 not cidrMatch(destination.ip, "10.0.0.0/8") よく使う関数の正しいスペル: cidrMatch 、 startsWith 、 endsWith 、 stringContains 、 indexOf 、 concat 。関数を大文字小文字を無視させたいときは ~ を付けます(例: endsWith~(file.path, ".exe") )。 ミス 7:関数の引数の大文字小文字でヒットしない 関数名そのものに加えて、 関数の引数(比較対象の文字列)もデフォルトで大文字小文字を区別 します。Windows のファイルパスのように大文字小文字が揺れるデータでは、これで取りこぼします。 # ❌ .EXE や .Exe は引っかからない(小文字 .exe のみマッチ) file where endsWith(file.path, ".exe") or endsWith(file.path, ".dll") # ✅ ~ を付けると大文字小文字を吸収 file where endsWith~(file.path, ".exe") or endsWith~(file.path, ".dll") ルール: 関数を大文字小文字を無視させたいときは、関数名の末尾に ~ を付けます。 endsWith~ 、 startsWith~ 、 stringContains~ 、 indexOf~ などすべての文字列関数で使えます。 💡 : と endsWith~ の使い分け: 単純な拡張子チェックなら file.extension : "exe" で十分。 endsWith~ はパス末尾や任意の文字列末尾を見たいとき(例: process.command_line の末尾)に便利です。 実際に動かす方法 方法 1:Kibana の Dev Tools で試す 最も手軽な方法。 POST logs-endpoint.*/_eql/search {   "query": """     sequence by process.entity_id with maxspan=30s       [process where process.name : "powershell.exe"]       [network where destination.port == 443]   """ } POST logs-endpoint.*/_eql/search 方法 2:Elastic Security の Timeline Elastic Security の「Timeline」では、UI から直接 EQL クエリを実行できます。脅威ハンティングのインタラクティブな探索に向いています。 方法 3:Detection Rule として登録 Elastic Security → Manage → Rules → Create new rule Rule type で「 Event Correlation 」を選択(これが EQL) クエリを貼り付け 重要度、MITRE ATT&CK タグ、Investigation Guide を設定 Save & enable 検証用のテストを必ず通してから本番有効化することをおすすめします。 まとめ EQL は「 順序ある脅威検出 」のために作られたクエリ言語 EQL を動かす前提は @timestamp と event.category の 2 フィールド Splunk SPL の transaction に近い考え方だが、構文が 攻撃チェーンのメンタルモデルに直結 している ECS は『同じ意味のデータには同じフィールド名を使う』というルール。だから 1 つのクエリで複数データソースに対応できる。ただし、すべてのデータソースが ECS の全フィールドを持っているわけではないので、Discover で実際の中身は必ず確認。 5 ステップ翻訳法(What → Action → Object → Actor → Sequence)で、日本語の脅威シナリオを EQL に変換できる sequence + maxspan + by が真骨頂。順序と時間ウィンドウを 1 つのクエリで表現 セキュリティ運用の効率は、「使えるクエリ言語」と「使える脅威モデル」の組み合わせで決まります。EQL は前者の強力な武器です。 Elastic 公式の Detection Rules リポジトリ をフォローして、新ルールをキャッチアップ 参考資料 EQL Syntax Reference (Elastic 公式) Event Query Language Overview Event correlation (EQL) r ules | Elastic Security Elastic Common Schema (ECS) Reference ECS Categorization Field: event.type ECS File Fields ECS Process Fields Elastic Security Detection Rules(GitHub) MITRE ATT&CK Framework ElasticsearchのためのLuceneクエリ入門ガイド The post セキュリティエンジニアのための EQL 入門:Elastic で脅威を見つけるクエリ言語 first appeared on Elastic Portal .
― マルチモーダル embedding の可能性と限界 ― サイオステクノロジー株式会社 Saman Elasticsearch のベクトル検索といえば、これまではテキストや画像が中心でした。 しかし最近は、テキスト・画像・動画・音声を同じ埋め込み空間で扱える「マルチモーダル embedding」が現実的な選択肢になってきています。 本記事は、Elastic Inference Service (以下 EIS) で利用できる .jina-embeddings-v5-omni-small を使い、音声ファイルを Elasticsearch に保存して kNN 検索でどこまで使えるかを検証した PoC のレポートです。 結論を先に書くと、次のとおりです。 音声を embedding 化して Elasticsearch に保存し、kNN で検索する 基本パイプラインは問題なく動いた 音声 → 音声(audio-to-audio) の類似検索は期待どおりに機能した 一方で テキスト → 音声(text-to-audio) の意味検索は、今回の条件では十分な精度が出なかった 技術ブログとして、うまくいった部分だけでなく「なぜうまくいかなかったか」も合わせて共有します。同じような検証を計画している方の参考になれば幸いです。 目次 マルチモーダル embedding と Jina v5 Omni embedding とは Jina Embeddings v5 Omni なぜ音声を検索可能にしたいか システム構成 インデックスの mapping 検証データ 音声を embedding 化して保存する Step 1: 音声を Base64 に変換する Step 2: EIS に送って embedding を生成してもらう Step 3: 返ってきた embedding を受け取る Step 4: メタデータと一緒に Elasticsearch に保存する 検証1: audio-to-audio 検索 結果 検証2: text-to-audio 検索 結果 なぜ text-to-audio は弱かったのか 1. 検証データが「音響的に似すぎている」 2. テキストと音声の意味空間が完全には揃っていない 3. 音声が短く、意味的な信号が少ない まとめ 改善方針: transcript と組み合わせた Hybrid Retrieval まとめ 参考資料 マルチモーダル embedding と Jina v5 Omni embedding とは embedding とは、データを数値ベクトルに変換したものです。たとえば「ログインできない」と「アカウントに入れない」は意味が近いので、embedding にすると近い位置のベクトルになります。 ログインできない        → [0.12, -0.03, 0.45, …] アカウントに入れない    → [0.11, -0.04, 0.46, …]   ← 近い 今日の天気は晴れです    → [0.92,  0.31, -0.20, …]  ← 遠い これまでは、テキストはテキスト用モデル、画像は画像用モデルと、モダリティごとに別の embedding 空間を使うのが一般的でした。 マルチモーダル embedding は、テキストも画像も音声も「同じ空間」に埋め込みます。同じ意味を持つテキストと音声が、空間上で近い位置に置かれることが理想です。 Jina Embeddings v5 Omni 今回使ったのは Jina AI のマルチモーダル embedding モデルです。Elastic Search Labs でも、テキスト・画像・動画・音声を 1 つの Elasticsearch インデックスに保存して横断的に検索できるモデルとして紹介されています。 EIS では preconfigured な inference endpoint として以下が利用できます。 .jina-embeddings-v5-omni-small(出力次元: 1024) 利用可能なモデルは、Dev Tools で  GET _inference  を実行することで確認できます。 ここで重要なのは、今回使用するモデルは ChatGPT のような 回答を生成する LLM ではなく、ベクトル変換のための embedding モデル だという点です。ここを混同すると後段の評価がブレるので、最初に押さえておきます。 なぜ音声を検索可能にしたいか ビジネス的な動機は明確です。音声データの「中で何が話されているか」で検索したいというニーズは、現場にたくさんあります。 コールセンター音声から「ログインできない」と話している通話を見つけたい 問い合わせ音声を内容で分類して FAQ を改善したい 障害発生時に「画面が固まる」「決済できない」といった声が急増していないか確認したい 顧客との会話音声から、契約・解約に関する文脈を後から探したい 社内セミナーや会議音声から、必要な情報を探したい 医療の現場で、音声カルテから何かを検索したい これらは現在、文字起こし(transcript)してから text search で実現するのが普通です。マルチモーダル embedding が一定の精度で動くなら、文字起こしを介さずに 音声そのもの を検索対象に加えられる可能性があります。 また、音声データには機密情報が含まれることが多く、外部 API には投げにくいケースが少なくありません。Elastic 内で inference・indexing・検索・アクセス制御を統合できれば、データを外に出さずに音声検索基盤を構築できる点も大きなメリットです。 システム構成 今回の構成はシンプルです。 音声ファイル(.wav)        │ Base64 エンコード        ▼ Elastic Inference Service (.jina-embeddings-v5-omni-small)        │ 1024 次元 embedding        ▼ Elasticsearch (dense_vector field)        │ kNN 検索        ▼ 類似音声 / 類似テキスト クライアント側(今回はローカル Mac の Python スクリプト)では、音声ファイルを Base64 化して EIS に送るだけです。embedding 生成自体は EIS 側で実行されるため、GPU やモデル管理をローカルに持つ必要はありません。 インデックスの mapping embedding を保存するインデックスの mapping は次のとおりです。 PUT audio-poc-jina-eis-v1 { "mappings": { "properties": { "audio_id": { "type": "keyword" }, "file_name": { "type": "keyword" }, "expected_topic": { "type": "keyword" }, "audio_url": { "type": "keyword" }, "embedding": { "type": "dense_vector", "dims": 1024, "index": true, "similarity": "cosine" }, "created_at": { "type": "date" }, "embedding_method": { "type": "keyword" } } } } 設計のポイントは以下です。 dense_vector の dims: 1024 は Jina v5 Omni small の出力次元に合わせる index: true を指定して kNN 検索の対象にする 類似度関数は cosine を選択。ベクトルの長さよりも方向で比較するため、テキスト/音声 embedding では一般的な選択 検証データ 検証用に、短い日本語の問い合わせ音声を5つ用意しました。 ファイル   想定トピック 話している内容 1.wav ログインできない 昨日から何度もログインしようとしていますが、正しいメールアドレスとパスワードを入力してもアカウントに入れません。 2.wav パスワード再設定 パスワードを忘れてしまったので再設定メールを送ったのですが、メールが届かず手続きが進められません。 3.wav クレジットカード決済エラー クレジットカードで支払いをしようとすると毎回エラーが出て、注文を完了できない状態です。 4.wav サービス画面の フリーズ サービスの画面が途中で固まってしまい、急ぎの作業ができないのでとても困っています。 5.wav 契約プランと 請求金額の確認 契約内容について確認したいことがあるので、現在のプランと次回の請求金額を教えてください。 すべて 同じ話者・同じ録音条件 で作成しています。 この条件が、後段で検索結果を解釈するうえで重要 になります。 音声を embedding 化して保存する 本記事のコードは GitHub で公開しています: https://github.com/SIOS-Technology-Inc/elastic-blogs/tree/main/2026-05-15-test-jina-audio ここは PoC の中核なので、少し丁寧にやったことの流れを追います。 Step 1: 音声を Base64 に変換する .wav は バイナリファイル です。HTTP の JSON ボディには通常バイナリをそのまま載せられないので、まず「テキスト」に変換する必要があります。そのために使うのが Base64 です。Base64 は、任意のバイナリデータを ASCII 文字列で表現する方式で、画像や音声を API に渡すときの定番テクニックです。 def audio_to_base64(file_path: Path) -> str: with open(file_path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") 1.wav を変換すると、こんな長い文字列になります。 UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAA... これで、音声を JSON に乗せられる形になりました。 Step 2: EIS に送って embedding を生成してもらう 次に、Base64 化した音声を Elasticsearch の inference API に送ります。EIS で公開されている embedding モデルは、以下の統一エンドポイントで呼び出します。 POST /_inference/embedding/{INFERENCE_ID} {INFERENCE_ID} には、今回は .jina-embeddings-v5-omni-small を指定します。リクエストボディは1行だけです。 { "input": ["data:audio/wav;base64,UklGRiQAAABXQVZF..."] } ここでひとつ重要なのが、Base64 文字列の前についている data:audio/wav;base64, という接頭辞です。これは データ URI と呼ばれる形式で、「この入力は wav 音声データだよ」とモデルに伝える役割を持ちます。同じエンドポイントはテキストも受け付けるので、入力がテキストなのか音声なのかをこの接頭辞で判別しています。 Python で書くとこうなります。 def get_audio_embedding(file_path: Path) -> list: audio_b64 = audio_to_base64(file_path) # data URI プレフィックスで「これは音声」だとモデルに伝える audio_input = f"data:audio/wav;base64,{audio_b64}" response = es.perform_request( "POST", f"/_inference/embedding/{INFERENCE_ID}", headers={ "Accept": "application/json", "Content-Type": "application/json", }, body={"input": [audio_input]}, ) return response["embeddings"][0]["embedding"] 実装で唯一ハマったポイントは、 Acceptと Content-Typeの両方を指定する必要があった ことです。片方しか指定しないと互換バージョンと衝突して 400 エラーになることがありました。気づくまで少し時間を使ったので、同じことを試す方は注意してください。 Step 3: 返ってきた embedding を受け取る EIS が返してくるレスポンスは次のような形です。 { "embeddings": [ { "embedding": [0.012, -0.028, 0.103, -0.057, /* ...計1024個の数値... */] } ] } embeddings[0].embedding を取り出すと、 長さ 1024 の float の配列 が手に入ります。これがその音声の「特徴を数値化したもの」です。人間には意味の分からない数値の羅列ですが、Elasticsearch にとってはこの 1024 個の数字が「似ているか」を判定する材料になります。 Step 4: メタデータと一緒に Elasticsearch に保存する 最後に、embedding をメタデータと組み合わせて、1つの ドキュメント として Elasticsearch に保存します。 indexed_doc = { ... } es.index( ... ) これで、audio-poc-jina-eis-v1 インデックスには次のような JSON ドキュメントが保存されます。 { "audio_id": "audio-001", "file_name": "1.wav", "expected_topic": "ログインできない", "embedding": [0.012, -0.028, 0.103, /* ...計1024個... */], "embedding_method": "elastic_inference_jina_omni_small", "created_at": "2026-..." } 5 つの音声に対してこの処理を繰り返すと、Elasticsearch には 5 件の音声 embedding が並びます。あとは kNN クエリで「近いベクトル」を探すだけ、という状態になりました。 検証1: audio-to-audio 検索 最初に、音声 → 音声の類似検索を試しました。1.wav を query として、最も近い音声を探します。 検索 body はシンプルな kNN クエリです。 { "knn": { "field": "embedding", "query_vector": [/* query 音声の 1024 次元 embedding */], "k": 5, "num_candidates": 10 }, "_source": ["audio_id", "file_name", "expected_topic"] } 結果 1.wav を query にした場合: 1位: 1.wav score: 0.99999 2位: 3.wav score: 0.99142 3位: 5.wav score: 0.99125 4位: 4.wav score: 0.98703 5位: 2.wav score: 0.98342 次、5.wav を query にした場合: 1位: 5.wav  score: 1.0000001 ※ ※ cosine 類似度ベースの kNN スコアは (1 + cos) / 2 で計算されるため理論上の上限は 1.0 です。query ベクトルとインデックス側ベクトルが同一の場合に、浮動小数点演算の丸め誤差で形式上 1.0 をわずかに超えた値が返ることがあります。実質 1.0 と読み替えてください。 期待どおり、query にした音声自身が 1 位になりました。 音声 → 音声の類似検索は正しく動作している と判断できます。 ただし注目すべきは 2 位以下のスコアです。すべて 0.98〜0.99 という非常に高い値に集中しています。1 位は明確に分離できるものの、それ以外は ほぼ団子状態 です。この観察は、次の text-to-audio の議論の伏線になります。 検証2: text-to-audio 検索 次に、日本語テキスト query から音声を探します。クエリは同じく kNN ですが、query_vector を「テキストから生成した embedding」に差し替えます。クライアント側のコードはほぼ同じで、入力をテキストに切り替えるだけです。 結果 query: ログインできない (期待: 1.wav が1位) 1位: 5.wav (契約プランと請求金額の確認)  score: 0.54343 2位: 1.wav (ログインできない) score: 0.54301 3位: 3.wav (クレジットカード決済エラー) score: 0.54214 少し長めの query でも試しました。 query: 正しいメールアドレスとパスワードを入力してもアカウントに入れません 1位: 5.wav 2位: 1.wav 期待した 1.wav は 1 位になりませんでした。さらに、上位 3 件のスコアが 0.543 前後に密集しており、意味的な分離がほとんど効いていないことが分かります。 つまり、 今回の条件では text-to-audio 検索の精度は実用レベルに届かなかった ということです。 なぜ text-to-audio は弱かったのか この PoC で最も重要なメッセージは、ここにあります。「マルチモーダルであれば何でも検索可能」というわけではない、という現実を共有できるかもしれません。 考えられる要因は複数あります。 1. 検証データが「音響的に似すぎている」 今回の 5 つの音声は、すべて以下の条件で作られています。 同じ話者 同じ口調 同じ録音条件(マイク、室内環境、無音区間の入り方) 同じくらいの長さ(10〜15 秒) 同じ「問い合わせ口調」の文体 audio embedding は、内容(何を話しているか)だけでなく、 話者の声質・録音条件・話すトーン・無音区間 といった音響的な特徴も拾います。今回のように音響条件が似すぎたデータでは、内容の違いより「音声としての雰囲気の共通性」が embedding を支配しやすくなります。audio-to-audio 検索で 2 位以下のスコアが 0.98 台に集中していたのは、まさにこの影響と整合します。 2. テキストと音声の意味空間が完全には揃っていない マルチモーダル embedding は「同じ意味のテキストと音声を近づける」ように学習されていますが、その整合性の強さは学習データやモデルサイズに依存します。 今回使ったのは omni-small(軽量モデル) です。日本語の短い問い合わせ音声で text-to-audio の対応関係を十分捉えられるかは、未知数の領域です。スコア差が 0.001 オーダーしかなくノイズに埋もれている状態は、まさにこの「整合性が弱い」状態と読めます。 3. 音声が短く、意味的な信号が少ない 各音声は 10〜15 秒程度です。短い音声ほど、テキスト query との意味的なマッチングに使える信号は少なくなります。数十秒〜数分の音声であれば、もう少し違う結果になった可能性があります。 まとめ audio-to-audio が動いて text-to-audio が弱かったのは「実装ミス」ではなく、 マルチモーダル embedding の現実的な特性と、検証データの条件が組み合わさった結果 だと考えています。 ここから引き出せる教訓はシンプルです。 「ベクトル検索の品質は、モデルだけでなく、データの性質と用途の組み合わせで決まる」 。これはマルチモーダルに限らず、テキスト embedding でも同じことが言えます。 改善方針: transcript と組み合わせた Hybrid Retrieval 実務で音声検索を本気で組むなら、音声 embedding 単体で頑張るより、 文字起こし(transcript)を併用する ほうが圧倒的に現実的です。 具体的にはこんな構成を考えています。 音声ファイル ├─ audio embedding (audio-to-audio 検索用) ├─ transcript text (BM25 / lexical 検索用) ├─ transcript embedding (semantic 検索用) └─ メタデータ (時間、顧客ID、カテゴリなど) │ ▼ Elasticsearch │ ▼ Hybrid Retrieval (RRF などで結果を統合) Elasticsearch には、複数の retriever の結果を統合する仕組みとして Reciprocal Rank Fusion (RRF) があります。これを使うと、以下を 1 リクエストで束ねられます。 音声 embedding による kNN(似た音声を探す) transcript embedding による kNN(意味の近い発話を探す) transcript への BM25(キーワード検索) メタデータでの filter(期間、顧客カテゴリなど) ユーザーが「ログインできない」と検索したとき、文字起こしテキスト側がしっかり 1.wav にマッチしてくれるはずです。音声 embedding はその上で「似た声質・トーンの問い合わせ」を補強する役割で使う、という役割分担が現実的です。 次のステップとして、この hybrid 構成を実装し、再度同じ query で評価してみる予定です。 まとめ 今回の PoC で確認できたことは次のとおりです。 EIS 経由で音声 embedding を生成できる — .jina-embeddings-v5-omni-small に Base64 音声を送ると 1024 次元の embedding が返る dense_vector に保存して kNN 検索できる — マルチモーダル検索の土台は問題なく動く audio-to-audio 検索は実用的に機能する — 同じ音声を query にすればその音声が 1 位に返る text-to-audio 検索は今回の条件では弱かった — 短く・音響条件が似た音声群では、テキスト query との意味的な分離が困難 ここから得た一番の学びは、 「マルチモーダル embedding は万能ではなく、ユースケースに合わせて他の検索手段と組み合わせて使うもの」 という現実です。 参考資料 Elastic Search Labs: Jina Embeddings v5 Omni — all media, one index https://www.elastic.co/search-labs/jp/blog/jina-embeddings-v5-omni-all-media-one-index Jina AI: jina-embeddings-v5-omni-small model card https://jina.ai/models/jina-embeddings-v5-omni-small/ Elasticsearch: dense_vector field type / kNN search / Reciprocal Rank Fusion (RRF) https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector.html Elastic Inference Service https://www.elastic.co/docs/explore-analyze/elastic-inference/eis The post Elastic Inference Service と Jina Embeddings v5 Omni で音声を検索する first appeared on Elastic Portal .
目次 はじめに 前提条件と準備 1. AI Agent でのモデル切り替え 2. Streams での活用:パーティショニング(分割提案) 2.1. Wired Streams の有効化 2.2. LLM によるパーティション分割 3. Streams での活用:プロセッシング(Grok パターン生成) まとめ 参考URL はじめに 先月のブログ、 Elastic Inference Service (EIS) を使った「ベクトル検索」および「生成AIによる回答(RAG)」(実践編) では、EIS を通じてセルフマネージドの Elasticsearch 上でクラウド LLM を利用し、ベクトル検索や簡易的な RAG を実現する方法を紹介しました。 今回はさらに一歩踏み込み、EIS 経由で提供されるクラウド LLM を AI Agent(Kibana 内の対話型アシスタント) や、Streams(ログのパーティショニングやパース処理) に適用する方法を解説します。これにより、自前環境のデータを維持しつつ、最新の AI 機能をフル活用できるようになります。 前提条件と準備 本記事では以下の環境・準備を前提としています。 Elastic Cloud: Enterprise License(EIS プロバイダーとして利用) セルフマネージド Elasticsearch: Enterprise License(筆者は v9.4.0 の Trial License で動作確認) EIS の初期設定: Elastic Inference Service (EIS) を使った「ベクトル検索」および「生成AIによる回答(RAG)」(準備編) のガイドに従い、EIS が利用可能な状態であること。 1. AI Agent でのモデル切り替え Elasticsearch 内部のデータ操作やトラブルシューティングを支援する「AI Agent」の思考エンジンとして、EIS 経由のクラウド LLM を設定します。 1.1. セルフマネージド環境の Elastic Home にアクセスします。 1.2. 画面右上の [AI Agent] アイコンをクリックしてチャットパネルを開きます。 1.3. 現在設定されているモデル名をクリックします。 1.4. ローカルモデルに混じって、EIS 経由で接続しているクラウドモデル(OpenAI, Anthropic 等)が表示されるので、利用したいモデルを選択します。 1.5. モデル選択後、AI Agent に質問を投げ、クラウド LLM ならではの高い解釈能力を確認してください。 ※設定した AI Agent は、Workflow 内から呼び出すことも可能です。 2. Streams での活用:パーティショニング(分割提案) 大量のログを効率的に管理するための「Streams」において、LLM を使った高度なパーティション分割(分類)を行うことができます。 2.1. Wired Streams の有効化 まず、LLM 連携に必要な Wired Streams を有効にする必要があります。 2.1.1. Management > Streams 画面を表示します。 2.1.2. 右上の [Settings] をクリックします。 2.1.3. [Wired Streams] をトグルスイッチで有効にします。 2.2. LLM によるパーティション分割 2.2.1. Streams 一覧から、パーティション分割したい Wired Stream を選択します。 (下記の例では、OpenTelemetry 経由で Windows のイベントログを取り込んだ logs.otel.windows Stream をあらかじめ作成しておき、それを選択しています。) 2.2.2. [Partitioning] タブをクリックします。 2.2.3. [Get partitions suggestions] ボタンの右にある 歯車アイコン をクリックし、EIS 経由のモデルを選択します。 2.2.4. [Get partitions suggestions] をクリックすると、LLM がログの内容を分析し、最適なカテゴリ分けを提案してくれます。 この例では、body.structured.channel の値が “Security”, “System”, “Application” の場合に、パーティション分割する案が提示されています。 2.2.5. 提案内容を確認し、適用したい項目にチェックを入れ [Accept selected] をクリックします。 2.2.6. 確認ダイアログが表示されるので、[Create all streams] をクリックします。 2.2.7. Streams のパーティション分割が行われます。しばらく待つと、分割された結果が表示されます。 ! 注意点: LLM の提案が常に最適とは限りません。必ず内容を吟味してから適用してください。 分割後のパーティションに振り分けられるのは、設定完了以降に取り込まれる新しいログのみです。 3. Streams での活用:プロセッシング(Grok パターン生成) エンジニアにとって頭の痛い「Grok パターンによるログパース」も、EIS 経由の LLM で自動化できます。 3.1. 対象 の Stream を選択し、[Processing] タブ > [Interactive] を選択します。 3.2. [Field] 欄で、パースしたい元のフィールド(message など)を指定します。 3.3. [Generate pattern] 横の歯車アイコンで モデル(Anthropic Claude Sonnet 4.6 など)を選択します。 3.4. [Generate pattern] をクリックすると、LLM がログの構造を読み取り、最適な Grok パターンを提示します。 3.5. 内容に問題がなければ [Create] をクリックします。これで Grok Processor が即座に作成されます。 ※ Model Management / Feature Settings の画面で、利用するモデルを選択しておくことも可能です。 まとめ 本記事では、Elastic Inference Service (EIS) を介して、セルフマネージドな Elastic 環境でもクラウド LLM の恩恵を多角的に受ける方法を紹介しました。 AI Agent: インフラ管理の対話型アシスタントを強化。 Streams Partitioning: 複雑なログ分類の自動化。 Streams Processing: 職人芸が必要だった Grok パターン作成の効率化。 EIS を活用することで、「機密データは自社環境(セルフマネージド)で保持しつつ、処理には強力な外部 AI を利用する」というハイブリッドな運用が現実的になります。特に v9.x 以降の Wired Streams 連携は、オブザーバビリティの運用負荷を劇的に下げる可能性を秘めています。 ぜひ、皆さんの環境でも EIS による「AI 駆動の運用」を試してみてください。 参考URL Elastic Documentation: Wired streams v9.2 Tech Previewの新機能Wired Streamsでどこまでログのパースが楽になるかをやってみた Elastic Inference Service (EIS) を使った「ベクトル検索」および「生成AIによる回答(RAG)」(準備編) Elastic Inference Service (EIS) を使った「ベクトル検索」および「生成AIによる回答(RAG)」(実践編)
Linuxは、多くの企業システム、クラウド環境、コンテナ基盤で使われています。 そのため、Linuxカーネルに深刻な脆弱性が見つかると、影響はとても大きくなります。 Elastic Security Labs は、Linuxカーネルの権限昇格脆弱性である Copy Fail (CVE-2026-31431) 、Copy Fail 2、そして DirtyFrag を分析しました。これらは、Linuxの page cache に関係するバグを悪用し、通常ユーザーから root権限 を取得できる可能性がある攻撃です。 特に Copy Fail (CVE-2026-31431) は実際の攻撃で悪用されたことが報告されており、米国CISAの Known Exploited Vulnerabilities (KEV) カタログ にも追加されています。KEVカタログに載るということは、「机上の脆弱性」ではなく「現実に攻撃で使われている脆弱性」であることを意味します。米国の連邦機関は期限内のパッチ適用が義務付けられるレベルであり、民間企業にとっても優先対応すべき強いシグナルです。 この記事では、この攻撃をセキュリティ初心者にもわかるように整理しながら、Elastic Securityがどのように脅威を分析し、検知につなげているのか、そして Elasticが公開している検知ルール を紹介します。 目次 まず、何が危険なのか? page cache とは何か? page cache corruption とは? Copy Fail は何をするのか? DirtyFrag は何が違うのか? ⚠️ ここが最重要:Copy Fail のパッチだけでは不十分 なぜ Elastic の分析が重要なのか? Elastic が公開した検知ルール5本 1. Potential Copy Fail (CVE-2026-31431) Exploitation via AF_ALG Socket 2. Suspicious SUID Binary Execution 3. Suspicious Kernel Feature Activity 4. Namespace Manipulation Using Unshare 5. Privilege Escalation via SUID/SGID 5本のルールがどう連携するか Elastic の強み:すべての検知ルールが GitHub で公開されている これがなぜ重要なのか? 日本のユーザーにとっての意味 ビジネス視点でなぜ重要なのか? まとめ:Elastic Security は「攻撃の形」ではなく「攻撃の動き」を見る 参考リンク まず、何が危険なのか? 今回のポイントは、攻撃者がLinux上で root権限 を取得できる可能性があることです。 rootとは、Linuxにおける最も強い権限を持つユーザーです。 たとえるなら、ビル全体のマスターキーを持つ管理者のような存在です。 通常ユーザーは、自分の部屋や許可された場所にしか入れません。 しかしrootは、システム全体の設定変更、ファイルの読み書き、プロセスの停止、ユーザー作成など、多くの操作ができます。 つまり、攻撃者がroot権限を取ると、次のようなことが可能になります。 機密ファイルを読む セキュリティツールを止める マルウェアを設置する ログを改ざんする 他のシステムへ侵入する足がかりを作る これは、単なる「1台のLinuxサーバーの問題」ではありません。 企業のクラウド環境、コンテナ基盤、業務システム全体に影響する可能性があります。 page cache とは何か? 今回の攻撃を理解するために、まず page cache を理解する必要があります。 page cacheとは、Linuxがファイルアクセスを速くするために使うメモリ上の一時的な保管場所です。 たとえば、図書館をイメージしてください。 本棚にある本が「ディスク上のファイル」だとします。 でも、よく読まれる本を毎回本棚まで取りに行くのは面倒です。 そこで図書館員は、よく使う本のコピーを机の上に置いておきます。 この「机の上のコピー」が、Linuxでいう page cache です。 たとえ Linux 本棚の本 ディスク上のファイル 机の上のコピー page cache 図書館員 Linuxカーネル 本を読む人 アプリケーション 通常、page cacheは便利な仕組みです。 ファイルを毎回ディスクから読むより、メモリから読んだ方が速いからです。 しかし、今回のような脆弱性では、この「メモリ上のコピー」が悪用されます。 page cache corruption とは? page cache corruption とは、簡単に言うと、Linuxが信頼しているメモリ上のファイルコピーを不正に書き換えることです。 重要なのは、攻撃者が必ずしもディスク上の本物のファイルを書き換えるわけではない、という点です。 本物のファイルは変わっていないように見えます。 しかし、Linuxが実際に使うメモリ上のコピーだけが壊されている可能性があります。 これは非常に厄介です。 なぜなら、ファイルの改ざんチェックをしても、ディスク上のファイルは正常に見えることがあるからです。 一方で、システムは壊されたpage cacheの内容を使ってしまう可能性があります。 たとえるなら、会社の正式な契約書は金庫の中で無事なのに、担当者が机の上に置いていたコピーだけがこっそり書き換えられている状態です。 担当者がそのコピーを信じて処理を進めると、間違った判断につながります。 Copy Fail は何をするのか? Elasticの説明によると、Copy Fail は Linuxカーネルの暗号処理(authencesn テンプレート)に関係するロジックバグです。AF_ALG と splice() という Linux の正規機能を組み合わせることで、読み取り可能なファイルのpage cacheに対して、制御された4バイトの書き込みを行えると説明されています。 ここで重要なのは、これが setuidバイナリ に対して使われるという点です。 setuid バイナリとは 実行したユーザーではなく、ファイルの所有者の権限で動く特殊なプログラムです。 たとえば /usr/bin/su は所有者がrootで、setuid が設定されているため、認証処理などの一部の処理をroot権限で実行できます。もちろん、通常はパスワード確認などの認証があるため、誰でも自由にrootになれるわけではありません。 しかし、この「root権限で動く部分」こそが攻撃者の標的になります。Copy Fail のような攻撃では、ディスク上のファイルを直接書き換えるのではなく、page cache上のバイナリ内容を壊すことで、root権限で実行される処理を悪用しようとします。 実際に Copy Fail では、/usr/bin/su のようなsetuidバイナリのメモリ上の見え方を壊し、 ディスク上のファイルを変更せずに権限昇格 につなげることができます。公開されている攻撃コードは、わずか732バイトのPythonスクリプトで、Ubuntu、Amazon Linux、RHEL、SUSE といった主要ディストリビューションで動作します。 ここで重要なのは、攻撃者が「怪しいマルウェア」だけを使っているわけではないことです。 AF_ALG も splice() も、Linuxに存在する正規の仕組みです。 つまり攻撃は、完全に外部から見て明らかに怪しい動作だけで成り立っているわけではありません。 正規のLinux機能を組み合わせて、カーネルの細かいバグを突いています。 これが、検知を難しくします。 DirtyFrag は何が違うのか? DirtyFragも、page cache corruption を悪用する Linuxカーネルの権限昇格攻撃です。 基本の考え方は Copy Fail と似ていますが、 攻撃経路がネットワークスタックに広がっている 点が大きく異なります。 Elasticのブログによると、DirtyFragには2つの経路があります。 経路 使われる仕組み 攻撃対象 結果 ESPパス AF_NETLINK 経由のXFRM SA /usr/bin/su suを最小限のroot shell ELFで上書き RxRPCパス(フォールバック) AF_RXRPC + pcbc(fcrypt) /etc/passwd rootのパスワードフィールドをクリア /etc/passwd のrootパスワードフィールドがクリアされると、環境によってはパスワードなしでrootとして認証が通ってしまう可能性があります。 実際の挙動は、PAM や SSH の設定、shadow ファイルの運用状況によって変わります。しかし、いずれにしても、root認証の前提を壊す重大な改ざんであることに変わりはありません。 さらに、両方の経路ともに unshare(CLONE_NEWUSER | CLONE_NEWNET) を使って namespace capability を取得する前段が必要です。これは、後述する検知ロジックで重要なポイントになります。 ⚠️ ここが最重要:Copy Fail のパッチだけでは不十分 Elasticのブログが警告している最も重要なポイントは次のことです。 DirtyFrag は algif_aead モジュールに依存しません。 つまり、Copy Fail の緩和策(algif_aead を無効化する)だけを適用したシステムは、依然としてDirtyFragに脆弱なままです。 「Copy Fail対策はやったから安心」という思い込みが、最も危険な状態を生みます。 両方の脆弱性に対して、 それぞれ独立した対策が必要 です。 なぜ Elastic の分析が重要なのか? ここからが、Elastic Securityを理解するうえで大事なポイントです。 Elasticは、単に「特定の攻撃コードを見つけましょう」という見方だけをしていません。 セキュリティ研究者は、新しい脆弱性が見つかると、しばしば PoC(Proof of Concept) と呼ばれる実証コードを公開します。これは「この攻撃が本当に可能であることを示すデモコード」であり、防御側が脆弱性を理解し、対策を検証するために使われます。 しかし、攻撃者はこの実証コードをそのままの形で使うとは限りません。 Pythonで書かれたコードを、GoやRustやCに書き換えることもできます。 ファイル名やプロセス名を変えることもできます。実行方法を少し変えることもできます。 実際、Copy Fail はすでに Python / Go / Rust / C / Metasploit など、複数の言語・フレームワークで実装が公開されており、DirtyFrag も C言語版の実装が公開されています。 そのため、 特定の攻撃コードの見た目だけを検知していると、少し変えられただけで見逃す可能性があります 。 Elasticが重視しているのは、攻撃の primitive と behavior です。 primitive とは、攻撃を構成する小さな技術的な部品のことです。 たとえば、ビルへの侵入で考えると、攻撃全体は「不正侵入」です。 その中のprimitiveは、次のような小さな行動です。 鍵をこじ開ける 監視カメラを避ける 裏口を使う 管理室に入る Linux攻撃で言えば、primitiveは次のようなものです。 AF_ALG を使う splice() を使う page cache を壊す setuidバイナリを悪用する unshare() でnamespaceを作る Elasticは、攻撃コードそのものだけでなく、こうした攻撃の部品や行動パターンを見ようとしています。 これは、現代のセキュリティ検知において非常に重要です。 Elastic が公開した検知ルール5本 今回 Elastic Security Labs は、Copy Fail / DirtyFrag に対応する検知ルールを公開しました。 ここで重要なのは、 これらのルールはすべて GitHub で誰でも見られる ということです(後述)。 以下、5本のルールがそれぞれ「何を検知するか」を簡潔に紹介します。 1. Potential Copy Fail (CVE-2026-31431) Exploitation via AF_ALG Socket 何を検知するか: 非rootユーザーが AF_ALG ソケット(暗号処理用の特殊なソケット)と splice() を組み合わせて使い、その後 root 権限のプロセス実行やシェル起動につながる流れ。 攻撃のどこで効くか: Copy Fail の最も核心的なプリミティブを直接捉えます。 前提条件: このルールを有効に活用するには、Linux 上で auditd 系のログを Elastic に取り込んでいる必要があります。具体的には、Elastic Agent の Auditd Manager integration や Auditbeat の設定が必要です。これらがない環境では、socket や splice のような低レベルな syscall の動きは見えません。 🔗 GitHubでルールの実物を見る 2. Suspicious SUID Binary Execution 何を検知するか: su、sudo、pkexec、passwd などのSUIDバイナリが、不審な親プロセス(PythonやRubyなどのスクリプトランタイム、/tmp や /dev/shm といったユーザー書き込み可能パスからの実行)から、最小限の引数で呼び出されるパターン。 攻撃のどこで効くか: Copy Fail / DirtyFrag の両方の 最終段階 (root権限取得の瞬間)を捉えます。auditd が入っていない環境でも、プロセス実行イベントだけで動作するため、適用範囲が広いのが特徴です。 🔗 GitHubでルールの実物を見る 3. Suspicious Kernel Feature Activity 何を検知するか: sysctl などによるカーネル機能の不審な操作。攻撃者が防御機構を無効化したり、カーネル動作を変更したりする動きを捉えます。 位置づけ: このルールは Copy Fail / DirtyFrag 専用というより、攻撃者がカーネル機能を不審に操作する動きを広く見るための補助的な検知です。今回のようなカーネル悪用の文脈でも、関連する不審な操作を見つけるための追加レイヤーとして役立ちます。 🔗 GitHubでルールの実物を見る 4. Namespace Manipulation Using Unshare 何を検知するか: unshare コマンドや syscall によるユーザーネームスペース(特に CLONE_NEWUSER | CLONE_NEWNET)の作成と、その直後の root プロセス実行・setuid(0) の相関。 攻撃のどこで効くか: DirtyFrag 固有の前段 を捉えます。DirtyFrag は namespace の取得が必須なので、ここを潰すと攻撃チェーン全体が成立しなくなります。 前提条件: このルールも、syscall レベルの検知部分は auditd 系のログが必要です。プロセス実行イベントの部分は Elastic Agent / Endpoint で取得できます。 🔗 GitHubでルールの実物を見る 5. Privilege Escalation via SUID/SGID 何を検知するか: SUID/SGIDバイナリを悪用した権限昇格全般のパターン。Copy Fail / DirtyFrag に限らず、類似の権限昇格手法を広くカバーします。 攻撃のどこで効くか: 汎用的な権限昇格の最終段階。Copy Fail / DirtyFrag の派生や、まだ公開されていない類似手法にも備える保険的なルールです。 🔗 GitHubでルールの実物を見る 5本のルールがどう連携するか これらのルールは、それぞれ独立して動きますが、 攻撃の異なる段階を多層的にカバーする設計 になっています。 攻撃者が1つの段階を回避しても、別の段階で検知できる 多層防御(defense in depth) の考え方です。 Elastic の強み:すべての検知ルールが GitHub で公開されている ここで、Elastic Security の重要な特徴をお伝えします。 Elastic は、商用製品の検知ルールをすべて GitHub で公開しています。 リポジトリはこちらです: 🔗 elastic/detection-rules このリポジトリには、Elastic Security で使われる検知ルールが TOML 形式で格納されており、 誰でも自由に閲覧・Fork・コメント・Pull Request 可能 です。 これがなぜ重要なのか? セキュリティ運用において、検知ルールの中身がわからないことは、いくつもの問題を引き起こします。 検知ルールが見られない場合 検知ルールが公開されている場合 アラートが出たが、なぜ発火したかわからない ルールのロジックを読んで理由を理解できる 誤検知が出ても、チューニングできない 条件を読んで、自社環境向けに例外を追加できる 「ベンダーを信じるしかない」状態 自分でレビューして納得できる 検知漏れがあっても、原因がわからない ロジックの穴を発見し、改善提案できる コミュニティ知見が共有されない OSSとしてコミュニティに還元できる なお、検知ルールを公開しているベンダーは Elastic だけではありません。Microsoft Sentinel も Analytics rules を GitHub で公開しており、透明性の高いアプローチを取っています。一方、多くの商用 EDR/SIEM 製品では検知ロジックが非公開で、ユーザーがルールの中身を確認できないことも珍しくありません。Elastic は早い段階からこの公開方針を一貫して続けている点が特徴です。 日本のユーザーにとっての意味 日本では、Elastic を完全に理解しているエンジニアはまだ多くありません。 だからこそ、 ルールがオープンソースとして公開されている ことの価値は大きいです。 英語のブログを完全に理解できなくても、 TOMLファイルを読めば検知ロジックがわかる 社内SOCのナレッジとして ルールを写経・改造して学べる 自社環境特有の誤検知に対して 自分で例外条件を追加できる 日本語コミュニティで ルールの解釈を議論できる ビジネス視点でなぜ重要なのか? この話は、セキュリティ研究者だけのものではありません。 企業にとって重要なのは、次の3つです。 1つ目は、被害の早期発見です。 root権限を取られると、攻撃者はより深くシステムに入り込めます。早く気づければ、被害を小さくできます。 2つ目は、調査時間の短縮です。 SOCやセキュリティ担当者は、毎日多くのアラートを見ています。Elastic Securityのように、攻撃の流れを見せられる仕組みがあると、「これは何が起きているのか」を早く理解できます。 3つ目は、未知・変種への対応力です。 攻撃者は攻撃コードを書き換えます。ツール名も変えます。実行方法も変えます。 しかし、攻撃に必要な基本行動は大きく変わりにくいです。 だからこそ、Elasticが重視している「ふるまい検知」は、ビジネスにとっても価値があります。 まとめ:Elastic Security は「攻撃の形」ではなく「攻撃の動き」を見る Copy Fail や DirtyFrag は、Linuxカーネルの細かいバグを悪用する高度な攻撃です。 しかし、初心者向けに一言でまとめるなら、こう言えます。 Linuxが高速化のために使っている page cache を悪用し、メモリ上のファイル内容を壊すことで、通常ユーザーから root権限を取る攻撃です。 そして、Elastic Security Labs の重要な貢献は、これを単なる脆弱性情報として紹介するだけでなく、 実際の検知ルールに落とし込み、GitHub で公開している 点です。 特定の攻撃コードだけを見るのではなく、攻撃に必要な primitive や behavior を見る。 そして、そのロジックをオープンにすることで、コミュニティ全体の防御力を底上げする。 これは、現代のセキュリティ運用においてとても重要な考え方です。 攻撃者はコードの見た目を変えられます。 しかし、root権限を取るために必要な行動の流れは、完全には隠しにくいです。 Elastic Security は、その流れをデータから見つけるためのプラットフォームです。 そして、その検知ロジックを オープンに、透明に、コミュニティと共に進化させている のが、Elastic の大きな強みです。 参考リンク Elastic Security Labs 原文ブログ: Copy Fail and DirtyFrag: Linux Page Cache Bugs in the Wild Elastic の検知ルールリポジトリ: elastic/detection-rules (GitHub) CISA Known Exploited Vulnerabilities Catalog: CISA KEV この記事は、Elastic Security Labs が公開した英語ブログ「Copy Fail and DirtyFrag: Linux Page Cache Bugs in the Wild」をもとに、日本のElastic利用者向けに整理・補足したものです。 The post Copy Fail / DirtyFrag を検知する:Linux カーネルの page cache 攻撃と5つの検知ルール first appeared on Elastic Portal .
目次 はじめに 検証用リソース 1. Audit Logging とは何か? 2. 監査ログを有効にする方法 elasticsearch.yml の設定例 Docker 環境でのログ出力設定 3. 主要な監査イベントの種類 4. ログ構造の理解(JSON 形式) 5. 実際の Audit Log サンプル 5.1. 認証失敗(存在しないユーザー / パスワード間違い) 5.2. 権限のないインデックスへのアクセス 5.3. 検索の実行とクエリ内容の記録 6. 実践的な運用 Tips ノイズのフィルタリング 7. まとめ 参考資料 はじめに システムのセキュリティを確保する上で、「誰が、いつ、何をしたか」を正確に記録する 監査ログ(Audit Logs) は欠かせません。 特に機密性の高いデータを扱う Elasticsearch クラスターにおいて、 監査ログは不正アクセスの検知やコンプライアンス要件(SOC2、PCI-DSSなど)の達成に不可欠な機能です。 本記事では、Elasticsearch の Audit Logging の仕組み、主要なイベントタイプ、そして運用上のベストプラクティスについて詳しく解説します。 検証環境今回の解説にあたり、以下の環境で動作を確認しています。 Elasticsearch バージョン: 9.4.0 デプロイ形態: Self-Managed (Docker コンテナ) ライセンス: Enterprise (Trial) ※ 監査ログ機能は Enterprise ライセンスでのみ提供されます。 ログ出力先: JSON ファイル 検証用リソース 今回の検証で使用した docker-compose.yml や設定ファイル一式は、以下の GitHub リポジトリで公開しています。 elastic-blogs/2026-05-audit-logging at main · SIOS-Technology-Inc/elastic-blogs A sample code for blogs about Elastic. Contribute to SIOS-Technology-Inc/elastic-blogs development by creating an accoun... github.com 1. Audit Logging とは何か? Elasticsearch の監査機能(Audit Logging)は、クラスター内で発生するセキュリティ関連のイベントを記録する機能です。 これには、認証の成功・失敗、インデックスへのアクセス、セキュリティ設定の変更などが含まれます。 この機能は Elasticsearch の「Security」スタックの一部として提供されており、設定を有効にすることで利用可能になります。 2. 監査ログを有効にする方法 監査ログはデフォルトでは 無効 です。 有効化するには elasticsearch.yml に設定を追加し、ノードを再起動する必要があります。 elasticsearch.yml の設定例 # 監査ログを有効化 xpack.security.audit.enabled: true # 検証用:実行されたクエリ本文(request.body)も記録する xpack.security.audit.logfile.events.emit_request_body: true # 全てのイベントタイプを対象にする(運用時は絞り込みを推奨) xpack.security.audit.logfile.events.include: _all ※GitHub のサンプルでは、docker-compose.yml ファイルで上記を定義しています。 [!CAUTION] emit_request_body を true にすると、クエリに含まれる機密情報(個人情報など)がそのままログに出力される可能性があります。 本番環境での利用には十分注意してください。 Docker 環境でのログ出力設定 今回は Docker コンテナを利用しており、ログ出力を適切に制御するために $ES_HOME/config/log4j2.properties を編集し、 /usr/share/elasticsearch/logs/<クラスター名>_audit.json に出力されるよう構成しています。 3. 主要な監査イベントの種類 記録されるイベントの中でも、特に運用監視で重要なものを紹介します。 イベント名 内容 監視のポイント access_granted 操作が許可された 正常なアクセス。特権操作の追跡に利用。 access_denied 操作が拒否された 権限不足の確認。短時間の多発は攻撃の予兆。 authentication_failed 認証に失敗した 不正なログイン試行、またはアプリの設定ミス。 authentication_success 認証に成功した 特権ユーザー(elastic 等)のログイン監視に。 security_config_change セキュリティ設定変更 ロールやユーザー定義の変更。内部不正防止に重要。 4. ログ構造の理解(JSON 形式) 監査ログは構造化された JSON 形式で出力されるため、SIEM や Kibana での解析が容易です。 timestamp: イベント発生時刻 event.action: イベントの種類(access_granted など) user.name: 操作を行ったユーザー名 origin.address: リクエスト送信元の IP アドレスとポート action: 実行された内部アクション(indices:data/read/search など) url.path: リクエスト先のパス request.body: 実行されたクエリ内容(設定時のみ出力) 5. 実際の Audit Log サンプル ここでは、具体的な操作とそれに対応するログの出力を確認します。 ※今回の検証環境では、/usr/share/elasticsearch/logs/<クラスター名>_audit.json ファイルに出力されます。 5.1. 認証失敗(存在しないユーザー / パスワード間違い) ユーザー名やパスワードを間違えた場合、event.action: “authentication_failed” が記録されます。 実行コマンド: curl -X GET -u dummy:password --cacert ./certs/ca/ca.crt https://localhost:9200/ 出力ログ(抜粋): { "type":"audit", "timestamp":"2026-04-30T01:22:22,842+0000", "event.action":"authentication_failed", "user.name":"dummy", "origin.address":"192.168.143.2:35134", "url.path":"/", "request.method":"GET" } 補足: ログ上はユーザー名間違いとパスワード間違いを区別できませんが、user.name を確認することで、既存ユーザーへの攻撃か未知のユーザーによるものかを判断できます。 5.2. 権限のないインデックスへのアクセス 認証には成功しているものの、操作権限がない場合は access_denied となります。 実行コマンド: # guest1 ユーザー(閲覧権限なし)で検索を実行 curl -X GET -u guest1:password --cacert ./certs/ca/ca.crt "https://localhost:9200/kibana_sample_data_logs/_search?pretty" 出力ログ(抜粋): { "type":"audit", "event.action":"access_denied", "user.name":"guest1", "action":"indices:data/read/search", "indices":["kibana_sample_data_logs"] } 5.3. 検索の実行とクエリ内容の記録 emit_request_body を有効にしている場合、どのようなクエリが投げられたかも記録されます。 実行コマンド: curl -X POST -u elastic:password --cacert ./certs/ca/ca.crt "https://localhost:9200/kibana_sample_data_logs/_search?pretty" \ -d '{"query":{"match":{"geo.dest":"CN"}}}' 出力ログ(抜粋): { "event.action":"authentication_success", "user.name":"elastic", "url.path":"/kibana_sample_data_logs/_search", "request.body":"{\"query\":{\"match\":{\"geo.dest\":\"CN\"}}}" } 6. 実践的な運用 Tips 監査ログは非常に詳細ですが、デフォルトのままではログサイズが膨大になり、ディスクやパフォーマンスに影響を及ぼします。 ノイズのフィルタリング 特定の監視用ユーザーや、信頼できる内部通信をログから除外することで、重要なイベントに集中できます。 設定例: # 特定のイベントを除外 xpack.security.audit.logfile.events.exclude: ["anonymous_access_denied"] # 特定のユーザーを監視対象から除外するフィルタ例 xpack.security.audit.logfile.events.ignore_filters: filter_monitor: users: ["monitor_user"] 7. まとめ Elasticsearch の Audit Logging は、クラスターの透明性を高め、インシデントへの対応力を向上させる強力な武器です。 1. まずは検証環境で有効化し、出力されるログの量と内容を確認する。 2. 必要なイベントに絞り込むことで、ストレージの消費とパフォーマンスへの影響を最小限にする。 3. Kibana や SIEM で可視化し、異常なアクセスパターンを即座に検知できる体制を整える。 セキュリティの第一歩として、ぜひ設定を試してみてください。 参考資料 Elasticsearch Guide: Security event audit logging Audit settings reference https://github.com/SIOS-Technology-Inc/elastic-blogs/blob/main/2026-05-audit-logging/ The post Elasticsearch Audit Logging 解説:セキュリティ監視とコンプライアンスのための第一歩 first appeared on Elastic Portal .
Elastic がバージョン 9.4 をリリースしました。セキュリティ自動化エンジン「Workflows」の正式版リリースを筆頭に、AI によるルール生成・専門知識モジュール(Skills)・クエリ言語 ES|QL の大幅強化など、幅広い領域にわたるアップデートが含まれています。本記事では注目機能を速報でまとめます。 目次 1. Elastic Workflows が正式版(GA)に 2. Elastic AI Agent に専門知識モジュール「Skills」が登場 3. AI による ES|QL 検知ルール自動生成 4. ES|QL クエリ言語の強化 5. ベクトル検索の高速化 6. Kibana の強化 7. Observability:メトリクス・時系列分析の強化 8. セキュリティ:エンティティ管理の深化 まとめ:9.4 の位置付け 参照リンク 1. Elastic Workflows が正式版(GA)に セキュリティ運用の自動化エンジン「Elastic Workflows」が 9.3 の試験公開(Tech Preview)から正式版に昇格しました。 アラートの受信から、ケース作成・担当者割当・Slack 通知・外部システム連携までを YAML または自然言語で定義し、Kibana 内で完結して実行できます。データ移動が不要な点が他の SOAR ツールとの大きな違いです。 主な追加機能: ケース管理ステップが 4 種類 → 25 種類に拡張 :担当者割当・証拠添付・重要度設定・タグ管理など、インシデントの全ライフサイクルに対応 Human-in-the-Loop( waitForInput ) :AI が調査・分類を行い、エスカレーション判断だけをアナリストに委ねる仕組みを正式サポート ワークフローの組み合わせ( workflow.execute ) :マルウェア対応・フィッシング対応などを独立したモジュールとして再利用可能に 制御フロー強化 :switch(多方向分岐)・while(ループ)・loop.break/continue を追加 自然言語でのワークフロー作成 (Tech Preview):攻撃対応シナリオを日本語・英語で説明するだけで YAML を自動生成 最小構成のワークフロー例(YAML): name: Critical アラート対応ワークフロー enabled: true triggers:   - type: alert        # アラート発火を起点に起動 steps:   - name: create_case     type: cases.createCase     with:       owner: securitySolution       title: "{{ event.rule.name }} - {{ event.alerts[0].host.name }}"       severity: high       tags:         - auto-triage 📎 参照: Elastic Workflows GA: automation where your security data already lives 2. Elastic AI Agent に専門知識モジュール「Skills」が登場 従来の AI アシスタントは「すべての知識を1つのプロンプトに詰め込む」設計でした。9.4 では、タスクに応じて専門知識モジュール(スキル)をオンデマンドで切り替える「Skills」アーキテクチャが導入されました。 コンテキストウィンドウを知識ではなく実データに使える分、各スキルの回答精度が向上します。スキルを追加しても既存スキルの品質が落ちない設計が特徴です。 9.4 で搭載された 5 つのセキュリティスキル: スキル 役割 Detection Rule Edit 自然言語から ES|QL 検知ルールを生成・編集 Alert Analysis アラートのトリアージ・関連アラート探索・脅威インテル照合 Threat Hunting 仮説駆動型の脅威ハンティング(横移動・C2 テンプレート内蔵) Entity Analytics ユーザー・ホストのリスクスコア・行動パターンのプロファイリング Security ML Jobs 機械学習ジョブの異常をエンティティコンテキストと相関させて調査 このほか、Kibana ダッシュボード作成・ワークフロー YAML 生成・エンティティ関係グラフ作成の 3 つのプラットフォームスキルも追加されました。 実際の使い方の例(自然言語プロンプトを送るだけ): プロンプト例 起動するスキル 「アラート 82a1f を分析して。認証情報窃取キャンペーンと関連してる?」 Alert Analysis 「過去7日間で侵害されたホストからの横移動をハントして」 Threat Hunting 「今週最もリスクの高いユーザーとその要因を教えて」 Entity Analytics 「svc-backup-prod に関連する異常は何?」 Security ML Jobs 📎 参照: One agent, the right skills: Elastic Security 9.4 brings domain expertise on demand to every SOC workflow 3. AI による ES|QL 検知ルール自動生成 攻撃の挙動を自然言語で記述するだけで、本番対応の ES|QL 検知ルールを AI が自動生成します。ルール作成画面から「AI rule creation」を選択するだけで使用できます。 生成されるもの: ES|QL クエリ(構文検証済み) MITRE ATT&CK マッピング 重要度・リスクスコア タグ・スケジュール設定 生成後はチャット形式で反復的に調整でき、有効化前に自環境の実ログでプレビュー確認が可能です。 実際のプロンプト例(公式ブログより): 「Okta で、同一ユーザー&同一 IP から:3 回以上の認証失敗、1 回以上の MFA 失敗、ログイン成功、その後に権限付与またはポリシー更新。この全シーケンスが揃った場合に、認証情報窃取の成功攻撃として検知して」 これだけで、STATS で各段階をカウントして閾値判定する複雑な ES|QL クエリ・MITRE ATT&CK マッピング(T1110.004 Credential Stuffing・T1078 Valid Accounts)・重要度設定までが一括生成されます。 ⚠️ Enterprise ライセンスが必要です。 📎 参照: From plain English to production rule: AI-native Elasticsearch ES|QL detection in Elastic Security 4. ES|QL クエリ言語の強化 Elastic のパイプライン型クエリ言語 ES|QL に 4 つの大きな機能が追加されました。 サブクエリ(Subqueries) :異なるインデックスの複数クエリを 1 文で結合。例えばビジネスデータとサーバーログを時系列でまとめて分析できます。 FROM   (FROM ecommerce | EVAL domain = "business" | KEEP ts, domain, summary),   (FROM logs       | EVAL domain = "ops"      | KEEP ts, domain, summary) | SORT ts ロジカルビュー(Logical Views) :複雑な集計ロジックを名前付きで保存し、ダッシュボード・アラート全体で再利用できます。SQL の VIEW に相当する概念で、ビュー定義を更新すれば参照する全ダッシュボードに即時反映されます。 -- ビューを定義(一度だけ) CREATE VIEW high_risk_users AS FROM .alerts-security* | WHERE risk_score > 70 | STATS ... -- 以降、複数のダッシュボードから FROM view_name で参照可能 FROM high_risk_users  -- 事前定義したビューを通常のインデックスのように利用 | WHERE @timestamp > NOW() - 24 hours | KEEP user.name, risk_score JSON 関数抽出 :JSON 形式で格納されたフィールドの値を、再インデックスなしに直接クエリで取り出せます。スキーマが不定形なログデータの分析に有効です。 ROW raw = "{ \"user\": { \"name\": \"yamada\", \"id\": 42 }, \"source\": { \"ip\": \"10.0.0.1\" } }" | EVAL user_name = JSON_EXTRACT(raw, "user.name") | EVAL user_id = JSON_EXTRACT(raw, "user.id") | EVAL src_ip = JSON_EXTRACT(raw, "source.ip") | KEEP user_name, user_id, src_ip 実行結果: user_name | user_id | src_ip ----------+---------+----------- yamada | 42 | 10.0.0.1 パスは user.name のドット記法、 groups[0] のブラケット記法のどちらも利用できます。キーに . が含まれる場合は ['event.id'] のブラケット記法が必須です。 マッピング外フィールドへのアクセス ( SET unmapped_fields="load" ) :インデックス定義に漏れていたフィールドも後から遡ってクエリ可能になりました(従来の「無知の崖」問題を解消)。 9.3のバージョン -- 従来:マッピング外のフィールドは結果に含まれない FROM my_unmapped_test | KEEP @timestamp, user, amount, department -- 9.4:SET ディレクティブで未マッピングフィールドも _source から取り出せる SET unmapped_fields="load"; FROM my_unmapped_test | KEEP @timestamp, user, amount, department 実行結果( SET unmapped_fields="load" を指定した場合): @timestamp | user | amount | department ---------------------+--------+--------+------------- 2026-05-06T13:00:00Z | tanaka | 320 | sales 2026-05-06T12:00:00Z | yamada | 150 | engineering "load" のほかに "nullify" (明示的に null を返す)も指定可能です。性能面では _source からの読み出しになるため、マッピング済みフィールドのクエリよりやや遅くなる点に注意が必要です。 📎 参照: What’s new in Elastic 9.4(公式ブログ) ・ ES|QL Logical Views 詳細ブログ ・ Elasticsearch リリースノート 5. ベクトル検索の高速化 AI ワークロード(RAG など)の基盤となるベクトル検索が大幅に強化されました。 DiskBBQ 改善 :フィルター付きクエリのレイテンシを最低 3 倍改善 GPU 加速インデックス作成が GA 昇格 :NVIDIA cuVS 統合により、セルフマネージド環境でインデックス速度が最大 12 倍、force merge が 7 倍高速化 量子化ビット数の選択肢拡大 :1 ビットのみだったところ、2・4・7 ビットが追加。精度とサイズのバランスを調整可能に 量子化ビットの設定例(インデックス作成時): PUT bbq_disk-index { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 64, "index": true, "index_options": { "type": "bbq_disk", "bits": 2 // 1, 2, 4, 7 から選択(数値が大きいほど高精度・大容量) } } } } } ⚠️ GPU 機能はセルフマネージド環境(NVIDIA GPU 搭載サーバー)限定です。 📎 参照: What’s new in Elastic 9.4(公式ブログ) ・ DiskBBQ アーキテクチャ解説ブログ ・ GPU ベクトルインデックス加速ブログ ・ GPU ベクトルインデックス ドキュメント 6. Kibana の強化 AI によるダッシュボード作成 :自然言語でダッシュボードのレイアウトや可視化を説明すると、AI が反復的に構築します。 Dashboards as Code :ダッシュボードを API・JSON で定義・管理できます。Git による差分管理や CI/CD パイプラインでの自動デプロイが可能になりました。 API 経由でダッシュボードを作成する例: POST kbn:/api/dashboards { "title": "My first API dashboard", "panels": [ { "grid": { "x": 0, "y": 0, "w": 24, "h": 10 }, "type": "vis", "config": { "type": "xy", "title": "Total log entries over time", "layers": [ { "type": "line", "data_source": { "type": "esql", "query": "FROM kibana_sample_data_logs | STATS count = COUNT() BY BUCKET(@timestamp, 75, ?_tstart, ?_tend)" } } ] } } ] } Agent Builder の拡張 :Skills・Attachments・Connectors・Plugins の 4 プリミティブが追加。長い会話でのコンテキスト管理(クエリ結果オフロード・コンパクション・要約)が改善され、マルチターン対話のコスト効率も向上しました。 📎 参照: What’s new in Elastic 9.4(公式ブログ) ・ Elastic AI Agent ドキュメント 7. Observability:メトリクス・時系列分析の強化 TSDB パフォーマンス改善 :時系列メトリクスの保存効率が Prometheus 比 2.6 倍向上、クエリ速度は Prometheus/Mimir 比で最大 25 倍高速化。 ES|QL 時系列関数の追加 :rate(変化率)・changes(変化量)・cumulative(累積)・trange(時間範囲)・clamp(値クリップ)が利用可能に。 PromQL のネイティブサポート :Prometheus メトリクスを Elasticsearch に直接取り込み、Kibana 上で PromQL を実行できます。PromQL の結果を ES|QL パイプラインに流し込むことも可能です。 PromQL → ES|QL を組み合わせる例: # PromQL の結果を ES|QL コマンドにパイプして集計 PROMQL index=k8s step=1h bytes=(max by (cluster) (network.bytes_in)) | STATS max_bytes=MAX(bytes) BY cluster | SORT cluster 📎 参照: What’s new in Elastic 9.4(公式ブログ) ・ Elasticsearch リリースノート(TSDB・PromQL 詳細) 8. セキュリティ:エンティティ管理の深化 エンティティ統合(Entity Resolution) :Okta・Microsoft Entra など複数の IdP に存在するアカウントを 1 つの従業員レコードに名寄せ。「同一人物が複数 ID を持っている」問題を解消し、横断的なリスク評価が可能になります。 統合のイメージ: 従来(バラバラに存在)            9.4(1つのレコードに統合) ─────────────────────────         ──────────────────────────── Okta:    t.yamada@co.jp     ┐ Entra:   tyamada            ├──→  山田 剛(Takeshi Yamada) GitHub:  yamada-t           │      └─ リスクスコアを統合計算 Slack:   takeshi.yamada     ┘      └─ クロスシステムのアラートを集約 動的ウォッチリスト(Dynamic Watchlists) :組織的な重要度(例:役員・特権アカウント)をリスクスコアへの乗数として反映できます。 エンティティ起点のハンティングリード :アラート起点の受動的調査から、リスクの高い行動パターンを事前に洗い出す能動的なハンティングへのシフトを支援します。 エンドポイント調査の拡張 : Runscript Response Action + Script Library:感染端末へのリモートスクリプト実行とライブラリ管理 Memory Dump Response Action(Linux 対応):マルウェア解析用のメモリ取得 Osquery 強化・Jumplists テーブル拡張:最近使用したファイル履歴のフォレンジック照会 📎 参照: What’s new in Elastic 9.4(公式ブログ) ・ Elastic Security リリースノート ・ Entity Analytics AI Skill ブログ まとめ:9.4 の位置付け カテゴリ 主なアップデート セキュリティ自動化 Workflows GA・25 種ケースステップ・Human-in-the-Loop AI エージェント Skills 5 種・プラットフォームスキル 3 種・Agent Builder 拡張 検知エンジニアリング AI による ES|QL ルール自動生成・MITRE 自動マッピング クエリ言語 ES|QL サブクエリ・ビュー・JSON 抽出・マッピング外フィールド ベクトル検索 3〜12 倍高速化・量子化ビット選択肢拡大 可観測性 TSDB 効率化・PromQL ネイティブ対応・時系列集計関数 エンティティ管理 名寄せ・動的ウォッチリスト・能動的ハンティングリード 9.4 はセキュリティチームだけでなく、インフラ・SRE・AI 開発チームにも広く関わるリリースです。特に Workflows と Skills の組み合わせによる「Agentic SOC(自律型 SOC)」への移行は、今後の Elastic Security の方向性を示すものといえます。 参照リンク 記事・ドキュメント URL What’s new in Elastic 9.4(公式メインブログ) https://www.elastic.co/blog/whats-new-elastic-9-4-0 Elastic Workflows GA(9.4) https://www.elastic.co/security-labs/elastic-workflows-ga-9-4 Workflows 入門(9.3 Tech Preview) https://www.elastic.co/security-labs/security-automation-with-elastic-workflows Skills in Elastic Security 9.4 https://www.elastic.co/security-labs/skills-elastic-security-9-4 AI による ES|QL 検知ルール生成 https://www.elastic.co/security-labs/ai-esql-detection-rule-creation Entity Analytics AI Skill ブログ https://www.elastic.co/security-labs/entity-analytics-agent-builder ES|QL Logical Views 詳細ブログ https://www.elastic.co/search-labs/blog/elasticsearch-esql-logical-views DiskBBQ アーキテクチャ解説ブログ https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction GPU ベクトルインデックス加速ブログ https://www.elastic.co/search-labs/blog/elasticsearch-gpu-accelerated-vector-indexing-nvidia GPU ベクトルインデックス ドキュメント https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/gpu-vector-indexing Elastic AI Agent ドキュメント https://www.elastic.co/docs/explore-analyze/ai-features/elastic-agent-builder Workflows ドキュメント https://www.elastic.co/docs/explore-analyze/workflows Elastic Workflow Library(GitHub) https://github.com/elastic/workflows Elasticsearch リリースノート(9.4) https://www.elastic.co/docs/release-notes/elasticsearch Elastic Security リリースノート(9.4) https://www.elastic.co/docs/release-notes/security Elastic リリースノート(全製品) https://www.elastic.co/docs/release-notes The post Elastic 9.4 リリースまとめ:AI・自動化・クエリ言語が一斉強化 first appeared on Elastic Portal .
サイオステクノロジー株式会社 Saman Part 1 では Elastic Agent Skills の概要とインストール方法を、 Part 2 では Claude Code とローカル Elasticsearch をつなぐ手順を紹介しました。 Part 3 では MCP Apps を試します。MCP Apps は、チャットの中にクリックできる画面を直接表示する仕組みです。Elastic は 2026 年 4 月に 3 つの MCP Apps をオープンソースで公開しました。Security、Search(ダッシュボードビルダー)、Observability の 3 つです。 本記事では Security に絞って、実際にインストールから動作確認まで一通り試した結果を紹介します。Search と Observability は最後に簡単に触れます。 ホストには Claude Desktop を使います。.mcpb ファイルをダブルクリックするだけでインストールできる、最もシンプルな方法です。なお Security MCP Apps は Claude Desktop 以外にも以下のホストで動作します。 ホスト インストール方法 セットアップガイド Claude Desktop .mcpb をダブルクリック 本記事で解説 Claude Code claude mcp add CLI setup-claude-code.md Claude.ai cloudflared トンネル経由 setup-claude-ai.md Cursor npx またはローカルサーバー setup-cursor.md VS Code npx またはローカルサーバー setup-vscode.md 接続先は Elastic Cloud Serverless を使います。ローカル接続(Part 2)と比べると、CA 証明書が不要な分セットアップがシンプルです。 本記事の対象環境は以下の通りです。 Claude Desktop(最新版) Elastic Cloud Serverless 9.3(Security プロジェクト) macOS(Windows の場合はパスのみ読み替えてください) 📝 本記事について 本記事は MCP App v1.0.0での 動作検証に基づいています。Elastic Security MCP App は現在 パブリックプレビュー中であり、活発に開発が続いています。 記事公開後もバージョンアップが頻繁に行われる可能性があるため、 実際の挙動が本記事の内容と異なる場合があります。 最新の動作状況は GitHub リリースノート を合わせてご確認ください。 目次 MCP Apps とは何か Step 1:API キーを作成する(権限が重要) Step 2:Claude Desktop に .mcpb をインストールする 拡張機能を「有効」にする Step 3:スキルをインストールする 7 つのインタラクティブツール 重要な制約:プロジェクト内のチャットでは動かない 実データで SOC フローを動かす Step 1:アラートをトリアージする Step 2:Attack Discovery を確認する Step 3:ケースを作成する Step 4:検知ルールを確認する Step 5:脅威ハントで掘り下げる Step 6:サンプルデータを生成する Attack Discovery のハマりどころ(実体験) 現象 1:MCP App から実行すると「AI コネクタなし」エラー MCP Apps 動作状況のまとめ Attack Discovery のライセンス要件 Search と Observability MCP App について まとめ Serverless × Claude Desktop の接続手順 気をつけるポイント(実体験で学んだこと) MCP Apps の現実と将来性 参考資料 本シリーズのリンク MCP Apps とは何か 通常、MCP ツールが返すのはテキストです。「アラートが 47 件あります」という文章です。それを読んだアナリストは Kibana に移動してアラートを開く、という作業が別途必要でした。 MCP Apps はこれを変えます。ツールの結果として、クリックできるダッシュボードがチャットの中に直接表示されます。Kibana に移動する必要はありません。会話の文脈を保ったまま、インタラクティブな UI を操作できます。 設計上の特性は 3 つあります。 コンテキストの維持: UI はチャットの中にあります。別タブを開く必要がないので、会話の流れが切れません。AI が前の文脈を保持したまま操作できることが SOC や調査でとても重要です。 双方向のデータフロー: UI は MCP サーバーに直接データを取りに行けます。チャットで別の質問をしながら、UI 上のデータが更新されます(UI → MCP Host → MCP Server → Elasticsearch)。 サンドボックス化された信頼境界: MCP Apps はホストが管理する iframe の中で動きます。親ページへのアクセスや Cookie の読み取りはできません。 Step 1:API キーを作成する(権限が重要) ここが最大の落とし穴です。単にキーを作るだけでは一部機能が動きません。 ⚠️ Serverless 環境での重要な注意: Elastic Cloud Serverless では、細かい権限指定(feature_cases.all など)が意図通りに機能しない場合があります。全機能を確実に動かすには、以下の superuser 相当のロールでAPIキーを作成してください。本番環境では最小権限への絞り込みを推奨します。 Kibana の Dev Tools で以下を実行します。 POST /_security/api_key { "name": "claude-mcp-security", "expiration": "30d", "role_descriptors": { "mcp-full-access": { "cluster": ["all"], "indices": [ { "names": ["*"], "privileges": ["all"] } ], "applications": [ { "application": "kibana-.kibana", "privileges": ["all"], "resources": ["*"] } ] } } } 返ってくるレスポンスの encoded フィールドの値が API キーです。 { "id": "rLV1zp0BZGqtkno0tEMy", "name": "claude-mcp-security", "expiration": 1779877313588, "api_key": "YOUR_API_KEY", "encoded": "ckx**********vMHR****6ZFZrV***********RODZoUQ==" } Step 2 で使うのでメモしておいてください。 補足(権限を絞りたい場合): 最小権限で構成する場合、以下が必要です。ただし Serverless 環境では動作しない権限名がある場合があります。検証済みの構成が確定次第、本記事を更新します。 cluster: monitor, monitor_inference indices: read, view_index_metadata, monitor(logs-*, .alerts-security*, .siem-signals*) Kibana: feature_agentBuilder.read, feature_siemAttackDiscovery.all, feature_siem.all, feature_cases.all, feature_actions.read Step 2:Claude Desktop に .mcpb をインストールする Security MCP Apps の最新版を GitHub の最新リリース からダウンロードします。 Assets セクションから example-mcp-app-security.mcpb をダウンロードしてください。 ダウンロードした .mcpb ファイルをダブルクリックします。Claude Desktop が自動的に起動して、インストールダイアログが表示されます。 警告について: 「インストールすると、この拡張機能にコンピュータ上のすべてのデータへのアクセス権が付与されます」というメッセージが表示されますが、これはすべての .mcpb 拡張機能に表示される標準メッセージです。Elastic Security MCP App が実際にアクセスするのは Elasticsearch と Kibana の API のみで、PC 上の他のデータにはアクセスしません。 「インストール」をクリックすると、続いて接続情報の入力ダイアログが開きます。 項目 値 ELASTICSEARCH_URL https://your-cluster.es.cloud.example.com ELASTICSEARCH_API_KEY Step 1 で作成した API キー KIBANA_URL https://your-cluster.kb.cloud.example.com API キーは macOS のキーチェーンに暗号化保存されます。設定ファイルには残りません。 拡張機能を「有効」にする ここが見落としがちなポイントです。インストール後、拡張機能はデフォルトで「無効」状態になっています。 Settings → Extensions で elastic-security-mcp-app を開き、トグルを「有効」に切り替えてください。これは Claude Desktop のすべての拡張機能に共通の動作です。 切り替えたら Claude Desktop を完全に再起動します。チャット画面の下部に 🔨 ハンマーアイコンが表示されれば接続成功です。 Step 3:スキルをインストールする スキルは Claude に「いつ・どのツールを使うか」を教える SKILL.md ファイルです。スキルがないと、Claude は各ツールの使いどころを判断できません。 最新リリース の Assets から以下の zip ファイルをダウンロードします。 alert-triage.zip attack-discovery-triage.zip case-management.zip detection-rule-management.zip generate-sample-data.zip macOS の注意: Safari でダウンロードすると zip が自動展開されてフォルダになります。その場合、フォルダを右クリック →「○○を圧縮」で zip に戻してからアップロードします。 Claude Desktop で Customize → スキル → スキルを作成 → スキルをアップロード から、zip を 1 つずつアップロードします。5 つすべて入れてください。 7 つのインタラクティブツール インストールが完了すると、以下の 7 つのツールが使えるようになります。それぞれがプロンプトに応じてインタラクティブな UI をチャット内に返します。 ツール 機能 triage-alerts アラートの取得・フィルタ・分類。AI 判定カード、プロセスツリー、ネットワークイベント triage-attack-discoveries 既存の Attack Discovery を一覧・トリアージ generate-attack-discovery 新しい Attack Discovery を生成(AI コネクタ必須) manage-cases SOC 調査ケースの作成・管理。AI アクションボタン付き manage-rules 検知ルールの閲覧・チューニング threat-hunt ES|QL ワークベンチ、クリッカブルなエンティティ、D3 調査グラフ generate-sample-data 17 の攻撃シナリオのサンプルデータ生成 重要な制約:プロジェクト内のチャットでは動かない Claude Desktop のプロジェクト機能の中の新規チャットでは MCP Apps の拡張機能が動作しません。プロジェクト外の通常チャットで使う必要があります。 New chat をクリックして、プロジェクトの外で会話を始めてください。 実データで SOC フローを動かす 今回使うデータは logs-endpoint.events.imported.fixed インデックスの Elastic Endpoint エンドポイントイベントです。監視対象は 2 台の Ubuntu ホスト(omm-nix-detect、omm-nix-prevent)で、実際に調査につながるシグナルが含まれています。 データのポイント 内容 omm-nix-prevent への SSH ログイン 16 人の異なるユーザー(isla、abrar、ddroot、kominfo など) unzip プロセスによるファイル作成 /home/ubuntu/74ef6cc38f5a1a80… event.action の種類 fork(117)、end(116)、deletion(82)、creation(80)、ssh_login(20)… Step 1:アラートをトリアージする omm-nix-prevent のアラートをトリアージして Alert Triage ダッシュボードがチャット内に表示されます。各検知ルールに対して AI の判定が信頼スコア付きで表示されます。omm-nix-prevent への大量の SSH ログインがフラグされ、isla、abrar、ddroot といったユーザーの認証履歴をプロセスツリーで確認できます。 ホスト別、検知ルール別、重大度別の集計が UI 内に表示され、アラートをクリックするとプロセスツリーや詳細が展開されます。 図 1:Alert Triage ダッシュボード。high 100 件、medium 100 件の計 200 件が表示され、検知ルール別・ホスト別の集計が確認できる。 Step 2:Attack Discovery を確認する 既存の Attack Discovery を一覧表示して triage-attack-discoveries ツールが起動し、既存の Attack Discovery 一覧が表示されます。 図 2:Attack Discovery 一覧。まだ生成していない場合は 0 件と表示される(正常動作)。 Step 3:ケースを作成する omm-nix-prevent SSH ログイン調査というタイトルでケースを作成して。 重大度は HIGH、関連タグは ssh-login, file-activity, suspicious-unzip Case Management ダッシュボードがインラインに表示され、ケースが即座に作成されます。 図 3:Case Management ダッシュボード。 Step 4:検知ルールを確認する 検知ルールを一覧表示して manage-rules ダッシュボードが起動し、検知ルールの一覧が表示されます。ルール名、重大度、有効/無効の状態、KQL クエリが確認できます。 図 4:検知ルール管理画面。critical、high、medium のルールが一覧表示され、個別に有効化・チューニングできる。 Step 5:脅威ハントで掘り下げる omm-nix-prevent へのSSHログイン後のファイル作成を調査して Threat Hunt ワークベンチが開き、クエリが自動生成されて実行済みの状態で返ってきます。結果には以下のような情報が表示されました。 unzip がハッシュ名のファイルを作成しているのが目立ちます。マルウェアペイロードの可能性があり、調査を進める根拠になります。テーブル内のホスト名やユーザー名はクリックでさらに掘り下げられます。 図 5:Threat Hunt ワークベンチ。ES|QL クエリが自動生成・実行済みで返ってくる。テーブル内のエンティティはクリックで掘り下げ可能。 Step 6:サンプルデータを生成する Ransomware Kill Chain のサンプルデータを生成して Sample Data Generator ダッシュボードが起動し、17 のシナリオから選択できます。 Windows Credential Theft AWS Privilege Escalation Okta Identity Takeover Ransomware Kill Chain(最も多段階で Attack Discovery 向き) Linux Persistence その他 12 シナリオ Ransomware Kill Chain を選択すると、複数の検知ルールに対応するアラートが生成されます。 図 6:Sample Data Generator。17 のシナリオが選択可能で、生成するイベント数も指定できる。 Attack Discovery のハマりどころ(実体験) ここから実体験のトラブルシュート記録です。同じ問題に遭遇する方の参考になればと思い、起きたことをそのまま書きます。 現象 1:MCP App から実行すると「AI コネクタなし」エラー Claude Desktop で「Attack Discovery を実行して」と入力したら、結果は「AI コネクタが設定されていません」のエラー画面でした。 調査した結果、以下のことがわかりました。Kibana 9.x Serverless では AI コネクタがすべて .inference タイプ(統合 Inference API ベース)として提供されています。しかし MCP App v1.0.0 はこのタイプのコネクタを列挙対象に含めていないため、Kibana UI から見えているコネクタが MCP App には 1 つも見えない状態になります。 確認のために手動で .gen-ai タイプのコネクタを作成したところ、そのコネクタだけは MCP App から認識されました。 コネクタタイプ Kibana UI MCP App .inference(Serverless 標準) ✅ 見える ❌ 見えない .gen-ai(手動作成) ✅ 見える ✅ 見える この問題は Elastic 側のバグとして認識済み です。修正時期は未定ですが、修正状況は example-mcp-app-security のリリースノート で確認できます。 図 7:generate-attack-discovery の実行結果。Serverless 標準の .inference コネクタが認識されず、「No matching connector. Available: (空)」エラーが表示される。 MCP Apps 動作状況のまとめ 本記事執筆時点(MCP App v1.0.0)での動作状況をまとめます。 ツール MCP App 経由 備考 triage-alerts ✅ 動作 フル機能 triage-attack-discoveries ✅ 動作 既存 Discoveries の閲覧は可 manage-cases ✅ 動作 superuser ロールが必要(Serverless) manage-rules ✅ 動作 通常動作 threat-hunt ✅ 動作 superuser ロールが必要(Serverless) generate-sample-data ✅ 動作 17 シナリオ対応 generate-attack-discovery ❌ 未動作 .inference タイプコネクタ非対応(Elastic 側バグ認識済、修正待ち) Attack Discovery 機能を使いたい場合は、現時点では Kibana UI から直接実行するのが確実です。 Attack Discovery のライセンス要件 Attack Discovery は OSS(Basic)ライセンスでは利用できません。 デプロイ形態 必要なライセンス Self Managed / Elastic Cloud Hosted Enterprise サブスクリプション Elastic Cloud Serverless EASE(Elastic AI SOC Engine)または Security Analytics Complete ティア 無料トライアルでは 14 日間 Enterprise 相当の機能を試せます。本番導入時のライセンス検討材料にしてください。 Search と Observability MCP App について Security MCP App と同じ仕組みで、別途リポジトリが用意されています。 Search MCP App(example-mcp-dashbuilder): プロンプトから Kibana ダッシュボードを生成します。「ホスト別のイベント数、ユーザー別の操作件数、event.action 種別の内訳を含むダッシュボードを作って」と入力すると、ES|QL でデータを探索して可視化を組み立て、Kibana にエクスポート可能なダッシュボードを返します。 Observability MCP App(example-mcp-app-observability): クラスターヘルスサマリ、APM サービス依存関係グラフ、Kubernetes ノード停止時のインパクト範囲分析などを提供します。 それぞれインストール手順は Security と同じで、.mcpb ファイルをダブルクリックしてダウンロード、API キーを設定、Settings → Extensions で有効化、という流れです。 まとめ Serverless × Claude Desktop の接続手順 ステップ 内容 Step 1 Kibana で API キーを作成(Serverless では superuser ロールを推奨) Step 2 example-mcp-app-security.mcpb をダブルクリックしてインストール、接続情報入力、「有効」に切り替え Step 3 スキル zip を 5 つアップロード 気をつけるポイント(実体験で学んだこと) .mcpb をインストールしただけでは拡張機能は「無効」状態。手動で有効化が必要 Serverless 環境では API キーに superuser ロールを使う (細かい権限指定が機能しない場合がある) API キーを変更したら拡張機能の設定で API キーを上書きして Claude Desktop を再起動 プロジェクト内の新規チャットでは MCP Apps 拡張が動かない。プロジェクト外で会話する Attack Discovery は Enterprise サブスクリプション(または Serverless の EASE / Security Analytics Complete)が必要 Attack Discovery は本記事執筆時点では Kibana UI 経由が確実(MCP App 側は Elastic バグ認識済、修正待ち) ⚠️ パブリックプレビュー期間中の注意 本記事執筆時点(2026年4月)では、MCP App は活発に開発・更新 されています。バージョンアップにより、本記事に記載の手順や 挙動が変わる場合があります。問題が発生した場合は、まず GitHub Issues で既知の問題を確認し、最新の .mcpb への更新や APIキーの再設定をお試しください。 MCP Apps の現実と将来性 正直に書くと、現時点では MCP Apps が Kibana の完全な代替にはなりません。Kibana の方が安定していて、機能が完成しています。 それでも MCP Apps が意義を持つ場面はあります。 SOC アナリスト初心者の学習用: 「アラートをトリアージして」と日本語で言うだけで、AI がどのフィールドを見て、どう ES|QL を書くかを示してくれます。Kibana の使い方を覚える前に、調査の流れを体感できます。 横断的な調査: Security、Search、Observability の 3 つの MCP Apps を入れておけば、1 つのチャットで「アラート確認 → メトリクス調査 → ダッシュボード作成」までできます。Kibana だと画面の往復が必要です。 レポート作成・要約: 「このアラート群を経営層向けに要約して」「IOC を抽出してケースに追加して」など、AI が得意な作業をデータに対して直接実行できます。 「今すぐ Kibana を置き換えるもの」というよりは、「AI 時代のセキュリティ運用の方向性を体験できる先取り技術」と捉えるのが現実的です。 参考資料 Elastic Agent Builder MCP server https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/mcp-server Permissions and access control in Elastic Agent Builder https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/permissions Attack Discovery https://www.elastic.co/docs/solutions/security/ai/attack-discovery Elastic Security, Observability, and Search now offer interactive UI in your AI tools https://www.elastic.co/search-labs/blog/mcp-apps-elastic elastic/example-mcp-app-security https://github.com/elastic/example-mcp-app-security elastic/example-mcp-dashbuilder https://github.com/elastic/example-mcp-dashbuilder elastic/example-mcp-app-observability https://github.com/elastic/example-mcp-app-observability ohmymalware(for dataset) https://ohmymalware.com/ 本シリーズのリンク Part 1:Elastic Agent Skills とは、インストールから始める https://elastic.sios.jp/blog/elastic-agent-skills-part1/ Part 2:Claude Code で Elastic Agent Skills を試す、ローカル接続編 https://elastic.sios.jp/blog/elastic-agent-skills-part2/ The post Kibana を開かずに SOC 業務をこなす、 Elastic Security MCP App 実践ガイド first appeared on Elastic Portal .
サイオステクノロジー株式会社 Saman Part 1 では、Elastic Agent Skills の概要とインストール方法を紹介しました。 Part 2 では、 Claude Code とローカル Elasticsearch を実際につなぐ手順 を、ステップバイステップで紹介します。最後まで進むと、自然言語で Elasticsearch にクエリを投げられるようになります。 本記事の手順はすべてローカル環境で実際に動作を確認しています。Elastic Cloud Serverless との接続は Part 3 で紹介します。 目次 検証環境 全体像:接続に必要なもの 1. CA 証明書 2. .env ファイル 3. Agent Skills Step 1:プロジェクトフォルダを作る Step 2:CA 証明書を取得する コンテナ名を確認する 証明書をコピーする Step 3:.env ファイルを作る 注意点が 2 つあります Step 4:接続を確認する Step 5:Agent Skills をインストールする フラグの意味 なぜこの 2 つから始めるのか インストール後の確認 Step 6:Claude Code を起動して接続を確認する Step 7:使用例 1 — ES|QL でデータを分析する カテゴリ別の売上集計 Step 8:使用例 2 — ログを調査する よくあるエラーと解決方法 エラー 1:.env が見つからない エラー 2:Elasticsearch に接続できない エラー 3:npm パッケージが見つからない 互換性についての注意:動かなかった例 実例:kibana-dashboards スキル スキルを追加する まとめ 参考資料 Elastic 公式ドキュメント Elasticsearch Labs ブログ GitHub リポジトリ 検証環境 本記事で使用した環境は以下の通りです。 macOS(Apple Silicon、M4) Docker Desktop Elasticsearch 9.3.1(Docker、3ノード構成、セキュリティ有効) Node.js Claude Code v2.1.117 OS や Elasticsearch のバージョンが異なると、パスや挙動が変わる可能性があります。 全体像:接続に必要なもの Claude Code からローカル Elasticsearch にアクセスするには、 3 つ のものが必要です。 1. CA 証明書 Docker で起動した Elasticsearch は HTTPS 通信を使っており、自己署名証明書(自分で発行した証明書)が使われています。通常の通信ではブラウザや CLI がこの証明書を信頼しないので、 証明書ファイルを取り出して Claude Code に渡す必要があります 。 2. .env ファイル Elasticsearch に接続するには、URL、ユーザー名、パスワード、証明書のパスといった情報が必要です。これを 環境変数として一箇所にまとめておくファイルが .env です。 .env を使うメリット: 接続情報を一箇所で管理できる パスワードをコードに書かなくて済む スキルのスクリプトが環境変数を自動で読み込める 3. Agent Skills Claude Code に Elasticsearch の使い方を教えるスキルです。Part 1 で紹介した通り、 npx skills add コマンドでインストールします。 Step 1:プロジェクトフォルダを作る 接続情報と証明書を管理するフォルダを作ります。 mkdir ~/claude_skills cd ~/claude_skills このフォルダで Claude Code を起動することが重要です。 Claude Code はスキルを、起動したディレクトリの .claude/skills/ から読み込みます。 Step 2:CA 証明書を取得する コンテナ名を確認する まず、Docker コンテナ名を確認します。 docker ps --format "{{.Names}}" Elasticsearch のコンテナは、利用している Docker Compose やセットアップによって様々な名前になります。例えば次のような名前です: es01 deploy_stack-es01-1 elasticsearch-master-0 elasticsearch Elasticsearch 関連のコンテナ名をメモしておいてください。 以降の手順で使います。 証明書をコピーする コンテナ名が確認できたら(本記事では es01 を例にします)、証明書をコピーします。 docker cp es01:/usr/share/elasticsearch/config/certs/ca/ca.crt ./http_ca.crt 証明書の場所は Docker の設定によって異なります。上記のパスで見つからない場合は、以下で探せます。 docker exec es01 find /usr/share/elasticsearch -name "*.crt" 2>/dev/null Step 3:.env ファイルを作る ~/claude_skills/ フォルダに .env ファイルを作り、接続情報を書きます。 export ELASTICSEARCH_URL=https://localhost:9200 export ELASTICSEARCH_USERNAME=elastic export ELASTICSEARCH_PASSWORD=<your-password> export ELASTICSEARCH_CA_CERT=/Users/<username>/claude_skills/http_ca.crt 注意点が 2 つあります 1. 各行の先頭に export を付ける export がないと、 source .env を実行しても環境変数がスキルのスクリプトまで渡りません。後述する「よくあるエラー」の原因になります。 2. ELASTICSEARCH_CA_CERT は絶対パスで書く ./http_ca.crt のような相対パスにすると、スキルが実行されるディレクトリによっては証明書を見つけられません。 Step 4:接続を確認する .env ファイルが正しく書けているか、curl で確認します。 source ~/claude_skills/.env && curl --cacert "$ELASTICSEARCH_CA_CERT" \ -u "$ELASTICSEARCH_USERNAME:$ELASTICSEARCH_PASSWORD" \ "$ELASTICSEARCH_URL/_security/_authenticate" 成功すると、以下のようなレスポンスが返ります。 { "username": "elastic", "roles": ["superuser"], "authentication_type": "realm" } Step 5:Agent Skills をインストールする ~/claude_skills/ フォルダで以下のコマンドを実行します。 npx skills add elastic/agent-skills -a claude-code \ -s elasticsearch-authn \ -s elasticsearch-esql \ --yes フラグの意味 GitHub リポジトリに記載されているフラグの一覧です。 フラグ 説明 -a, --agent インストール先のエージェントを指定(例: -a claude-code ) -s, --skill スキル名を指定してインストール(例: -s elasticsearch-esql ) -g, --global プロジェクトではなくホームディレクトリにインストール -y, --yes 確認プロンプトをスキップ --all 全スキルを全エージェントにインストール --list インストールせずにスキル一覧を表示 --yes を付けると、「インストールしますか?」という確認が自動的にスキップされます。 出典: elastic/agent-skills GitHub Repository なぜこの 2 つから始めるのか GitHub のリポジトリには次のように書かれています。 原文(英語): “Install the cloud and elasticsearch auth skills — most other skills depend on them — then add only the skills relevant to your workflow.” 日本語訳: cloud スキルと elasticsearch auth スキルをインストールし(多くのスキルがこれらに依存しています)、それからワークフローに関連するスキルだけを追加してください。 まず認証スキルを入れ、その上に必要なスキルを追加していくのが推奨の順序です。 インストール後の確認 スキルは Claude Code を起動したプロジェクトフォルダの .claude/skills/ に配置されます。 ls ~/claude_skills/.claude/skills/ # elasticsearch-authn/ elasticsearch-esql/ Step 6:Claude Code を起動して接続を確認する .env ファイルと同じフォルダで Claude Code を起動します。 cd ~/claude_skills claude 起動したら、チャットに入力します。 .env ファイルを読み込んで、Elasticsearch に接続し、利用可能なインデックスの一覧を表示してください。 成功すると、Claude Code がインデックスの一覧を取得して表示します。 Step 7:使用例 1 — ES|QL でデータを分析する Kibana のサンプルデータを使って、ES|QL クエリを試してみましょう。 Kibana( http://localhost:5601 )の「Add data」メニューから eCommerce サンプルデータをまだ追加していない場合は、先に追加してください。 カテゴリ別の売上集計 チャットに入力します。 kibana_sample_data_ecommerce インデックスを使って、 カテゴリ(category)別の売上合計(taxful_total_price)を 高い順に並べた ES|QL クエリを実行してください。 elasticsearch-esql スキルが起動し、インデックスのフィールド構造を確認してから、正しい ES|QL 構文でクエリを生成・実行します。 実行された ES|QL クエリ: FROM kibana_sample_data_ecommerce | STATS total_sales = SUM(taxful_total_price) BY category | SORT total_sales DESC Step 8:使用例 2 — ログを調査する 次は kibana_sample_data_logs インデックスを使ったログ調査です。Kibana の「Add data」から Logs サンプルデータを追加してから試してください。 まず、 observability-logs-search スキルを追加します。 npx skills add elastic/agent-skills -a claude-code \ -s observability-logs-search --yes スキル追加後、Claude Code のチャットに入力します。 kibana_sample_data_logs インデックスで、 直近のログから最もバイト転送量が多いリクエストを 上位 5 件表示してください。 Elastic Observability Labs のブログには、このスキルの設計について次のように書かれています。 原文(英語): “The key shift is that the request is outcome-first. The skill captures implementation details such as API order, field expectations, and verification steps.” 日本語訳: 重要な変化は、リクエストが「結果から始まる」点です。スキルは、API の呼び出し順序、フィールドの期待値、検証ステップなどの実装の詳細をカバーします。 つまり、「どの API を呼ぶか」「どのフィールドを使うか」はスキルが判断します。ユーザーは「何を知りたいか」を自然言語で伝えるだけです。 出典: Elasticsearch Labs — Agent Skills for Elastic Observability よくあるエラーと解決方法 エラー 1:.env が見つからない (eval):source:1: no such file or directory: .env 原因: Claude Code が .env を相対パスで探したが、実行時のカレントディレクトリが異なる。 解決方法: .env の読み込みに絶対パスを使う。 source /Users/<username>/claude_skills/.env または、 .env があるフォルダで Claude Code を起動する。 エラー 2:Elasticsearch に接続できない Set one of these environment variable combinations: 1. ELASTICSEARCH_CLOUD_ID + ELASTICSEARCH_API_KEY 2. ELASTICSEARCH_URL + ELASTICSEARCH_API_KEY 3. ELASTICSEARCH_URL + ELASTICSEARCH_USERNAME + ELASTICSEARCH_PASSWORD 原因: .env ファイルの各行に export が付いていないため、環境変数がスキルのスクリプトに渡されていない。 解決方法: .env の各行の先頭に export を追加する。 # NG ELASTICSEARCH_URL=https://localhost:9200 # OK export ELASTICSEARCH_URL=https://localhost:9200 エラー 3:npm パッケージが見つからない Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@elastic/elasticsearch' 原因: スキルの Node.js スクリプトが必要とするパッケージがインストールされていない。 解決方法: スキルのフォルダで npm install を実行する。Claude Code は自動で対処することもあります。 cd .claude/skills/elasticsearch-esql && npm install 互換性についての注意:動かなかった例 現時点では、Agent Skills は Elastic Cloud Serverless との互換性を最大化 して設計されています。 原文(英語): “This initial technical preview release focuses on skills with maximum compatibility for Elastic Cloud Serverless” 日本語訳: この最初のテクニカルプレビューリリースは、Elastic Cloud Serverless との互換性を最大化することに重点を置いています。 出典: Elasticsearch Labs — Agent Skills for Elastic ローカル Elasticsearch 9.x では、一部のスキルが動作しない場合があります。本記事の検証でも実際にエラーが発生したので、共有します。 実例:kibana-dashboards スキル 以下のコマンドで kibana-dashboards スキルをインストールし、Claude Code に Kibana ダッシュボードの作成を依頼しました。 npx skills add elastic/agent-skills -a claude-code \ -s kibana-dashboards --yes ダッシュボード作成を依頼すると、以下のエラーが発生しました: Error: Invalid version number. Received "2023-10-31", expected a string containing _only_ a finite, whole number greater than 0. スキルのスクリプトが、バージョン番号として "2023-10-31" (日付形式)を送信していますが、Elasticsearch 9.x は整数のバージョン番号を期待しています。 この挙動はローカルの Elasticsearch 9.x 特有のもので、Elastic Cloud Serverless では動作する可能性があります。 Part 3 で Serverless での検証結果を紹介します。 スキルを追加する ワークフローに合わせて、後からスキルを追加できます。 npx skills add elastic/agent-skills -a claude-code \ -s <スキル名> --yes インストール済みのスキルを確認するには: npx skills list スキルを追加した後、Claude Code の 再起動は不要 です。スキルはチャットから自然言語で依頼するだけで、自動的に読み込まれます。 出典: Elastic 公式ドキュメント — AI agent skills for Elastic まとめ 本記事では、ローカル Elasticsearch と Claude Code をつなぐ手順を、実際に動作確認しながら紹介しました。 接続に必要なもの 項目 内容 CA 証明書 Elasticsearch の HTTPS 通信を信頼するために必要(Docker コンテナから docker cp で取得) .env ファイル 4 つの環境変数( export 付き、絶対パス) 起動場所 .env と同じフォルダで Claude Code を起動 スキルの場所 起動したフォルダの .claude/skills/ (プロジェクトローカル) 動作確認できたスキル elasticsearch-authn :認証 elasticsearch-esql :ES|QL クエリ observability-logs-search :ログ調査 動作しなかったスキル(ローカル Elasticsearch 9.x) kibana-dashboards :バージョン番号の互換性エラー Part 3 では: Elastic Cloud Serverless を使って、ローカルで動かなかったスキルを含む、より幅広い検証結果を紹介します。 MCP Apps を使った Elasticsearch との連携方法を紹介します。お楽しみに! 参考資料 Elastic 公式ドキュメント AI agent skills for Elastic | Elastic Docs Elasticsearch Labs ブログ Agent Skills for Elastic: Turn AI agents into Elastic experts Agent Skills for Elastic Observability GitHub リポジトリ elastic/agent-skills The post Claude Code で Elastic Agent Skills を試す、 Part 2 ローカル接続編 first appeared on Elastic Portal .
サイオステクノロジー株式会社 Saman 目次 機能紹介編 Agent Skills とは? Context Engineering というアプローチ なぜ Agent Skills が必要か 課題 1:ES|QL は新しい領域 課題 2:API サーフェスが広く深い 課題 3:ベストプラクティスは訓練データにない Agent Skills でカバーされている領域 スキルは組み合わせ可能(Composable) インストール方法 準備:Node.js が必要 方法 1:npx を使う(推奨) オプション:特定のスキルだけをインストール オプション:特定のエージェントにインストール 方法 2:ローカルで管理したい場合 サポートされているエージェント スキルを最新に保つ npx でインストールした場合 ローカルクローンの場合 セキュリティに関する重要な注意事項 まとめと次のステップ 参考資料 機能紹介編 AI コーディングエージェント(Claude Code、Cursor、GitHub Copilot など)は強力ですが、Elasticsearch や Kibana の使い方になると、うまくいかないことがあります。「この構文は合っているのか」「この API の呼び出し方でいいのか」といった疑問です。 Elastic Agent Skills は、この悩みを解決するために Elastic が公開した オープンソースのスキルパッケージ です。エージェントに Elastic の専門知識を直接与えることができます。 では、何ができるのか、どうインストールするのか、見ていきましょう。 Agent Skills とは? まずシンプルに説明します。 Agent Skills は、AI エージェントに特定の領域の専門知識を教える「説明書」です。 各スキルは、以下を含む自己完結型のフォルダとして提供されます: SKILL.md ファイル — スキルの説明と指示が書かれた中心ファイル 補助スクリプトやリソース — 必要に応じて追加される エージェントは起動時にスキルの name と description フィールドを読み込みます。そして、マッチするタスクが検出されたタイミングで、該当スキルの詳細な指示を動的に読み込みます。 この仕組みによって、エージェントは普段は軽量に動作しながら、必要なときだけ深い専門知識にアクセスできます。 Context Engineering というアプローチ Agent Skills の考え方は「Context Engineering」という概念に基づいています。エージェントに正しい「文脈」を与えることで、より正確な結果を得るという考え方です。 Elastic Labs の記事には、次のように書かれています: スキルが有効になると、エージェントは適切なタイミングで、適切な文脈(クエリ構文、API パターン、検証ロジック、実例)にアクセスできます。結果として、最初の試みで正しくタスクを完了できます。 なぜ Agent Skills が必要か Elastic Labs の記事では、AI コーディングエージェントが Elastic のような特定プラットフォームで苦戦する理由を、3 つ挙げています。 課題 1:ES|QL は新しい領域 Elasticsearch 独自のクエリ言語 ES|QL は、LLM にとって馴染みが薄い言語です。 LLM は主に SQL で訓練されていますが、ES|QL はパイプベースのクエリ言語で、構文も関数もセマンティクスも異なります。エージェントは、もっともらしく見えるがパースできないクエリを書くことが多くあります。 Agent Skills はこのギャップを埋めます。 課題 2:API サーフェスが広く深い Elasticsearch、Kibana、Elastic Security は、数多くの API を公開しています。 Elasticsearch、Kibana、Elastic Security は、検索、取り込み、アラート、検出ルール、ケース管理、ダッシュボードなど、数百の API を公開しています。 一般的な訓練データだけを持つエージェントは、どのエンドポイントを呼び出すべきか、リクエストボディはどう構成すべきかを推測で判断することになります。 課題 3:ベストプラクティスは訓練データにない semantic_text を使うべきか、カスタム埋め込みパイプラインを使うべきか? 10GB の CSV にはどんな ingest pipeline を構成すべきか? 汎用エージェントは、こういった Elastic 固有の知識を、整理された形で持っていません。 Agent Skills でカバーされている領域 Elastic が公開している Agent Skills は、以下の領域をカバーしています(v0.1.0 初回リリース時点)。 Elasticsearch API との対話(検索、インデックス管理、クラスタ管理) Kibana のコンテンツ管理(ダッシュボード、アラート、コネクタなど) Elastic Observability のドメイン専門知識 Elastic Security のドメイン専門知識 Agent Builder 内で効果的なエージェントを作る知識 スキルは組み合わせ可能(Composable) スキルは、モノリシックではなく、モジュラーに設計されています。エージェントは、手元のタスクに関連するスキルだけを読み込みます。 ES|QL クエリを書いているとき?ES|QL スキルが有効になります。結果からダッシュボードを作りたい?ダッシュボードスキルが引き継ぎます。セキュリティアラートを調査中?トリアージスキルが、調査の進行に応じてケース管理や応答スキルに連鎖します。 インストール方法 では、実際にインストールしてみましょう。 準備:Node.js が必要 Agent Skills をインストールするには、npx が必要です。まず確認しましょう。 node –version npm –version どちらも出力されれば OK です。なければ nodejs.org からインストールしてください。 方法 1:npx を使う(推奨) 最も簡単な方法です。以下のコマンドを実行してください。 npx skills add elastic/agent-skills このコマンドを実行すると、対話的なプロンプトが表示され、スキルと対象エージェントを選択できます。 オプション:特定のスキルだけをインストール すべてのスキルが必要ではない場合、個別にインストールできます。 # Elasticsearch ES|QL スキルだけ npx skills add elastic/agent-skills@elasticsearch-esql # 複数指定 npx skills add elastic/agent-skills -s elasticsearch-esql -s kibana-dashboards オプション:特定のエージェントにインストール 複数のエージェントを使っている場合、特定のものだけをターゲットできます。 # Claude Code と Cursor にインストール npx skills add elastic/agent-skills -a claude-code -a cursor 方法 2:ローカルで管理したい場合 Node.js がない環境、または git で管理したい場合は、リポジトリをクローンできます。 git clone https://github.com/elastic/agent-skills.git cd agent-skills ./scripts/install-skills.sh add -a <agent-name> サポートされているエージェント Agent Skills は、複数の AI コーディングエージェントで動作します。 エージェント インストール先 Claude Code .claude/skills Cursor .agents/skills GitHub Copilot .agents/skills Windsurf .windsurf/skills Codex .agents/skills OpenCode .agents/skills Cline .agents/skills Gemini CLI .agents/skills Roo .roo/skills スキルを最新に保つ Elastic Agent Skills は定期的に更新されます。 npx でインストールした場合 最新バージョンをチェック: npx skills check アップデート: npx skills update ローカルクローンの場合 git pull ./scripts/install-skills.sh add -a <agent-name> –force –force フラグにより、既存のスキルが上書きされます。 セキュリティに関する重要な注意事項 Elastic Labs の記事には、使用する前の注意として、次のように書かれています。 AI コーディングエージェントは、実際の認証情報、実際のシェルアクセス、そして多くの場合、実行しているユーザーの完全な権限で動作します。エージェントをセキュリティワークフローに向けるとき、リスクは高まります。検出ロジック、応答アクション、機密性の高いテレメトリーへのアクセスを、自動化システムに渡すことになるからです。 特にセキュリティ系のワークフローで使う場合は、以下を評価するよう推奨されています: エージェントがアクセスできるデータは何か エージェントが取ることのできるアクションは何か エージェントが予期せぬ挙動をした場合、何が起こるか まとめと次のステップ Agent Skills とは: AI コーディングエージェント(Claude Code、Cursor など)に Elastic の専門知識を与えるスキルパッケージ オープンソース、Apache 2.0 ライセンス Elasticsearch、Kibana、Observability、Security、Agent Builder など複数の領域をカバー インストール方法: npx skills add elastic/agent-skills で簡単インストール 複数のエージェントに対応 次のステップ: Part 2 では、実際に Claude Code で Agent Skills を使いこなす方法 を紹介します。 参考資料 本記事の執筆に使用した参考資料: Elastic 公式ドキュメント: AI agent skills for Elastic | Elastic Docs Elasticsearch Labs ブログ: Agent Skills for Elastic: Turn AI agents into Elastic experts GitHub リポジトリ: elastic/agent-skills Agent Skills Open Standard (agentskills.io) The post Elastic Agent Skills とは 、インストールから始めるPart 1 first appeared on Elastic Portal .
Elastic Stackの可視化を担うKibana。 普段、ブラウザ上のGUIからダッシュボードを作成したり、ログを検索したりするのに使っている方が多いはずです。 しかし、Kibanaの真のポテンシャルは、その裏側に用意されたREST APIにあります。 今回は、Kibana APIを活用して、開発者やSREが運用を「手作業」から「コードによる管理」へとシフトさせるための主要なAPIとその活用シーンについて解説します。 目次 なぜKibana APIを使うのか? 押さえておきたい3つの主要APIカテゴリー 1. Saved Objects API 2. Spaces & Security API 3. Alerting & Actions API 実践:APIを叩いてみる 1. 全ダッシュボードを ndjson 形式でエクスポートする 2. Dev Tools からデータビューの一覧を取得する 運用を加速させるためのTips 主要エンドポイント一覧(抜粋) まとめ なぜKibana APIを使うのか? GUIは直感的で便利ですが、スケールするシステムや厳格な構成管理が求められる現場では、以下のような課題に直面します。 環境構築の自動化(IaC) ステージング環境で作り込んだダッシュボードやインデックスパターンを、人的ミスなく本番環境へ一括デプロイしたい。 マルチテナント管理 数十、数百の「Space(スペース)」を作成し、ユーザー権限(RBAC)を動的に割り当てたい。 動的なアラート設定 外部システム(TerraformやCI/CDパイプライン等)と連携して、監視対象の追加に合わせてアラートの閾値を自動更新したい。 これらを解決するのがAPIによる自動化です。 押さえておきたい3つの主要APIカテゴリー Kibana APIは非常に豊富ですが、運用の自動化においてまず押さえるべきは以下の3点です。 1. Saved Objects API Kibanaにおける最も重要なAPIです。ダッシュボード、ビジュアライゼーション、データビュー(旧インデックスパターン)などの「設定データ」を操作します。 活用例 _export / _import エンドポイントを使用して、ダッシュボードのバックアップや環境間移行をCI/CDに組み込む。 2. Spaces & Security API Kibana内の独立したワークスペースである「Space」や、ロールベースのアクセス制御(RBAC)を管理します。 活用例 組織変更や新規プロジェクト発足時に、専用のSpaceと閲覧権限を持つロールをスクリプトで一括生成する。 3. Alerting & Actions API 監視の要となる「ルール(Rules)」と「コネクター(Connectors)」を管理します。 活用例 サービスデプロイ時に、そのサービス専用のSlack通知設定と異常検知ルールを自動でセットアップする。 実践:APIを叩いてみる 1. 全ダッシュボードを ndjson 形式でエクスポートする 外部からAPIを呼び出す際は、認証情報と kbn-xsrf ヘッダーが必要です。 curl -X POST "http://localhost:5601/api/saved_objects/_export" \ -H 'kbn-xsrf: true' \ -H 'Content-Type: application/json' \ -u 'elastic:<password>' \ -d '{ "type": "dashboard", "includeReferencesDeep": true }' > all_dashboards_export.ndjson Note includeReferencesDeep: true を指定することで、ダッシュボードに関連付けられたチャートやデータビューもまとめてエクスポートできます。 2. Dev Tools からデータビューの一覧を取得する Kibana内の「Dev Tools」を使えば、認証を意識せずにAPIを試せます。 Kibana APIを叩く際は、パスの先頭に kbn: を付加するのがルールです。 GET kbn:/api/data_views 運用を加速させるためのTips API Keyの活用を検討する 自動化スクリプトでは、ユーザー名/パスワードではなく「API Key」を発行して利用するのがセキュリティ上のベストプラクティスです。 バージョン互換性に注意 Elastic Stackのバージョンアップにより、レスポンスの構造が変わることがあります。アップグレード前には必ず公式の変更履歴を確認しましょう。 「GUIで作ってAPIで抜く」が最短ルート Saved ObjectsのJSON構造をゼロから書くのは困難です。一度GUIで理想のダッシュボードを作り、それをGET APIで取得してテンプレート化するのが効率的です。 主要エンドポイント一覧(抜粋) 機能カテゴリ エンドポイント (ベースパス) 説明 Saved Objects /api/saved_objects/_export ダッシュボード等のエクスポート Data Views /api/data_views データビューの管理 Alerting /api/alerting/rules/_find アラートルールの検索・取得 Connectors /api/actions/connectors SlackやWebhook等の通知先管理 Security /api/security/role ロールの作成・管理 Spaces /api/spaces/space スペースの作成・管理 Status /api/status Kibana自体の稼働ステータス確認 詳細な仕様は、 Kibana API Reference (Official) を参照してください。 まとめ Kibana APIを使いこなすことで、Kibanaは単なる「可視化ツール」から、システムの一部として組み込める 「運用プラットフォーム」 へと進化します。 「毎回同じダッシュボードを手で作っているな」と感じたら、それが自動化のサインです。 まずは、よく使う設定のエクスポートあたりから手を付けてみてはいかがでしょうか? The post Kibanaを「ツール」から「プラットフォーム」へ:Kibana APIで実現する運用自動化の第一歩 first appeared on Elastic Portal .
先日のブログ  では、AutoOps による Elasticsearch クラスタの監視について紹介しました。 今回は、Kibana の Dev Tools (Console) 上で「今すぐクラスタの状態を知りたい」「具体的な数値をサクッと確認したい」といった場面で非常に重宝する _cat API を紹介します。 目次 1. _cat API とは? 2. 運用効率を劇的に上げる共通パラメータ 3. 現場で多用する主要エンドポイント 3.1. クラスタの健康診断: /_cat/health 3.2. ノードのリソース確認: /_cat/nodes 3.3. インデックスの統計: /_cat/indices 3.4. シャードの配置状況: /_cat/shards 4. 実践的な活用例:CLI との組み合わせ 5. _cat API のエンドポイント一覧(抜粋) まとめ 1. _cat API とは? _cat は “Compact and Aligned Text” の略称です。 その名の通り、人間がターミナルやコンソール上で読むことを前提とした「コンパクトで整列されたテキスト形式」で情報を返してくれる API 群です。 なぜ _cat を使うのか? 圧倒的な可読性: デフォルトで表形式(Tabular format)で出力されるため、構造が一目でわかります。 CLI フレンドリー: grep や awk、sort といった UNIX コマンドとの相性が抜群です。 軽量・高速: 余計な JSON メタデータが含まれないためレスポンスが速く、帯域も消費しません。 2. 運用効率を劇的に上げる共通パラメータ どの _cat エンドポイントでも利用できる、必須級のパラメータを紹介します。 パラメータ 説明 使用例 v (verbose) ヘッダー行を表示。これがないと列の意味がわからないため、ほぼ必須です。 /_cat/indices?v help その API で出力可能なカラム一覧と説明を表示します。 /_cat/nodes?help h (headers) 表示するカラムを指定(フィルタリング)します。 /_cat/indices?h=index,docs.count s (sort) 指定したカラムでソートします(昇順/降順の指定も可)。 /_cat/indices?s=docs.count:desc format 出力形式の指定。JSON や YAML 形式での出力も可能です。 /_cat/health?format=json bytes サイズ表記を固定します (b, kb, mb, gb)。比較に便利です。 /_cat/indices?bytes=mb 3. 現場で多用する主要エンドポイント トラブルシューティングやキャパシティプランニングで特に役立つものを厳選しました。 3.1. クラスタの健康診断: /_cat/health クラスタ全体のステータス(green/yellow/red)やノード数、シャードの状態を 1 行で把握できます。 GET /_cat/health?v Check Point: status が yellow や red の場合、unassign(未割り当てシャード)の数を確認しましょう。 3.2. ノードのリソース確認: /_cat/nodes 各ノードの CPU 使用率、メモリ使用量、ロードアベレージ、役割(role)などを一覧表示します。 GET /_cat/nodes?v&h=ip,name,role,cpu,heap.percent,load_1m 特定のノードに負荷が偏っていないか、Heap メモリが逼迫していないかを瞬時に特定できます。 3.3. インデックスの統計: /_cat/indices インデックスごとのドキュメント数やストレージ容量を確認できます。 Tips: s=store.size:desc を付けると、容量を圧迫しているインデックスを即座に特定できます。 GET /_cat/indices?v&s=store.size:desc 応用編:特定の名前を持つインデックスのみを対象にする。 GET /_cat/indices/*kibana*?v&s=store.size:desc 3.4. シャードの配置状況: /_cat/shards どのシャードがどのノードに配置されているか、INITIALIZING(初期化中)や UNASSIGNED(未割り当て)なシャードがないかを調査する際に重宝します。 GET /_cat/shards?v&s=state 4. 実践的な活用例:CLI との組み合わせ _cat API は、curl と組み合わせることで真価を発揮します。 ストレージを圧迫しているトップ5インデックスを探す。 # 容量(store.size)が大きい順にソートし、ヘッダーを含めた上位6行を表示 curl -u user:pass -X GET "http://localhost:9200/_cat/indices?v&s=store.size:desc" | head -n 6 出力例: health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size green open logs-2026.04 _pK_TOLwQKepPxXSu56... 1 1 1540740 0 1.2gb 614.4mb ... green open metrics-2026 9MYQYnnBSyuKaDp7t9q... 1 1 850200 0 840.5mb 420.2mb ... ... 5. _cat API のエンドポイント一覧(抜粋) 下記に _cat API のエンドポイント一覧の抜粋を掲示しておきます。 Endpoint 説明 /_cat/aliases エイリアスの一覧表示 /_cat/allocation シャードの割り当て情報表示 /_cat/component_templates コンポーネントテンプレートの一覧表示 /_cat/count クラスタ全体(またはインデックス全体)のドキュメント数の表示 /_cat/health クラスタの健康診断 /_cat/indices インデックスの一覧表示 /_cat/master マスターノード情報の表示 /_cat/ml/anomaly_detectors Anomaly Detection Job の一覧表示 /_cat/ml/trained_models Trained Model の一覧表示 /_cat/nodeattrs ノード属性の一覧表示 /_cat/nodes ノードの一覧表示 /_cat/plugins プラグインの一覧表示 /_cat/recovery リカバリー情報の表示 /_cat/repositories スナップショットリポジトリ情報の一覧表示 /_cat/segments セグメント情報の表示 /_cat/shards シャードの一覧表示 /_cat/snapshots スナップショット情報の表示 /_cat/tasks タスク情報の一覧表示 /_cat/templates インデックステンプレート情報の一覧表示 /_cat/transforms Transform情報の表示 他にもあります。 詳細は、Elastic 公式ドキュメント – _cat APIs  を参照してください。 まとめ _cat API はエンジニアの「目」であるElasticsearch の運用において、_cat API は単なる便利ツールではなく、クラスタの「今」を素早く正確に捉えるための必須装備です。 JSON レスポンスをパースするスクリプトを書く前に、まずは ?help でカラムを調べ、?v と ?h で自分専用のビューを作ってみてください。 ターミナルが、より強力な監視ダッシュボードに変わるはずです。 [!CAUTION] 注意: _cat API はあくまで人間用です。アプリケーションからプログラム的に情報を取得する場合は、通常のエンドポイント(JSON レスポンスを返す API)を使用することが推奨されます。 The post Elasticsearch の「中」を素早く覗く — _cat API 活用ガイド first appeared on Elastic Portal .
サイオステクノロジー株式会社 Saman ⚡ TL;DR:3分で分かる要点 やりたかったこと Elastic公式アナウンスを、英語のまま手動で追うのをやめる どう解決したか Logstash → Elasticsearch → Elastic Workflows → AI要約 → Slack 何が自動化されたか 毎朝9時に新着アナウンスが日本語でSlackに流れてくる 学べること Elastic WorkflowsのTrigger / Step / Connector / Data flowの実践パターン この記事では 「ゼロから動かせる構成」 を目標に、設定ファイルとWorkflow YAMLを全文掲載しています。 目次 なぜ作ったか Elastic Workflows とは この記事で学べること なぜこの構成にしたのか Part 1. Logstash で raw インデックスを作る 1-1. RSS を収集する rss.confを作成する ポイント解説 1-2. pipelines.ymlに登録する 1-3. Logstash を Homebrew サービスとして動かす 1-4. Logstash の動作ログを確認する 1-5. raw インデックスに保存されたことを確認する Part 2. Workflow で日本語化・分類・保存・Slack 通知する 2-1. Trigger の種類を先に整理する 2-2. Workflows のテンプレート記法を先に押さえる 2-3. Workflow 全体 YAML 2-4. この Workflow の見どころ 2-5. Workflow 実行画面では何を見るか 2-6. ハマりやすかったポイント 1. Workflows が見えない 2. {{ }}と ${{ }}の使い分け 3. Slack connector の違い 4. テスト時は manual trigger が便利 5. connector-idの出し方 まとめ 今後の発展方向 関連記事 なぜ作ったか 毎日 Elastic の Announcements ページを開いて、英語を読んで、Slack にまとめて投稿する――これを手作業でやっていたのをやめました。 協力会社や社内メンバーへの共有は「読む → 整理する → 伝える」の3ステップが毎回発生し、どうしても属人化しやすくなります。しかも英語のままでは、社内共有のハードルがどうしても上がります。 🔧 システム構成(全体の流れ) 📡 Elastic Announcements RSS ↓ ⚙️ Logstash(3時間ごとに取得) ↓ 🗂 elastic-announcements-raw(原文保存) ↓ 🤖 Elastic Workflows(毎朝9時起動) ・未処理記事だけを抽出 ・AIで日本語要約 / カテゴリ分類 / 対応項目生成 ・保存→Slack通知 ↓ 📦 elastic-announcements(加工済み保存) + Slack Elastic Workflows とは Elastic Workflows は、 Elastic 上のデータや外部サービスをつなぎ、手作業で繰り返している処理を自動化するための仕組み です。 たとえば、定期的にデータを検索する、条件に応じて分岐する、AI で要約する、結果を保存する、Slack に通知する、といった処理を 1 本の YAML で組み立てられます。 Workflows の基本要素は、次の 4 つです。 Triggers : いつ Workflow を動かすか Steps : Workflow が何をするか Connectors : 外部サービスとどう接続するか Data flow : 前の Step の出力を次の Step にどう渡すか Kibana の左サイドバーから「Workflows」を選ぶと、 このエディタ画面が開きます。YAMLを直接貼り付けて 「Save」するだけで Workflow が登録できます。 上部の「Enabled」トグルで有効/無効を切り替えられます。 画面下部に「19 warnings」のような警告が表示されることがありますが、 黄色の warning は動作に影響しません。 赤いエラーが出ていなければ、そのまま保存して問題ありません。 この記事で学べること Elastic Workflows の基本パターンをそのまま学べる実例になっています。 Trigger → Search → Foreach → If → AI → Update → Notify この流れを一通り含んでいるので、RSSに限らず他の自動化にも応用できます。 なぜこの構成にしたのか 最初は Workflows だけで RSS 取得から通知まで全部やる構成も考えました。ただ、「安定して取り込める raw 層」を先に作る方が実用的と判断しました。 責務を分けると、こうなります。 Logstash :RSS を安定して取得して raw 保存する Workflows :取得済みデータを判定・要約・保存・通知する この分割のよいところは、 収集の問題 と AI 要約や通知の問題 を切り分けやすいことです。まず「重要なお知らせを取り逃さず貯める」ことができれば、要約の質・カテゴリ設計・通知形式は後から改善できます。 前提条件 Mac(Homebrew でインストールした Logstash) Elastic Cloud または Elastic Serverless の保存先 Elastic Workflows を有効化済みの Kibana 環境 Slack connector を作成済みの環境 AI connector を利用できる環境 画面が見えないときは 、まず Kibana の Advanced Settings で workflows:ui:enabled を確認してください。 Part 1. Logstash で raw インデックスを作る Logstashには標準でRSS pluginが含まれていない場合があるため、必要に応じてインストールを行います。 logstash-plugin install logstash-input-rss インストール後は、以下のコマンドで確認できます。 logstash-plugin list | grep rss   #logstash-input-rssが返ってきます ※このpluginがインストールされていない場合、rssブロックは動作しません。 1-1. RSS を収集する rss.confを作成する まず、Logstash のパイプライン設定を作成します。 今回使った rss.conf の役割は次の通りです。 Elastic 公式 Announcements RSS を読む 3時間ごとにポーリングする HTML タグを除去する 重要そうなタイトルだけ残す link をキーにして重複を抑える elastic-announcements-raw に保存する input { rss { url => "https://discuss.elastic.co/c/announcements/5.rss" interval => 10800 } } filter { mutate { add_field => { "source_type" => "elastic_rss" } } mutate { gsub => [ "message", "<[^>]*>", "" ] } if [title] !~ /(Security Update|ESA-|CVE|What'?s new in Elastic|Elastic Stack|release|announcement|Announcing)/ { drop { } } } output { elasticsearch { hosts => ["https://YOUR-ENDPOINT"] #Elastic Cloud URL api_key => "YOUR_API_KEY" #APIキー index => "elastic-announcements-raw" document_id => "%{link}" # ← 記事URLをIDにして重複を防ぐ manage_template => false } stdout { codec => rubydebug } } ポイント解説 interval => 10800 :10,800 秒、つまり 3 時間ごとの取得 です。定期収集にしておくと、人が手動チェックしなくて済みます。 gsub による HTML 除去 :RSS の本文は HTML を含むため、そのまま AI に渡すとノイズになります。ここで最低限の整形をしておくと、後段の AI 要約が安定しやすくなります。 document_id => "%{link}" :同じ記事を定期取得しても、記事 URL を ID として使うことで重複を抑えられます。今回の Workflow では、この ID をそのまま processed 側の重複判定にも使っています。 manage_template => false :Logstash のデフォルトテンプレート自動適用でハマるケースを避けるために、今回は明示的に無効化しています。今回のような小さな raw 保存用パイプラインでは、この方がシンプルでした。 1-2. pipelines.ymlに登録する Homebrew の Logstash サービスは pipelines.yml で指定されたパイプラインを読みます。 rss.conf を作っただけでは動きません。 - pipeline.id: main path.config: "/opt/homebrew/etc/logstash/conf.d/rss.conf" 確認コマンド cat /opt/homebrew/etc/logstash/pipelines.yml ここはかなりハマりやすいポイントです。 「設定ファイルはあるのに実行されていない」 ときは、まず pipelines.yml の参照先を確認した方が早いです。 1-3. Logstash を Homebrew サービスとして動かす 今回の構成では、Logstash を手動起動ではなく Homebrew サービスとして動かしています。 これにより、毎回ターミナルで起動し直さなくて済みます。 # 起動 / 再起動 brew services restart logstash # 状態確認 brew services list # 動作ログ確認 tail -n 50 /opt/homebrew/var/log/logstash.log この状態が作れていれば、 放置してもデータ収集が継続する ので、raw 層としてかなり扱いやすくなります。 1-4. Logstash の動作ログを確認する stdout { codec => rubydebug } を入れているため、Logstash は処理したイベントをログにも出します。 これで、RSS を読めているか、どんなフィールドができているかを確認できます。 tail -n 50 /opt/homebrew/var/log/logstash.log ログを見ると、 title 、 published 、 link 、 source_type 、 message などが出力されます。これは RSS 取得とフィールド整形が動いている証拠です。 1-5. raw インデックスに保存されたことを確認する ログが出ているだけでは不十分です。実際に Elasticsearch に保存されているかも確認します。 // 件数確認 GET elastic-announcements-raw/_count // 最新1件確認 GET elastic-announcements-raw/_search { "size": 1, "sort": [{ "published": { "order": "desc" } }] } 返ってきたドキュメントに title / message / link / published / source_type / event.original があればOKです。 ここまでできれば、Workflow 側は raw インデックスからタイトルと本文を読める状態になっています。 Part 2. Workflow で日本語化・分類・保存・Slack 通知する ここからが、ビジネス価値を作る部分です。 raw データは英語のままで保存されていますが、実際にやりたいのは 「関係者が読みやすく、行動しやすい形にすること」 です。 2-1. Trigger の種類を先に整理する Elastic Workflows には、主に次の Trigger があります。 Trigger 用途 manual: 手動実行(検証に便利) scheduled: 定期実行(今回のメイン) alert: アラート起点の実行 今回の記事で使うのは scheduled trigger です。毎日 9:00 JST に動かし、その日の業務開始時に新着アナウンスを確認しやすくする構成にしています。 検証中は manual に切り替えてすぐ実行、確認が取れたら scheduled に戻す流れが安全です。 triggers: - type: manual 2-2. Workflows のテンプレート記法を先に押さえる この記事では、次のテンプレート記法を使います。 記法 意味 {{…}} 文字列として値を埋め込む ${{…}} 配列・オブジェクト・真偽値の型を保ったまま渡す steps.<name>.output 前のStepの出力を参照する foreach.item foreachで今処理中の1件を参照する 2-3. Workflow 全体 YAML ここから、今回の完成版 Workflow を載せます。 使う前に変更が必要な箇所: AI connector の設定(Default AI Connector または connectorId ) dtstart (自分のタイムゾーン・実行時刻) connector-id (自分の Slack コネクタ名) # ═══════════════════════════════════════════════════════════════ # METADATA - Identifies and describes the workflow # この Workflow は Elastic 公式アナウンスを処理し、 # 日本語要約・分類・保存・Slack 通知まで自動化します # ═══════════════════════════════════════════════════════════════ name: elastic_announcements_ai_production_V5_slack description: Process only new Elastic announcements, analyze once with AI, generate actions, store, and notify to Slack enabled: true # ═══════════════════════════════════════════════════════════════ # TRIGGER - Starts the workflow on a fixed schedule # 毎日 9:00 JST に Workflow を起動します # 朝の業務開始時に新着アナウンスを確認しやすくする設定です # ═══════════════════════════════════════════════════════════════ triggers: - type: scheduled with: rrule: freq: DAILY interval: 1 tzid: Asia/Tokyo dtstart: 2026-03-16T09:00:00+09:00 byhour: [9] byminute: [0] # ═══════════════════════════════════════════════════════════════ # STEPS - Main workflow logic # 検索 → 繰り返し処理 → 未処理判定 → AI要約 → 保存 → 通知 # という流れで処理します # ═══════════════════════════════════════════════════════════════ steps: # ──────────────────────────────────────────────────────────── # STEP 1 - Get raw announcements from Elasticsearch # raw インデックスから過去24時間分の記事を取得します # Output は hits.hits 配列で、次の foreach で1件ずつ処理します # ──────────────────────────────────────────────────────────── - name: get_raw type: elasticsearch.search with: index: elastic-announcements-raw size: 10 sort: "published" query: range: published: gte: "now-24h" lte: "now" on-failure: retry: max-attempts: 2 delay: "5s" # -------------------------------------------------------- # STEP 2.1 - Check whether this article was already processed # processed インデックスに同じ ID の記事があるか確認します # raw と processed で同じ ID を使い、重複処理を防ぎます # -------------------------------------------------------- - name: process_items type: foreach foreach: "{{ steps.get_raw.output.hits.hits }}" steps: - name: lookup_processed type: elasticsearch.search with: index: elastic-announcements size: 1 query: ids: values: - "{{ foreach.item._id }}" on-failure: retry: max-attempts: 2 delay: "3s" # -------------------------------------------------------- # STEP 2.2 - Continue only if the article is new # lookup_processed の結果が 0 件なら未処理とみなし、 # AI 要約や保存処理へ進みます # -------------------------------------------------------- - name: if_new_item type: if condition: "${{ steps.lookup_processed.output.hits.total.value == 0 }}" steps: # ---------------------------------------------------- # STEP 2.2.1 - Generate Japanese summary and category # 記事タイトルと本文を使って、日本語要約とカテゴリ分類を行います # summary_ja と category を schema で固定し、 # 後続ステップで扱いやすい構造化 output を返します # ---------------------------------------------------- - name: analyze_article type: ai.prompt with: prompt: | あなたはElastic公式アナウンスの整理担当です。 以下の記事を分析し、2つの項目を出力してください。 1. 日本語サマリー(2〜3段落) - 元の内容に忠実に - 余計な推測はしない - タイトルは含めない - 元記事にない内容は追加しない 2. category(1つ選択) - security_update - release - product_update - maintenance - other 判定ルール: - CVE / 脆弱性 / ESA / セキュリティ修正 → security_update - バージョン公開 / 一般的なリリース案内 → release - 機能追加 / 製品更新 / 改善案内 → product_update - 運用 / 停止 / 保守作業 → maintenance - どれにも明確に当てはまらない → other タイトル: {{ foreach.item._source.title }} 本文: {{ foreach.item._source.message }} schema: type: object properties: summary_ja: type: string category: type: string enum: - security_update - release - product_update - maintenance - other required: - summary_ja - category temperature: 0.2 on-failure: retry: max-attempts: 2 delay: "8s" # ---------------------------------------------------- # STEP 2.2.2 - Generate short action items # 記事の内容をもとに、最初に確認すべき対応事項だけを # 短く箇条書きで生成します # 要約だけでなく、次の行動につながる情報を作るステップです # ---------------------------------------------------- - name: generate_actions type: ai.prompt with: prompt: | 次のElastic公式アナウンス記事をもとに、ユーザーが最初に確認すべき対応事項だけを書いてください。 出力ルール: - 1〜3項目 - 各項目は箇条書きで短く書く - 元記事にない内容は追加しない - 冗長な説明は書かない - 見出しやタグは書かない 例: - 影響を受けるバージョンを確認する - 必要ならアップデートを検討する タイトル: {{ foreach.item._source.title }} 本文: {{ foreach.item._source.message }} on-failure: retry: max-attempts: 2 delay: "8s" # ---------------------------------------------------- # STEP 2.2.3 - Save processed result to Elasticsearch # AI が作成した要約・カテゴリ・対応項目を # processed インデックスに保存します # doc_as_upsert: true により、同じ ID があれば更新、 # なければ新規作成になります # ---------------------------------------------------- - name: upsert_processed type: elasticsearch.update with: index: elastic-announcements id: "{{ foreach.item._id }}" doc: source_link: "{{ foreach.item._source.link }}" title: "{{ foreach.item._source.title }}" published: "{{ foreach.item._source.published }}" summary_ja: "{{ steps.analyze_article.output.content.summary_ja }}" actions_ja: "{{ steps.generate_actions.output.content }}" category: "{{ steps.analyze_article.output.content.category }}" processed_at: "{{ execution.startedAt }}" doc_as_upsert: true on-failure: retry: max-attempts: 2 delay: "5s" # ---------------------------------------------------- # STEP 2.2.4 - Send notification to Slack # 整理した記事情報を Slack に通知します # 保存後に関係者へ共有するための最終ステップです # continue: true により、Slack 送信だけ失敗しても # 保存処理全体は止めません # ---------------------------------------------------- - name: send_slack type: slack connector-id: e3****01-****-****-****-a****c****ae with: message: | 🚨 *【お知らせ】{{ foreach.item._source.title }}* *Published:* {{ foreach.item._source.published }} *Category:* {{ steps.analyze_article.output.content.category }} *Link:* {{ foreach.item._source.link }} *Summary* {{ steps.analyze_article.output.content.summary_ja }} *Actions* {{ steps.generate_actions.output.content }} *※この通知はAIにより自動生成されています。必ず原文をご確認ください。* on-failure: retry: max-attempts: 1 delay: "10s" continue: true 注意)上の YAML をそのまま使う場合は、少なくとも次の3つを自分の環境に合わせて変更してください。 dtstart connector-id AI connector の設定(Default AI Connector または connectorId ) 2-4. この Workflow の見どころ get_raw : まず raw から必要な分だけ取る ここでの実務上の意図は、 毎回全件を再処理しないこと です。 AI を使う構成では、処理件数がそのままコストと実行時間に効いてきます。最初に対象期間を絞っておくのは、かなり重要です。 foreach : 検索結果を 1 件ずつ処理できる形にする この Step の役割は、検索結果の配列を 1 件ずつ処理できる形に変えること です。 この構造にすることで、記事ごとに AI 要約・保存・Slack 通知を個別に行えます。Workflow のデータの流れは、ここから見やすくなります。 lookup_processed + if_new_item : 重複処理を防ぐ中心 condition: "${{ steps.lookup_processed.output.hits.total.value == 0 }}" ここが重複処理を防ぐ中心です。 raw で使っている _id は link ベースなので、processed 側でも同じ ID を使えば、 「すでに処理済みか」 をシンプルに判定できます。 この設計のよいところは、Logstash 側の重複抑制と Workflow 側の未処理判定がつながっていることです。別々のキーを使うより、ずっと分かりやすくなります。 analyze_article : 要約と分類を 1 回の AI 呼び出しでまとめる この Step では、 要約とカテゴリ分類を 1 回の AI 呼び出しで同時にやっています 。 これは、コストと一貫性の両面でよい設計です。特に ` schema ` を付けて ` summary_ja ` と ` category ` を固定している点が大事です。AI の自由回答にせず、後続 Step で扱いやすい形にしています。 generate_actions : 読者の次の行動につながる情報を作る ここでは要約とは別に、 「読者が最初に何を確認すべきか」だけを抜き出しています 。 要約だけだと、「結局どう動けばいいのか」が分かりにくいことがあります。一方で、対応項目を 1〜3 個に制限しているので、Slack 上でも読みやすくなります。 この Step を入れることで、単なる翻訳ではなく、 実務で動きやすい情報 に変わります。 upsert_processed : 人が再利用しやすい形で保存する この Step で、英語 raw とは別に、日本語要約済みの processed データを保存します。 doc_as_upsert: true を使っているので、同じ ID があれば更新、なければ作成です。これにより、再実行しても扱いやすい保存先になります。 send_slack : 最後に人へ届ける Workflow は「処理して終わり」ではなく、 必要な相手に届けるところまで自動化して初めて価値が出ます 。 Slack 送信が失敗しても、その前の upsert_processed (保存)はすでに完了しています。 continue: true により、通知失敗で保存結果が失われることを防ぎます。 このworkflowで保存先を 2 層に分けています。 elastic-announcements-raw : 原文に近い保存先 elastic-announcements : 日本語要約・カテゴリ付きの加工済み保存先 この二層構造にしておくと、あとで要約ルールやカテゴリ設計を変えたくなったときも、raw から再処理できます。ここは再利用性の面でかなり大事です。 実際に Slack に届いたメッセージがこちらです。 タイトル・公開日・カテゴリ・リンクに加え、 AI が生成した日本語サマリーと具体的な対応事項(Actions)が 1通にまとまって届いています。 英語の原文を読まなくても「何が起きたか」「何をすべきか」が そのまま伝わる形になっているのが確認できます。 2-5. Workflow 実行画面では何を見るか Workflow 実行後は、Executions 画面で次を確認できます。 どの Step が成功したか どこで失敗したか 各 Step にどんな Input / Output が入ったか 各 Step の実行時間はどのくらいか 特に今回のような構成では、次を順に見ると原因を切り分けやすいです。 get_raw で記事が取れているか lookup_processed が想定通り 0 件または 1 件を返しているか analyze_article の output.content が schema 通りか upsert_processed が update 成功しているか send_slack が正常に送信できているか 「Executions」タブを開くと、この画面で実行結果を確認できます。 中央のツリーで各Stepの成否と実行時間が一覧でき、 Stepをクリックすると右ペインにInput/Outputの詳細が表示されます。 画像では analyze_article が 6s、upsert_processed が 669ms など、 各Stepの処理時間も確認できます。 2-6. ハマりやすかったポイント 1. Workflows が見えない まず疑うべきは、 workflows:ui:enabled です。 また、権限不足でも表示されないことがあります。画面が見えないときは、最初にこの 2 点を確認した方が早いです。 2. {{ }}と ${{ }}の使い分け 文字列埋め込みなら {{ }} 型を保ちたいなら ${{ }} if の条件や配列・オブジェクトには ${{ }} が必要です。ここを間違えると条件分岐が常に false になります。 3. Slack connector の違い Slack connector には、Incoming Webhook 型と Web API 型があります。 Webhook 型はシンプルですが、メッセージ表現に制約があります。チャネル選択や表現の柔軟性を重視するなら、Web API 型の方が扱いやすい場面があります。 4. テスト時は manual trigger が便利 毎回 scheduled trigger を待つより、検証中は manual trigger にしてその場で実行した方が早いです。 また、Workflow エディタでは Workflow 全体だけでなく、個別 Step の実行もできる ので、AI prompt や検索 Step を切り分けて試すのにも向いています。 5. connector-idの出し方 コネクタIDの特定がこのステップで最も難航した点でした。最終的に、Macで作業している場合、connector-idの入力欄でCMD + iを同時に押すことで、オートコンプリート機能によりIDが自動的に補完されることが判明しました。 まとめ 今回の構成で自動化できたこと: 毎日の手動チェック → ゼロ 英語読み込み → 日本語要約に置き換え 「で、何すればいい?」への回答 → 対応項目を自動生成 社内共有 → Slack に自動配信 Elastic Workflows をこれから触る人にとって、この構成は入門題材としてかなりちょうどよいと思います。 Trigger → Search → Foreach → If → AI → Update → Notify という基本パターンが全部入っており、保存や通知までつながっているからです。 今後の発展方向 ai.prompt を ai.agent に置き換えて、より高度な判断をさせる 通知先を Slack だけでなくメールやチケットシステムに広げる RSS 以外のデータソース(GitHub Releases、Elastic Blog など)に展開する セキュリティアラートや運用アラートの triage に応用する 関連記事 Elastic Stack v9.3新登場のWorkflowsでワークフローとAIエージェントによるデータ分析を実装する例 公式ドキュメント elastic/ workflows (github) The post Elastic Workflows実践:Logstash × AI要約 × Slack通知をYAMLだけでつなぐ自動化パイプラインの作り方 first appeared on Elastic Portal .
Elasticsearch は強力な REST API を備えており、ほぼすべての操作を HTTP リクエストで行うことができます。 Kibana の Dev Tools も便利ですが、CLI の王者 curl を使いこなすことで、シェルスクリプトによる自動化や、リモートサーバーでのデバッグ効率が飛躍的に向上します。 本記事では、初心者がまず覚えるべき基本コマンドから、現場で役立つ Tips までをまとめました。 ※本記事では、Windows 11 上の PowerShell から curl.exe を実行する環境を想定しています。 目次 1. 事前準備:curl.exe の導入 インストール方法 2. 共通オプションと「神オプション」 3. 効率化の鍵:PowerShell 関数を作る 4. クラスターの状態を確認する 4.1 疎通確認 4.2 クラスターの健康状態(ヘルスチェック) 5. インデックスとドキュメントの操作 (CRUD) 5.1 データの登録 (Index) 5.2 データの更新 (Update) 5.3 検索を実行する (Search) 6. 知っておくと便利な Tips 6.1 インデックス一覧を表示する (cat API) 6.2 複雑な JSON はファイルから読み込む まとめ 1. 事前準備:curl.exe の導入 Windows の PowerShell には curl というコマンドが存在しますが、これは Invoke-WebRequest という別のコマンドレットへの エイリアス(別名) です。 これは Elasticsearch の複雑な JSON リクエストを送る際に挙動が異なるため、本記事では 本家 curl.exe を使用します。 インストール方法 1: curl for Windows から最新版(例: curl-8.19.0_6-win64-mingw.zip)をダウンロード。 2: 任意のフォルダ(例: C:\curl-8.19.0_6-win64-mingw)に展開します。 3: (推奨)展開先の bin フォルダを環境変数 PATH に追加しておくと、フルパスを入力せずに実行できて便利です。 2. 共通オプションと「神オプション」 Elasticsearch へのリクエストで頻用するオプションは以下の通りです。 オプション 説明 -u [user]:[pass] 認証情報の指定。 -H “Content-Type: application/json” JSON データを送る際に必須。 -X [METHOD] GET, POST, PUT, DELETE などのメソッド指定。 –cacert [path] 自己署名証明書(SSL)を使用している場合にパスを指定。 ?pretty 必須級。 レスポンスの JSON を整形して表示します。 ※認証情報を -u user:pass の形式ではなく、API Key を渡す方法もあります。 3. 効率化の鍵:PowerShell 関数を作る 毎回長いパスや認証情報を打つのは苦行です。PowerShell の $PROFILE (C:\Users\ユーザー名\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1) に以下の変数および関数を登録してしまいましょう。 $ESURL = "https://localhost:9200" function wincurl { # 展開したパスに合わせて書き換えてください $CURL_DIR = "C:\curl-8.19.0_6-win64-mingw" & $CURL_DIR\bin\curl.exe -u elastic:password -H "Content-Type: application/json" --cacert C:\certs\ca\ca.crt $args } これで、次のようにスッキリとしたコマンドで操作が可能になります。 wincurl -X GET "$ESURL/?pretty" 4. クラスターの状態を確認する まずは Elasticsearch が正常に稼働しているか確認しましょう。 4.1 疎通確認 wincurl -X GET "$ESURL/?pretty" 正常であれば、クラスター名や Elasticsearch のバージョンを含む JSON が返ってきます。 4.2 クラスターの健康状態(ヘルスチェック) wincurl -X GET "$ESURL/_cluster/health?pretty" status 項目に注目してください: green: すべてのシャードが割り当て済み(快調) yellow: プライマリは動いているが、レプリカが未割り当て red: 一部のデータにアクセス不能 5. インデックスとドキュメントの操作 (CRUD) 5.1 データの登録 (Index) PowerShell で JSON を書く際は、全体をシングルクォーテーションで囲んで、JSON内のダブルクォーテーションを \ でエスケープする必要があります。 wincurl -X PUT "$ESURL/my_index/_doc/1?pretty" -d '{ \"user\": \"user1\", \"message\": \"Elasticsearch curl test\" }' 5.2 データの更新 (Update) _update エンドポイントを使い、doc 要素で囲んで指定します。 wincurl -X POST "$ESURL/my_index/_update/1?pretty" -d '{ \"doc\": { \"message\": \"Updated by curl\" } }' 5.3 検索を実行する (Search) 最も頻繁に使う検索リクエストです。 # 全件検索 wincurl -X GET "$ESURL/my_index/_search?pretty" # クエリ指定(Match Query) wincurl -X POST "$ESURL/my_index/_search?pretty" -d '{ \"query\": { \"match\": { \"message\": \"Elasticsearch\" } } }' 6. 知っておくと便利な Tips 6.1 インデックス一覧を表示する (cat API) GUI がなくても、現在のインデックス数やドキュメント数を把握できます。?v をつけるとヘッダーが表示されます。 wincurl -X GET "$ESURL/_cat/indices?v" 出力例: health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open my_index sFNfkveMQRejftl7xenW1Q 1 1 1 0 4.5kb 2.2kb ... 6.2 複雑な JSON はファイルから読み込む コマンドラインに長い JSON を書くのが限界に達したら、-d ‘@filename’ を使いましょう。 query.json にクエリーを記載しておきます(ダブルクォーテーションをエスケープする必要はありません)。 { "query": { "match": { "message": "Elasticsearch" } } } -d ‘@filename’ を使ってクエリーを渡す例。 wincurl -X POST "$ESURL/my_index/_search?pretty" -d '@query.json' ※注 @filename の部分は、シングルクォーテーションで囲む必要があります。 まとめ curl は Elasticsearch API の構造を理解するための最短ルートです。コマンドが「手になじむ」ようになると、スクリプトによる一括処理や、Kibana が使えない環境でのトラブルシューティングが圧倒的に楽になります。 まずは _cluster/health を叩くところから、あなたの CLI ライフを始めてみてください! The post CLI から Elasticsearch を自在に操る! curl 操作ガイド first appeared on Elastic Portal .
目次 はじめに 1. AutoOps の通知機能とは? 2. 通知の設定ステップ ステップ 1:コネクタ(Connector)の作成 1.1 コネクタ作成画面への移動 1.2 コネクタの追加 1.3 送信先情報の入力 ステップ 2:通知フィルター(Notification Filters)の設定 2.1 通知フィルターの設定 2.2 通知条件とコネクタの紐づけ 3. 動作確認 : 異常検知から復旧検知まで 3.1 異常の発生(データノードの停止) 3.2 復旧の確認 4. レポート機能 5. さらに踏み込んだカスタマイズ : イベント設定 まとめ はじめに [ 前回 ]は、AutoOps を使ってオンプレミスの Elasticsearch のインデックス情報やメトリクスを可視化する方法を解説しました。 今回は一歩進んで、AutoOps の通知(Notification)機能を活用し、異常検知から通知までを自動化する設定例を紹介します。管理画面を常時監視することなく、トラブルの予兆に素早く気づくための設定をマスターしましょう。 1. AutoOps の通知機能とは? AutoOps の通知機能を利用すると、新しいイベントの発生時や問題の解決(クローズ)時に、外部ツールへリアルタイムでアラートを飛ばすことができます。 これにより、管理画面に張り付く「監視」から、通知を受けて動く「アクション」主体の運用へとシフトでき、MTTR(平均復旧時間)の短縮にも貢献します。 2. 通知の設定ステップ 設定は大きく分けて 「どこに送るか(Connector)」 「何を・いつ送るか(Notification Filter)」 の 2 つのステップで行います。 ステップ 1:コネクタ(Connector)の作成 まず、通知をどこに送るかを設定します。AutoOps では以下の組み込みコネクタが利用可能です。 Email: 指定したアドレスへのメール通知。 Webhook: カスタム HTTP エンドポイントへの通知。 Slack: チャンネルへの投稿。 PagerDuty / Opsgenie: 障害管理ツールとの連携。 など。 ※詳細は、公式ドキュメント  https://www.elastic.co/docs/deploy-manage/monitor/autoops/ec-autoops-notifications-settings#ec-built-in-connectors  を参照してください。 今回は、基本となる Email での設定例を紹介します。 1.1 コネクタ作成画面への移動 Elastic Cloud の AutoOps のメニューから Settings > Notifications Settings をクリックします。 1.2 コネクタの追加 Connector Settings タブをクリックし [ Add ] をクリックします。 1.3 送信先情報の入力 以下の項目を設定し、[ Save ] で保存します。 Connector Type を Email にします。 Connector 名を入力します。 送信先の Email アドレスを入力します。 イベントがクローズした際にも Email を送信するよう設定しておきます。 ステップ 2:通知フィルター(Notification Filters)の設定 すべてのイベントを通知すると「アラート疲れ(Alert Fatigue)」を招きます。フィルター機能を使い、「本番環境のクリティカルな問題のみ」といった絞り込みを行うことが可能です。 ※今回は、サンプルなので、すべてのイベントを通知します。 2.1 通知フィルターの設定 Notifications Settings の Filter Settings タブをクリックし [ Add ] をクリックします。 2.2 通知条件とコネクタの紐づけ 通知したいイベントと、先ほど作成したコネクタを選択し、[ Save ] をクリックします。 Name : 通知名を入力します。 Clusters: 今回の監視対象のクラスタを選択します。 Connectors : 先ほど設定した Email 送信用のコネクタを選択します。 Delay : No Delay としておきます。 Events : 通知対象とするイベントを選択します。 画面左側にあるイベントが「通知対象」です。今回は、動作確認のため、すべてのイベントを左側に配置します。 3. 動作確認 : 異常検知から復旧検知まで 実際に異常を発生させて、通知の流れを確認してみます。 3.1 異常の発生(データノードの停止) 前回の Docker コンテナ環境で、わざと Elasticsearch の データノード es02 のコンテナを停止させてみます。 しばらく待つと、AutoOps が異常(The cluster status is yellow)を検知し、以下のような Email が送信されてきます(日時は UTC 表記)。 3.2 復旧の確認 再度、es02 のコンテナを開始します。しばらく待つと、問題が解消されたことを示す「No longer detected」通知が届きます。 このように「異常発生」と「障害からの復旧」の両方を把握できるのが AutoOps 通知の強みです。 4. レポート機能 Reports > Notifications 画面では、過去に送信された通知履歴を一覧で確認できます。「特定の時間帯にアラートが頻発していないか」「通知が多すぎていないか」といった運用状況の振り返りや、キャパシティプランニングの材料として役立ちます。 ※参考URL  https://www.elastic.co/docs/deploy-manage/monitor/autoops/ec-autoops-notifications-settings#ec-notification-report 5. さらに踏み込んだカスタマイズ : イベント設定 AutoOps では、通知のトリガーとなるイベントの「重大性」や「閾値」が詳細に定義されています。 重大性:大 (Critical) No master node was discovered(master node不在)など 重大性:中 (Major) The memory usage is too high(メモリ高負荷) Long running index task(インデックス処理の遅延)など 重大性:小 (Warning) Some data nodes do not contain any shards(シャード未割り当て)など これらの詳細設定は、Settings > Events Settings 画面で確認・カスタマイズが可能です。例えば「Long running index task」の検知時間を変更することで、自社のワークロードに合わせた最適なアラート運用を構築できます。 まとめ Elastic Cloud AutoOps の通知設定を適切に行うことで、リアクティブな(起きてから対処する)運用から、プロアクティブな(予兆を掴んで対処する)運用へと進化させることができます。 「通知が多すぎて無視してしまう」状態にならないよう、フィルター機能を活用して本当に必要なアラートを厳選することから始めてみてください。あなたのクラスタの安定稼働のために、ぜひこの機会に通知設定を見直してみましょう! The post AutoOps の Notification を使った Elasticsearch の異常検知および通知 first appeared on Elastic Portal .
情報源: Elastic on Defence Cyber Marvel 2026: A Technical overview from the Exercise Floor Elastic Security Labs に掲載された DCM26 の記事をもとに、本ブログでは構成や設計上のポイントを整理します。 サイオステクノロジー株式会社 Saman イギリス国防省主催の Defence Cyber Marvel 2026(DCM26) は、伝統的なITネットワーク、企業環境、複雑な産業制御システムを対象にした、英国最大級の軍事サイバー演習です。形式としては force-on-force 型 が採用されており、防御を担う Blue Team が担当システムを守り、攻撃を担う Red Team がさまざまな手法で侵入や妨害を試みます。さらに、その攻防を White Team が監視し、システム可用性、攻撃検知、インシデント報告、復旧状況などをもとに評価します。つまり DCM26 は、単なる製品検証やデモではなく、攻撃・防御・評価が同時に進む実戦型の演習として設計されていました。 DCM26には 29カ国・70組織から 2,500人以上が参加し、5,000を超える仮想システムが稼働しました。演習は 2026年2月に5日間にわたって行われ、シンガポールの Exercise Control を中心に運営されました。Blue Team は地理的に分散した状態で参加し、英国内や海外の拠点から VPN 経由で演習環境に接続していました。この前提だけでも、参加者全員に同じ環境を安全に配布し、チームごとに厳密に分離しながら、攻撃と防御を同時に成立させる必要があったことがわかります。 こうした前提の中で、Elastic は DCM26 全体を役割ごとに異なる形で支えていました。特に中心となったのは Blue Team 向けの単一マルチテナント基盤ですが、それに加えて Red Team 向けには C2 可視化用の専用デプロイメント、NSOC 向けには演習全体と AI 利用監査を担う専用デプロイメントも用意されていました。つまり Elastic は、攻撃・防御・運営の各レイヤーをそれぞれに合った構成で支えていたのです。 目次 Blue Team基盤の設計 データ分離の仕組み 事前検証と負荷テスト 演習向けの防御設定 Red TeamとNSOCの基盤 AI活用のガバナンス Attack Discoveryの役割 3つのAI活用レイヤー 感情分析という試み まとめ 用語集 Blue Team基盤の設計 Blue Team 向けの中心構成は、単一の Elastic Cloud デプロイメント をベースにしたマルチテナント設計でした。記事では、40の defending Blue Teams を支える単一デプロイメントが中核として紹介され、チームごとの分離には Kibana Spaces と datastream namespaces が使われていたと説明されています。 この設計の価値は、規模が大きいほどはっきりします。各チームに個別クラスタを割り当てれば分離はしやすい一方で、構築・更新・監視の負荷が急増します。逆に、単一デプロイメントに集約しつつ Spaces と権限制御でチーム単位に分ければ、標準化しやすく、全体運用も現実的になります。DCM26は、このマルチテナント方式を大規模演習に適用した実例でした。 データ分離の仕組み この構成では、見た目のワークスペースを分けるだけでなく、データの流れ自体もチーム単位で整理されていました。各チームには bt_01_deployed や bt_01_hostnation のような datastream namespace が割り当てられ、読み取り権限もその namespace に応じて制御されていました。認証は Keycloak SSO と Elasticsearch の role mapping でつながれており、どのユーザーがどのチーム空間に入れるかも明確に管理されていました。 この点が重要なのは、マルチテナント環境で本当に避けたいのは UI 上の見え方ではなく、データ境界の破れ だからです。DCM26では、Spaces・データストリーム・認証・権限の各レイヤーをそろえることで、演習に必要な厳格な分離を成立させていました。 事前検証と負荷テスト このアーキテクチャは、ぶっつけ本番で採用されたわけではありません。事前には 50 の Kibana Spaces を用意し、space-scoped Fleet policies を作成したうえで、6,000台の EC2 インスタンスを使った負荷検証が行われました。そこで確認されたのは、データ漏えいが起きないこと、Fleet ポリシー更新が 60 秒以内に伝播すること、space ごとに絞った検索が高負荷でも高速に動作することなどです。 また、6,000台を一度に起動しようとすると AWS EC2 API のレート制限に当たるため、500台ずつ段階的に起動し、間に 5 分のクールオフを挟む形で展開していました。こうした地道な調整も含めて大規模構成を実運用レベルに引き上げていた点は、この事例の大きな価値です。 演習向けの防御設定 Blue Team には、System、Elastic Defend、Windows event forwarding、Auditd、Network Packet Capture などの統合が配布されていました。ただし、 Elastic Defend はそのままだと防御力が高すぎるため、演習中は Prevent mode を無効にし、Detect-only mode で使われていました 。さらに Memory Threat Prevention and Detection も、演習の大部分では無効化されていました。 ここからわかるのは、DCM26が単に「製品機能を最大限見せる場」ではなかったということです。重要だったのは、防御側がきちんと検知し、判断し、対応する訓練を成立させることでした。そのために、製品の強さをあえて制限する判断が取られていたのです。 Red TeamとNSOCの基盤 Blue Team 向けの中心基盤とは別に、Red Team 向けの専用 Elastic デプロイメントと、NSOC 向けの専用デプロイメントも用意されていました。Red Team 側では、Tuoni という C2 フレームワークの状態、ビーコンのコールバック、攻撃オペレーションの進行状況を観測するための基盤として Elastic が使われていました。 一方の NSOC では、演習全体のヘルス状況やセキュリティ監視に加え、AI利用の監査も対象に含まれていました。特に Bedrock API の呼び出しは CloudWatch に記録され、それが NSOC 側の Elastic デプロイメントから観測できるようになっていました。AIもまた、監視されるべき運用対象として扱われていたわけです。 AI活用のガバナンス DCM26では AWS Bedrock を基盤として AI を活用していましたが、運用はかなり慎重に設計されていました。Bedrock Guardrails により、ヘイト、侮辱、性的内容、暴力といった不適切コンテンツ、PII、さらに実際の機密作戦や現実世界の軍事活動に関わる話題を制限していました。 この点は、企業で生成AIを導入するときにも重要です。先に問われるのは「どれほど賢いか」ではなく、「何を扱わせてよいか」「誰が使ったかを追跡できるか」「扱ってはいけない情報に触れないか」です。DCM26は、AIの性能以前に、AIを安全に運用するための条件を固めていた事例として読めます。 Attack Discoveryの役割 演習中、Blue Team は大量のアラートに向き合う必要がありました。そこで有効だったのが Attack Discovery です。複数のアラートを相関し、攻撃の流れをストーリーとして整理することで、平均対応時間の短縮や alert fatigue の軽減に役立ったと説明されています。 ここでの役割は、すべてを自動で解決することではありません。ばらばらのシグナルを整理し、何から見るべきかを判断しやすくすることです。つまり、防御側の判断を置き換えるのではなく、 判断しやすい状態を作る ための支援として位置づけられていました。 3つのAI活用レイヤー DCM26のAI活用を理解するうえでは、この3つを混ぜないことが大切です。まず Elastic AI Assistant や Attack Discovery は、Elastic Security の標準機能として、防御側の調査やアラート理解を助ける役割を担っていました。 一方で Agent Builder は、役割別のカスタムAIエージェントを作るために使われていました。全参加者向けの IT サポートを担う GrantPT 、White Team 向けの採点支援を担う RefPT 、Red Team 向けの攻撃支援を担う Red Rock がその例です。GrantPT は手順書や過去のサポートチケットを参照し、RefPT は提出レポートや演習イベントをもとに採点を支援し、Red Rock は脆弱性や攻撃ベクトルの知識を使って Red Team を助けていました。 さらに Tines は AI そのものではなく、自動化フローの基盤として使われていました。サポート要求が発生すると Tines が動き、Bedrock AI と連携しながら過去の解決策を参照して応答を補助し、サポートキューの負荷を下げていました。つまり、Elastic AI Assistant は調査支援、Agent Builder は役割特化のエージェント構築、Tines は運用自動化と、それぞれの役割は明確に分かれています。 感情分析という試み 演習中には RocketChat の会話全体を Elastic に取り込み、Named Entity Recognition と感情分析を通じて、会話内容やチーム状態の変化を捉える取り組みも行われました。攻撃や障害だけでなく、参加者側のストレスや混乱の兆候も、運営が把握する対象に含まれていたわけです。 大規模演習では、システム異常だけでなく、人の疲労や情報過多も成果に直結します。Elastic がログ以外のテキストデータも同じ基盤で扱えることが、こうした運営の立体化につながっていました。 まとめ DCM26が示したのは、AIの価値は単にモデルを導入することでは生まれない、ということです。大規模データを処理できる基盤、チームごとに厳密に分離された設計、アラートを文脈化する機能、役割別に作られたエージェント、そして AI 利用そのものを監査できる運用モデル。これらがそろってはじめて、AIは実戦的な価値を持ちます。 Elastic はこの演習で、単なるログ基盤や SIEM としてではなく、可視化・検知・AI支援・自動化連携をつなぐ中核として機能していました。ただしそれは Elastic 単独で完結した話ではなく、AWS Bedrock、Tines、Tuoni などとの連携も含めて成立した構成です。DCM26は、AI時代のセキュリティ基盤に必要なのが強い機能の寄せ集めではなく、安全に運用できる一貫した設計 であることを示した事例だと言えるでしょう。 用語集 Elastic 検索、ログ分析、セキュリティ監視、可観測性などをまとめて扱えるプラットフォームです。大量のデータを集めて、見える化し、分析し、異常や攻撃の兆候を見つけるために使われます。 仮想システム 物理的な専用機器ではなく、ソフトウェア上で動くサーバーや端末環境のことです。クラウドや仮想化技術を使って、多数のシステムを柔軟に用意できます。 イベント システム上で起きた出来事を記録したものです。たとえばログイン、ファイル作成、通信、エラー発生などがイベントです。 EPS(Events Per Second) 1秒あたりに処理されるイベント数です。ログやセキュリティイベントがどれくらい大量に流れているかを見る目安です。 マルチテナント 1つの大きなシステムを、複数のチームや組織で共用する考え方です。たとえば1つの建物の中に、別々の会社がそれぞれ専用の部屋を持って入っているイメージです。 テナント マルチテナント環境の中で、各チームや各組織に割り当てられた独立した利用領域のことです。 アクセス制御 誰がどのデータや機能を使えるかを決める仕組み全体を指します。 インフラ自動化 サーバー構築、設定反映、ソフトウェア配布などを手作業ではなく自動で行う考え方です。大規模環境ほど重要になります。 Kibana Elasticに入ったデータを画面で見たり、検索したり、グラフやダッシュボードを作ったりするための画面ツールです。 Kibana Spaces Kibanaの中で、チームごとに画面やダッシュボード、設定を分けるための仕組みです。同じKibanaを使っていても、チームAにはA用の画面、チームBにはB用の画面を見せられます。 Keycloak SSOやユーザー認証、権限管理を行うためのソフトウェアです。誰がどのサービスに入れるかを一元的に管理できます。 SSO(Single Sign-On) 一度のログインで、複数のシステムを使えるようにする仕組みです。何度も別々にIDとパスワードを入れなくて済みます。 自動スケーリング(Autoscaling) 負荷が増えたときに、必要なリソースを自動で増やす仕組みです。逆に負荷が減れば縮小できます。 RBAC(Role-Based Access Control) 役割ベースのアクセス制御です。「この人はこの役割だから、このデータだけ見られる」というように、ロールに応じて権限を決める考え方です。 DLS(Document Level Security) ドキュメント単位のアクセス制御です。同じデータベースの中でも、「このユーザーにはこの文書だけ見せる」「別の文書は見せない」と細かく制御できます。 ドキュメント Elasticの中に保存される1件1件のデータのことです。たとえば1つのログ記録、1つのイベント記録が1ドキュメントになります。 AIガバナンス AIを安全かつ適切に使うための管理の考え方です。何をAIにさせるか、何を禁止するか、記録をどう残すかなどを決めます。 PII(Personally Identifiable Information) 個人を特定できる情報のことです。氏名、電話番号、メールアドレスなどが代表例です。 監査ログ 誰が、いつ、何をしたかを記録するログです。あとで追跡や確認ができるように残します。 CloudWatch AWS上のログやメトリクスを監視・保存するサービスです。 AWS Amazon Web Servicesの略です。Amazonが提供するクラウドサービス群のことです。 IaC(Infrastructure as Code) インフラをコードで管理する方法です。サーバーや設定を手作業で作るのではなく、設定ファイルやコードで自動的に作れるようにします。 Terraform IaCを実現する代表的なツールの1つです。クラウド環境やインフラ構成をコードで定義し、同じ環境を何度でも再現できます。 HashiCorp Vault パスワード、トークン、認証情報などの秘密情報を安全に保管・配布するためのツールです。 Catapult 記事内では、監視エージェントの展開を自動化するために使われたツールとして登場します。大量の環境に同じ設定を一括で配る役割を持ちます。 Fleet エージェントと通信し、設定を配信するための仲介サーバーです。 ポリシー システムに適用する設定ルールのことです。たとえば「このログを集める」「この挙動を監視する」などを定義します。 エージェント 各サーバーや端末に入れて、ログ収集や監視を行う小さなプログラムです。 データストリーム(Data Stream) 時系列で増え続けるデータを効率よく保存・管理するための仕組みです。ログや監視データのように、時間とともにどんどん追加されるデータに向いています。 ILM(Index Lifecycle Management) インデックスを、作成から削除まで自動で管理する仕組みです。たとえば「古いデータは圧縮する」「30日後に削除する」といったルールを自動化できます。 インデックス Elasticでデータを保存する単位です。本でいうと「1冊の本」、データベースでいうと「表」に近いイメージです。 ストレステスト 高い負荷をかけて、システムが耐えられるかを確認するテストです。本番前に限界や弱点を見つけるために行います。 EC2 AWS上で仮想サーバーを起動できるサービスです。必要な台数のサーバーをクラウド上で柔軟に用意できます。 Attack Discovery 多数のアラートやイベントを関連づけて、「1つの攻撃の流れ」として整理するElasticの機能です。ばらばらの警告を、そのままではなく意味のある攻撃ストーリーにまとめます。 アラート 「異常の可能性がある」「確認が必要」とシステムが知らせる通知です。 Initial Access 攻撃者が最初にシステムへ入り込む段階です。たとえば不正ログインや脆弱性悪用が含まれます。 Lateral Movement 攻撃者が、最初に侵入した1台から別の端末やサーバーへ横に広がっていく動きです。 Exfiltration データの持ち出しです。攻撃者が機密情報を外部へ送る段階を指します。 MITRE ATT&CK サイバー攻撃者の手口を体系的に整理した有名なフレームワークです。攻撃の段階や方法を共通言語として扱うためによく使われます。 相関分析 ばらばらに見える複数のデータの関係を見つける分析方法です。個別では小さな異常でも、つなげると大きな攻撃の流れが見えることがあります。 Agent Builder 用途ごとに専用のAIエージェントを作るための機能です。利用者、目的、参照データに応じて、役割別のAIを設計できます。 AIエージェント 特定の目的や役割を持って動くAIです。単なる雑談AIではなく、「サポート担当AI」「分析担当AI」のように仕事が決まっています。 Jira チケット管理や問い合わせ管理によく使われるツールです。障害対応やタスク管理で広く使われています。 SOP(Standard Operating Procedure) 標準作業手順書です。日常運用やトラブル対応で「この順番で対応する」という標準手順をまとめた文書です。 脆弱性 システムやソフトウェアにある弱点のことです。攻撃者に悪用される可能性があります。 可観測性(Observability) システムの状態を、外から十分に把握できるようにする考え方です。問題が起きたときに「今どこで何が起きているか」を見えるようにします。 Blue Team 防御側チームです。攻撃を検知し、調査し、守る役割を担当します。 Red Team 攻撃側チームです。実際の攻撃者を模して侵入や攻撃を行い、防御側の弱点を明らかにします。 NSOC ネットワークやセキュリティの運用全体を監視・統制する役割を持つ運用センターを指します。ここでは演習全体を見守る統制側として使われています。 White Team 演習の運営や審判を行うチームです。ルール管理や評価、全体統制を担当します。 Elastic Defend Elasticのエンドポイント防御・可視化機能です。端末上の挙動を監視し、脅威検知や調査に役立てます。 PCAP ネットワーク通信の中身を記録したデータ形式です。どんな通信が流れていたかを詳しく調べるときに使います。 感情分析 テキストから、その内容がポジティブかネガティブか、怒りや疲労の傾向があるかなどを分析する方法です。 Rocket.Chat チャットやチームコミュニケーションに使うツールです。Slackのような役割を持つソフトウェアです。 ゼロショットNLP 事前に細かく追加学習させていない分類でも、AIが文章の意味を見てテーマやカテゴリを判断する方法です。 NLP(Natural Language Processing) 自然言語処理のことです。人間の言葉をAIやコンピュータで扱えるようにする技術分野です。 ベクトル化 文章や画像を、AIが比較しやすい数値の形に変換することです。 クラスタリング 似ているデータを自動でグループ分けする分析手法です。 人的指標 システムの数字だけではなく、人の疲労、混乱、士気の変化などを表す観点です。運用の現場では、こうした人の状態も重要な判断材料になります。 The post DCM26事例:国防省主催の大規模演習を支えたElasticセキュリティの基盤設計とAI支援 first appeared on Elastic Portal .
目次 概要 実現できること AutoOps とは システム構成イメージ サンプルの内容 動作確認環境 ファイルの説明 セットアップ手順 1. パスワードなどの設定 2. コンテナの起動 3. オンプレミス側での API Key の発行 3.1. オンプレミス Kibana へのログイン 3.2. API Key の発行 3.3. Home 画面 3.4. Welcome 画面 3.5. API Key 作成画面 3.6. API Key の貼り付け 4. Cloud Connect 4.1. メニュー移動 4.2. Elastic Cloud へのログイン 4.3. Cloud Connect API Key の取得 4.4. 接続 5. AutoOps の有効化と接続 5.1. Connect AutoOps 5.2. Configure Docker Agent 5.3. Docker Compose 用の設定 5.4. AutoOps の Docker コンテナのビルド 5.5. Elastic Cloud 側での受付開始 6. AutoOps 画面 6.1. Overview 6.2. Cluster 6.3. Nodes 6.4. Indices 6.5. Shards 6.6. その他 まとめ 概要 本ブログは、オンプレミス環境の Elasticsearch のインデックス情報やメトリクスを Elastic Cloud 上で一元監視する Elastic AutoOps の紹介記事です。 実現できること オンプレミス環境の Elasticsearch ノードの稼働状態、パフォーマンス、リソース使用率の可視化 インデックス情報、シャード配置、スレッドプールなどの詳細監視 Elastic Cloud の管理画面からの統合的なヘルスチェック AutoOps とは Elastic AutoOps は、Elasticsearch クラスターの健全性を維持するための監視・最適化支援ツールです。 無料ユーザーでも利用できます。 参考URL https://www.elastic.co/docs/deploy-manage/monitor/autoops https://www.elastic.co/jp/blog/autoops-free https://www.elastic.co/jp/platform/autoops https://www.elastic.co/search-labs/jp/blog/elastic-autoops-self-managed-elasticsearch システム構成イメージ Elastic Agent がオンプレミス環境の Elasticsearch のインデックス情報や、各種メトリクスを取得し、それらを Elastic Cloud へセキュアに送信します。 これにより、外部からセキュアにインデックス情報やCPU使用率などの監視が可能になります。 サンプルの内容 Elasticsearch 環境 docker-compose.yml, .env.sample オンプレミス Elasticsearch をコンテナとして動作させます。 AutoOps エージェント環境 docker-compose-autoops.yml, Dockerfile-autoops メトリクスを転送するためのエージェントを構成します。 動作確認環境 Elastic Cloud (無償アカウントで利用可能) Docker 実行環境 筆者は Windows 上の Rancher Desktop 1.20.1 で動作確認 オンプレミス Elasticsearch: v9.3.3 (Basic License) 自動でダウンロードされます。 AutoOps: v9.3.2 執筆時点で v9.3.3 での動作検証ができなかったため、v9.3.2 を使用しています。 自動でダウンロードされます。 ファイルの説明 ※下記のファイルは、 https://github.com/SIOS-Technology-Inc/elastic-blogs/blob/main/2026-04-autoops/README.md で公開しています。 ファイル 説明 備考 .env.sample 環境変数のテンプレート .env にコピーして使用 docker-compose.yml Elasticsearch 本体の構成 Master : 3 nodes, Data : 2 nodes, Kibana docker-compose-autoops.yml AutoOps用エージェントの構成 Dockerfile-autoops AutoOps用カスタム Dockerfile セットアップ手順 [!IMPORTANT] ※事前に Elastic Cloud のアカウントが必要です。(無償アカウントでも可) 1. パスワードなどの設定 .env.sample を .env にコピーし、パスワードや暗号化キー、メモリサイズを編集します。 cp .env.sample .env 主な設定項目 CLUSTER_NAME : 監視画面に表示されるクラスタ名 ELASTIC_PASSWORD : 任意のパスワード KIBANA_PASSWORD : 任意のパスワード SAVEDOBJECTS_ENCRYPTIONKEY: 32文字以上のランダムな文字列 MEM_LIMIT : 各コンテナに割り当てるメモリの上限サイズ 2. コンテナの起動 Rancher Desktop 等の Docker ランタイムが起動していることを確認し、以下を実行します。 docker-compose up -d --build オンプレスの Elasticsearch 9.3.3 のダウンロードが行われるため、しばらく時間がかかります。 3. オンプレミス側での API Key の発行 AutoOps から オンプレミス Elasticsearch へ接続するための API Key を発行します。 3.1. オンプレミス Kibana へのログイン http://localhost:5601 へアクセスしログインします。 user: elastic password : .env ファイルの ELASTIC_PASSWORD に設定したパスワード 3.2. API Key の発行 オンプレミス Elastic の Home 画面上で、AutoOps から オンプレミス Elasticsearch へアクセスするための API Key を発行します。 3.3. Home 画面 Home 画面で Elasticsearch を選択します。 3.4. Welcome 画面 Welcome 画面が表示されるので、右上の [(+) API keys] をクリックします。 3.5. API Key 作成画面 API Key 作成画面が表示されるので、API key name に autoops_key と入力し、 [Create API key] をクリックします。 3.6. API Key の貼り付け 生成された API Key が画面に表示されるので、これをコピーして、 .env ファイルの AUTOOPS_ES_API_KEY に貼り付けます。 AUTOOPS_ES_API_KEY=... 4. Cloud Connect オンプレミス Elasticsearch を Elastic Cloud に紐づけます。 4.1. メニュー移動 Home > Management > Cloud Connect をクリック。 4.2. Elastic Cloud へのログイン [Log in]をクリックします。その後、画面の指示に従い Elastic Cloud へログインします。 4.3. Cloud Connect API Key の取得 画面の指示に従い Cloud Connect API Key を取得します。 4.4. 接続 取得したキーをオンプレミスの Kibana 上の入力欄にペーストし、[Connect] をクリックします。 5. AutoOps の有効化と接続 5.1. Connect AutoOps Elastic Cloud 側で操作します。 画面に沿って Connected Clusters の Connect AutoOps 画面へ進みます。 ※もしも、次の画面が表示されたら、画面下の Just want AutoOps ? の Get started をクリックしてください。 AutoOps Agent のインストールタイプを聞かれますが、今回は Docker を使用しているので、Docker をクリックします。 5.2. Configure Docker Agent AutoOps の設定画面が表示されるので、今回は、Elasticsearch endpoint URL に https://es01:9200 を入力します。 authentication method が API key となっていることを確認して、[Next]をクリックします。 5.3. Docker Compose 用の設定 Docker か Docker Compose かを選択する画面になるので、Docker Compose を選択し、 画面に表示されているコマンドをコピーします。 本来であれば、これをそのまま動かしたいところなのですが、この画面に表示されている内容だと Elasticsearch の SSL 設定が考慮されていません。 したがって、本サンプルでは SSL に対応した docker-compose-autoops.yml を用意しています。 画面からコピーしたコマンドの内容を元に下記の4つの値を .env ファイルへ転記していきます。 AUTOOPS_OTEL_URL=... ... AUTOOPS_TOKEN=... ... ELASTIC_CLOUD_CONNECTED_MODE_API_KEY=... ... AUTOOPS_TEMP_RESOURCE_ID=... ※ 値の部分を ‘…’ や “…” で囲む必要はありません。 5.4. AutoOps の Docker コンテナのビルド docker-compose -f ./docker-compose-autoops.yml up -d --build AutoOps用の Elastic Agent 9.3.2 がダウンロードされるため、しばらく時間がかかります。 5.5. Elastic Cloud 側での受付開始 コンテナが動き出したら、Elastic Cloud の先ほどの画面の右下の [I have run the command] をクリックします。 6. AutoOps 画面 しばらくすると、オンプレミス Elasticsearch の各種情報が AutoOps 画面で確認できるようになります。 6.1. Overview 6.2. Cluster 6.3. Nodes 上記は、Nodes の Activity を表示した画面ですが、Activity 以外にも下記を表示することができます。 Host and process Thread Pools Data Http Circuit Breakers Network Disk Activity-Additional 6.4. Indices 6.5. Shards 6.6. その他 他にも下記の画面が用意されています。実際に使ってみてください。 Template Optimizer Notifications Notifications Settings Events Settings Dismiss Events まとめ 本サンプルを通じて、Elastic Cloud Connect を利用することで、セルフマネージド(オンプレミスや独自のクラウド環境)で運用している Elasticsearch クラスターを、 Elastic Cloud 上の高度な運用支援機能「AutoOps」 にシームレスに統合できることを確認しました。 本構成のメリット 運用負荷の軽減: 複雑な監視ダッシュボードを自作することなく、Elastic 公式のベストプラクティスに基づいた監視画面(スレッドプール、サーキットブレーカー、シャード配置など)を即座に利用できます。 一元管理: 複数のセルフマネージドクラスターを Elastic Cloud という単一のコントロールプレーンで俯瞰できるようになります。 最適化の示唆: Template Optimizer などの機能により、インデックス設計の改善点など、パフォーマンス向上に直結する気づきを得られます。 次のステップへのヒント 本サンプルは評価・学習用としての最小構成です。実運用に向けては、以下の検討をお勧めします。 証明書の管理 本サンプルでは SSL 接続を簡略化していますが、本番環境では適切な CA 証明書による検証を検討してください。 アラート通知 Notifications Settings を利用して、Slack やメールへの通知設定を行い、異常検知を自動化しましょう。 リソース監視の深化 Host and process メトリクスを深掘りし、Elasticsearch プロセスだけでなく、ホスト OS 側のリソース逼迫状況との相関を分析してみてください。 このサンプルが、皆さまの Elasticsearch 運用自動化(AutoOps)の第一歩となれば幸いです。 The post AutoOps を使ってオンプレミスの Elasticsearch のインデックス情報、メトリクスを Elastic Cloud で監視する first appeared on Elastic Portal .
少し間が空きましたが、シリーズを再開します。 第1〜3回でデータの取り込み・最初のルール作成・Timelineでの 攻撃チェーン調査まで進みました。第4回はその続きです。 EQLのsequenceで「失敗のあとに成功した」攻撃パターンを 自動検出し、ES|QLで「どのIPが最も危険か」「何バイト送られたか」 を数値で把握する方法を紹介します。CaseとNotesを使った 調査記録の残し方も扱います。 シリーズのこれまでの流れ: 1回目  環境構築とログの取り込み 2回目  KQLでログを読んで最初のルールを作る 3回目  Timelineで攻撃の全体像を追う ← ここまで完了している前提 ※本シリーズで使用するデータセットは、 第1回 の記事からダウンロードできます。 目次 この記事を読むと何ができるか EQL(Correlation)で攻撃の「順序」を自動検出する ES|QLで集計・分析する クエリ1:ログイン失敗をIPごとに集計する クエリ2:攻撃対象のユーザー名を集計する クエリ3:大容量通信を探す Caseに調査内容を登録する Notesで調査メモを残す この章のまとめ 第4回チェックリスト この記事を読むと何ができるか EQLのsequence構文で攻撃の順序パターンを自動検出できる ES|QLでIPごとのログイン失敗件数・大容量通信を集計できる CaseとNotesで調査内容をチームで共有・記録できる EQL(Correlation)で攻撃の「順序」を自動検出する なぜ使うのか 第3回では「目でイベントを追って」攻撃の流れを確認しました。しかし実務では、1日に何千件ものイベントが流れる中から「特定の順番で起きたイベントの組み合わせ」を手動で見つけるのは現実的ではありません。 EQL(Event Query Language)の sequence 構文を使うと、「AのあとにBが起きた組み合わせ」を自動で検出できます。 EQLのsequenceクエリを書く このサンプルデータでは event.category の値が "iam" です。Elastic SecurityのEQLパーサーが期待する authentication カテゴリとは名称が異なるため、 any where event.category == "iam" という書き方を使います。 TimelineのCorrelationタブを開き、次のクエリを入力します。 sequence by source.ip [ any where event.category == "iam" and event.action == "user-login" and event.outcome == "failure" ] [ any where event.category == "iam" and event.action == "user-login" and event.outcome == "success" and user.name in ("admin_root", "admin", "root", "administrator") ] このクエリの意味を整理します。確認ポイント: source.ip: 192.168.1.100 のシーケンスが検出されているか 1つ目のイベント(failure)と2つ目のイベントが時系列順に並んでいるか 45.33.21.11 のシーケンスも検出されているか EQLでできること・できないことを整理しておきます。 できること できないこと イベントの順序を条件にする 集計・合計値の計算 複数イベントをまとめて1件として扱う フィールドの加工・変換 時間的な近接(maxspan)を条件にする 複数インデックスにまたがる複雑な結合 集計や加工が必要なときは、次のES|QLを使います。 ES|QLで集計・分析する KQLは「条件に一致するイベントを見つける」検索ツールです。一方ES|QLは「見つけたイベントを集計・加工・ランキングする」分析ツールです。「どのIPが一番多く失敗しているか」「何バイト送られたか」を素早く把握したいときに使います。 ES|QLはパイプ( | )でコマンドをつなげる構造です。「FROMでデータを取り出し、WHEREで絞り込み、STATSで集計し、SORTで並べる」という順番で読むと理解しやすいです。 TimelineのES|QLタブを開きます。 クエリ1:ログイン失敗をIPごとに集計する FROM training-security-logs | WHERE event.action == "user-login" AND event.outcome == "failure" | STATS failure_count = COUNT(*) BY source.ip | SORT failure_count DESC 期待される結果: source.ip failure_count 45.33.21.11 8 192.168.1.100 4 45.33.21.11 が外部から8回、 192.168.1.100 が内部から4回失敗していることが一目でわかります。 クエリ2:攻撃対象のユーザー名を集計する FROM training-security-logs | WHERE event.action == "user-login" AND event.outcome == "failure" | STATS attempt_count = COUNT(*) BY user.name | SORT attempt_count DESC 期待される結果: user.name attempt_count guest 5 admin_root 3 administrator 2 admin 1 root 1 guest が最も多く試されています。攻撃者が「存在しそうなデフォルトアカウント名」から順番に試している典型的なパターンです。 クエリ3:大容量通信を探す FROM training-security-logs | WHERE event.action == "data-transfer" | STATS max_bytes = MAX(network.bytes), total_bytes = SUM(network.bytes) BY source.ip, destination.ip | WHERE max_bytes > 10000000 | SORT max_bytes DESC 期待される結果: source.ip destination.ip max_bytes total_bytes 192.168.1.100 103.10.10.100 85,000,000 85,000,000以上 103.10.10.100 への85MB超の転送が浮かび上がります。このようなデータ量ベースの異常検知はKQLでは書けず、ES|QLが得意とする用途です。 Caseに調査内容を登録する セキュリティ調査は個人作業ではありません。「何を見つけたか」「誰が対応しているか」「どう判断したか」をチームで共有し、記録として残すことが実務では不可欠です。 Security → Alerts を開き、 source.ip: 192.168.1.100 のアラートをクリックして flyout を開きます。「Add to existing case → Add to new case」を選択します。 Case の記入例: 項目 入力例 タイトル 内部ブルートフォース攻撃 from 192.168.1.100 Severity Medium(ログイン成功・データ持ち出しが確認されているため) Tags brute-force , data-exfiltration , prod-srv-01 説明欄のテンプレート(初動調査メモ): ## 概要 2025-03-18 UTC 10:01〜10:10 の間に、192.168.1.100 から PROD-SRV-01 に対する一連の攻撃を確認。 ## 確認された活動 - 10:01台:ポートスキャン(445, 139, 80, 3389, 22) - 10:03台:admin_root へのブルートフォース → 10:03:06 に成功 - 10:03〜10:04台:whoami, net user, net localgroup による偵察 - 10:05〜10:07台:スケジュールタスク・レジストリによる永続化 - 10:06〜10:10台:103.10.10.100 への C2 接続・85MB のデータ持ち出し ## 次のアクション - [ ] 192.168.1.100 の所有者・用途を確認する - [ ] admin_root アカウントのパスワードを即時変更する - [ ] 103.10.10.100 への通信をブロックする - [ ] PROD-SRV-01 のスケジュールタスク・レジストリを精査する CaseのSeverityをアラートのSeverityより高くした理由:第2回で作ったルールはSeverity: Low(単純なログイン失敗の検知)でした。しかしTimelineで調査した結果、ログイン成功・永続化・データ持ち出しまで確認できました。ルールのSeverityはイベントの性質、CaseのSeverityは調査で判明した実際の影響度を反映させます。 Notesで調査メモを残す Timelineは分析ツールですが、「自分が何を考えながら調査したか」はTimelineには残りません。Notesを使うことで、「事実(ログ)」「解釈(何が起きているか)」「仮説(次に何を確認すべきか)」を時系列のイベントに紐づけて残せます。 Timelineで気になるイベントの行にカーソルを合わせ、行左端のアクションアイコンから「Add note」をクリックします。 良いNotesには3つの要素があります。 要素 内容 例 事実 ログから読み取れること 10:03:06 に admin_root で user-login success 解釈 そのイベントが意味すること ブルートフォース成功。この時点から侵害が始まっている 仮説・次のアクション 次に確認すること 10:03:06 以降の admin_root の行動を追う 実際のメモ例(10:03:06の成功イベントに紐づけて記録): 【事実】 192.168.1.100 から admin_root での user-login が success。 直前の 10:03:00〜10:03:05 に同 IP から失敗が4件続いている。 【解釈】 ブルートフォース攻撃が成功し、PROD-SRV-01 への侵入が完了した と判断できる。この時点が攻撃の「侵入成功ライン」。 【次のアクション】 admin_root として実行されたプロセスを 10:03:06 以降で追う。 特に cmd.exe, powershell.exe, schtasks.exe の実行を確認する。 ノートを追加しているものに赤い点が付きます。 この章のまとめ 機能 使う場面 KQL(第3回) イベントを絞り込んで目で読む Correlation(EQL) イベントの順序パターンを自動検出する ES|QL 集計・ランキング・異常値の発見 Case 調査内容をチームで共有・記録する Notes 調査の思考プロセスを時系列に紐づける 第4回チェックリスト [ ] EQLのsequenceクエリを実行し、 192.168.1.100 のブルートフォースシーケンスが検出されている [ ] ES|QLでIPごとのログイン失敗件数を集計し、 45.33.21.11 (8件)と 192.168.1.100 (4件)が確認できている [ ] 調査内容をCaseに登録し、タイトル・説明・次のアクションが入力されている [ ] 10:03:06 の成功イベントにNotesを追加し、事実・解釈・次のアクションが記録されている 次回は: ルールを「作る」だけで終わらせない最終回です。Alert suppressionとExceptionsを正しく使い分けてノイズを減らし、ルールタイプ(Custom query / Threshold / ES|QL)を目的に応じて使い分ける方法を学びます。 The post Elastic Securityで始める検知エンジニアリング — EQLとES|QLで攻撃を自動検出・集計する(第4回) first appeared on Elastic Portal .
サイオステクノロジー株式会社 Saman 2026年3月、ソフトウェアサプライチェーンを狙った攻撃が相次ぎました。 信頼されているライブラリやツールそのものが侵害され、開発者が普通に使うだけでリスクにさらされる状況が現実のものとなりました。 その中で注目されたのが、JavaScriptライブラリ「Axios」の侵害と、それを早い段階で捉えたElasticのPoCツールです。 目次 2026年3月:相次いだサプライチェーン攻撃 Axiosとは何か 今回の攻撃で何が起きたのか plain-crypto-jsとは インストール時に起きること なぜ気づきにくかったのか ElasticのPoC:supply-chain-monitor ツールの構成とAIの役割 仕組み 実証できたから、オープンソースにした なぜAIが必要なのか Elasticの方向性 まとめ 2026年3月:相次いだサプライチェーン攻撃 2026年3月には、複数のサプライチェーン攻撃が確認されています。 Trivy侵害 セキュリティスキャナが侵害され、CI/CD関連の認証情報が流出 LiteLLM侵害 流出した認証情報を利用し、悪意あるパッケージが公開 Telnyx Python SDK侵害 同様の流れで公式SDKが汚染 Axios侵害 npm上で公開されたパッケージに悪意ある依存が追加 これらは同じ月に発生した一連の事象ですが、 すべてが単一の攻撃者によるものではなく、複数の活動が重なっていたと考えられています。 Axiosとは何か Axiosは、WebアプリケーションでAPI通信を行うためのJavaScriptライブラリです。 多くのプロジェクトで使われており、週1億回くらいダウンロードされることもある、非常に広く利用されているパッケージです。 今回の攻撃で何が起きたのか 今回の攻撃では、AxiosのGitHub上の通常の開発コードではなく、npmで公開されたパッケージに対して変更が加えられました。 具体的には、以下のような構造です。 axios └── plain-crypto-js(悪意ある依存パッケージ) plain-crypto-jsとは plain-crypto-jsは、実在する暗号ライブラリ「crypto-js」に似せた名前のパッケージです。 見た目は自然(crypto系ライブラリに見える) しかし中身はマルウェア このように、既存ライブラリに似た名前を使うことで、開発者に違和感を持たせないようにする手口が使われていました。 インストール時に起きること 開発者は通常どおり以下を実行します。 npm install axios しかし、悪意あるバージョン(例:1.14.1 / 0.30.4)を取得した場合、裏では次のような処理が行われます。 Axiosがインストールされる plain-crypto-jsが依存としてインストールされる postinstallスクリプトが自動実行される マルウェア(RAT)が起動する この悪意あるバージョンは短時間(数時間程度)公開されており、その間に取得した場合に影響を受ける可能性がありました。 なぜ気づきにくかったのか 今回のポイントは、「違和感の小ささ」です。 crypto系の自然な名前 依存関係は自動でインストールされる パッケージの差分は通常見ない さらに、GitHub上の通常の開発フローではなく、公開パッケージ側に変更が加えられた点も検知を難しくしていました。 ElasticのPoC:supply-chain-monitor この攻撃を捉えたのが、Elastic Security LabsのJoe Desimone氏が開発した supply-chain-monitor  というPoCツールです。 ツールの構成とAIの役割 Joeが作った  supply-chain-monitor  の考え方は「差分をAIに読ませる」に尽きます。パッケージ更新が出た瞬間に旧バージョンとの差分を取り、LLMに「これは悪意ある変更か?」と問うだけです。 仕組み PyPIやnpmの更新フィードを定期的に取得し、新しいバージョンの公開を検知する あらかじめ定義したwatchlist(ダウンロード数上位パッケージ)に含まれるかを確認する 対象パッケージの場合、レジストリから「旧バージョン」と「新バージョン」を直接ダウンロードする npm install  や  pip install  は使用せず、コードを実行しない形で安全に取得する 2つのバージョン間の差分(diff)を生成する 差分をMarkdown形式に整形する 整形された差分をLLMに入力として渡すLLMは以下の観点で分析する この変更は開発として自然か 追加されたコードや依存関係に意味があるか 不要・不自然な変更が含まれていないか 分析結果として「malicious / benign」などの判定(verdict)を生成する maliciousと判断された場合、Slackなどにアラートを送信する アナリストはアラート内容(差分+AIの説明)をもとに追加調査を行う このアプローチの重要なポイントは、 コードを実行せずに、 使われる前の段階で異常を検知できることです。 従来のアプローチ AIを使ったアプローチ – IOC(IP・ドメイン)を照合 – シグネチャによるマッチング – 過去の攻撃パターンに対応 -「何があるか」を見る – コードの変化を読む – 変更の意図を分析する – 未知の攻撃にも対応できる -「何が変わったか」の意味を見る Axiosの検知でAIが見抜いたのは次の点です: plain-crypto-js  は依存として追加されているのに、コード内で使われていない。人はcryptoっぽい名前だから関係あるかもと見過ごします。AIは 使われていない依存の追加=説明できない変更=怪しい と判断しました。 実証できたから、オープンソースにした このツールはAxiosの侵害を、非常に早い段階でアラートとして検知しました。実際に機能することが証明されたことで、Elasticはこのツールをオープンソースとしてコミュニティに公開することを決定しました。 Joe氏はテスト中に明確なフォールスポジティブを経験しなかったと述べていますが、本人もサンプル数の少なさによる過学習の可能性に触れており、PoCとしての位置づけです。 この取り組みを共有する理由はコミュニティ全体で学ぶことが最も重要だと考えているからです。もしこのアイデアをもとに、より良いものを作る人がいれば素晴らしいことですし、パッケージレジストリ側がこの仕組みを取り入れることができれば、さらに良いことです。そして、この考え方によって次に誰かが被害を防げるのであれば、それだけで十分に価値があります。 Joe Desimone MITライセンスで公開。誰でも使え、誰でも改善に貢献できます。 github.com/elastic/supply-chain-monitor なぜAIが必要なのか パッケージ更新は毎日大量に発生します。 人間がすべての差分を確認することは現実的ではありません。 AIは、 差分を読み続ける 文脈を理解する 異常を説明できる ことで、従来では対応できなかった領域をカバーします。 Elasticの方向性 Elasticでは、AIを活用したセキュリティの進化が、すでにさまざまな形で進んでいます。 例えば、Attack Discovery、Workflows、Agent Builderといった機能を組み合わせることで、APTレベルの高度な攻撃を自動で検知し、その妥当性まで確認する仕組みが実現されています。 これは単なる自動化ではなく、 調査・判断・対応の一連の流れを支援する「エージェント型セキュリティ」 です。 日々増え続けるアラートや攻撃に対して、SOCが疲弊するのではなく、より効率的かつ的確に対応できる。 Elasticは、AIを中核に据えることで、セキュリティの「効率」と「精度」の両方を引き上げています。 ※  APTレベル = 国や大企業レベルの“高度でしつこい攻撃” まとめ 今回のAxiosの事例が示したのは、信頼そのものが攻撃対象になる時代です。 そして、それに対抗するためには「変化を理解する力」が必要になります。 ElasticのPoCツールが示したのは、その新しい方向性です。 セキュリティは今、「見る」から「理解する」へと進み始めています。 参考元: How we caught the Axios supply chain attack — Elastic Security Labs Joe Desimone shares the story of how he caught the Axios supply chain attack with a proof of concept tool built in an af... www.elastic.co GitHub - elastic/supply-chain-monitor Contribute to elastic/supply-chain-monitor development by creating an account on GitHub. github.com The post AIで変化の意味を読む:Elasticの新検知ツール(PoC)がAxios攻撃を捉えた方法 first appeared on Elastic Portal .