0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

本稿に記載した内容は筆者個人の見解であり、所属組織の公式見解ではありません。

概要

Node.js で Model Context Protocol (MCP) のサーバーを実装し、PAN-OS / Panorama の XML API を叩くツールを提供します。
実装されているツールは次の2つです。

  • test_connectionshow system info を呼び出して装置情報を返す疎通確認
  • get_firewall_logsジョブ方式で各種ログ(traffic / threat / url / system など)を取得

MCP クライアント(例:ChatGPT / Gemini CLI など)からPAN-OSに接続して利用できます。


目次


アーキテクチャ

  • MCP サーバーindex.ts

    • ツールの登録(疎通確認/ログ取得)
    • StdioServerTransport で MCP クライアントと標準入出力で通信
  • PAN-OS XML API クライアントpanapi.ts

    • fetch(Undici)で /api/application/x-www-form-urlencodedPOST
    • X-PAN-KEY ヘッダによる認証(必要に応じて key= クエリに切替可)
    • ログ取得は ジョブ投入→ポーリング→結果取得

動作の流れ(シーケンス)


環境変数と挙動切り替え

必須:

  • PA_FIREWALL_URL … 例: https://pa-or-panorama.example.com
  • PA_API_KEY … PAN-OS で生成した API Key

任意(挙動切替):

  • PA_INSECURE_TLS=true
    TLS 検証を無効化(検証用途のみ/本番非推奨)
  • PA_REQUIRE_KEY_IN_QUERY=true
    → ヘッダ X-PAN-KEY ではなく クエリ ?key= で認証
  • PA_LOG_JOB_TIMEOUT_MS(既定: 20000ms)
  • PA_LOG_JOB_POLL_MS(既定: 800ms)

.env 例:

.env
PA_FIREWALL_URL=https://<firewall-or-panorama-hostname>
PA_API_KEY=<api-key>
# オプション
# PA_INSECURE_TLS=true
# PA_REQUIRE_KEY_IN_QUERY=true
# PA_LOG_JOB_TIMEOUT_MS=30000
# PA_LOG_JOB_POLL_MS=500

サーバー側(index.ts)の役割

  • ツール登録:

    • test_connectionPanOSClient.getSystemInfo() を呼び出し、結果を JSON文字列として返却
    • get_firewall_logs … 入力スキーマ(Zod)で logType / query / nlogs / skip / dir / timeoutMs / pollMs を受け取り、PanOSClient.getLogsXML() を実行。{ count, entries }JSON文字列で返却
  • 接続開始: StdioServerTransport で MCP クライアントと接続


API クライアント側(panapi.ts)の役割

  • URL 正規化/api/api/ の差異を吸収(常に末尾 / にそろえる)
  • 認証:既定は X-PAN-KEYPA_REQUIRE_KEY_IN_QUERY=true なら ?key= へ切替
  • XML パースfast-xml-parser を利用(属性も保持)
  • TLSundici.AgentrejectUnauthorized を制御(PA_INSECURE_TLS

getSystemInfo()

type=op & cmd=<show><system><info/></system></show> を POST → XML をパースして response.result を返す。

getLogsXML(logType, opts)

  1. ジョブ投入type=log, log-type=<type>, [query, nlogs, skip, dir]

    • 通常は response.result.jobjob-id
    • 例外的に <msg><line>…jobid 1234…</line></msg> の文字列から抽出するケースもケア
    • 稀にインラインで logs が返ることがあり、その場合はそのまま entries を返す
  2. ポーリングaction=get, job-id=<id>

    • タイムアウト/ポーリング間隔は環境変数または引数で調整可
  3. 完了判定

    • response.result.log.logs.entry を配列に正規化して返却

ツールごとの入出力仕様

1) test_connection

  • 入力: なし
  • 出力(例・整形済みJSON文字列)
{
  "system": {
    "hostname": "PA-VM",
    "serial": "0123456789",
    "sw-version": "11.0.2",
    "model": "PA-VM",
    "...": "..."
  }
}

2) get_firewall_logs

  • 入力(主な項目)

    • logType"traffic" | "threat" | "url" | "system" | "config" | "hipmatch" | "globalprotect" | "wildfire" | "data" | "corr" | "corr-detail" | "corr-categ" | "userid" | "auth" | "gtp" | "external" | "iptag" | "decryption"
    • query … Monitor > Logs と同じ検索式
    • nlogs … 1〜5000(既定 20)
    • skip … ページング用スキップ件数
    • dir"backward"(新しい順:既定) or "forward"
    • timeoutMs / pollMs … ジョブ待ちの調整

実行方法と動作確認

1) 依存のインストール

package.jsonに従い、関連のパッケージをインストールします。

command
npm i
package.json
{
  "name": "pafirewall-mcp",
  "version": "0.1.0",
  "type": "module",
  "description": "MCP Tools server to query Palo Alto Networks PAN-OS logs via XML API.",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc -p .",
    "start": "node dist/index.js",
    "dev": "node --loader ts-node/esm src/index.ts"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.2.0",
    "dotenv": "^16.4.5",
    "fast-xml-parser": "^4.4.1",
    "undici": "^7.15.0",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "ts-node": "^10.9.2",
    "typescript": "^5.5.4"
  }
}

2) 環境変数の設定

PA_FIREWALL_URL=https://<firewall-or-panorama-hostname>
PA_API_KEY=<api-key>
# オプション
# PA_INSECURE_TLS=true
# PA_REQUIRE_KEY_IN_QUERY=true
# PA_LOG_JOB_TIMEOUT_MS=30000
# PA_LOG_JOB_POLL_MS=500

3) ビルド & 起動(例)

npm run build

4) MCP クライアントから呼び出し

  • test_connection を実行 → show system info の結果が JSON 文字列で返る
  • get_firewall_logs を実行 → 条件に合致するログが {count, entries} 形式で返る

よくあるハマりどころ

  • /api/api/ の差異
    → 本実装は常に末尾 / にそろえて POST(リダイレクトや解釈違いの回避)
  • ヘッダ認証が通らない
    PA_REQUIRE_KEY_IN_QUERY=true?key= に切替(古い機種/プロキシ越し対策)
  • 自己署名証明書で TLS 失敗
    → 検証用途なら PA_INSECURE_TLS=true、本番は信頼済み CA を正しく配布
  • ログ量が多くてタイムアウト
    query で期間/条件を絞る、nlogs を抑える、timeoutMs を増やす、ページング(skip)を使う

セキュリティ/運用の注意点

  • API Key の取り扱い:環境変数/Secret 管理。ログや標準出力に生値を出さない
  • TLS 検証PA_INSECURE_TLS は検証専用。運用では正しい証明書チェーンを構築することが推奨。
  • 最小権限:ログ閲覧(APIコール)に必要な最小ロールを付与。
  • 負荷対策:広い期間や大きな nlogs は避け、必要に応じてページング。夜間バッチなどともバッティングしないように。

免責事項
本記事に掲載する情報・ソースコード・スクリプト・設定例は現状有姿(AS IS)で提供します。正確性・完全性・最新性・動作を保証しません。ご利用は自己責任で行ってください。
本記事の利用により生じたいかなる損害・不利益・トラブルについても、法令で認められる範囲内で、筆者および筆者の所属組織は一切の責任を負いません。
本番適用前には必ず十分な検証を行ってください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?