本稿に記載した内容は筆者個人の見解であり、所属組織の公式見解ではありません。
概要
Node.js で Model Context Protocol (MCP) のサーバーを実装し、PAN-OS / Panorama の XML API を叩くツールを提供します。
実装されているツールは次の2つです。
-
test_connection…show system infoを呼び出して装置情報を返す疎通確認 -
get_firewall_logs… ジョブ方式で各種ログ(traffic / threat / url / system など)を取得
MCP クライアント(例:ChatGPT / Gemini CLI など)からPAN-OSに接続して利用できます。
目次
- アーキテクチャ
- 動作の流れ(シーケンス)
- 環境変数と挙動切り替え
- サーバー側(index.ts)の役割
- API クライアント側(panapi.ts)の役割
- ツールごとの入出力仕様
- 実行方法と動作確認
- よくあるハマりどころ
- セキュリティ/運用の注意点
アーキテクチャ
-
MCP サーバー(
index.ts)- ツールの登録(疎通確認/ログ取得)
-
StdioServerTransportで MCP クライアントと標準入出力で通信
-
PAN-OS XML API クライアント(
panapi.ts)-
fetch(Undici)で/api/にapplication/x-www-form-urlencodedの POST -
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 例:
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_connection…PanOSClient.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-KEY、PA_REQUIRE_KEY_IN_QUERY=trueなら?key=へ切替 -
XML パース:
fast-xml-parserを利用(属性も保持) -
TLS:
undici.AgentでrejectUnauthorizedを制御(PA_INSECURE_TLS)
getSystemInfo()
type=op & cmd=<show><system><info/></system></show> を POST → XML をパースして response.result を返す。
getLogsXML(logType, opts)
-
ジョブ投入(
type=log, log-type=<type>, [query, nlogs, skip, dir])- 通常は
response.result.jobに job-id - 例外的に
<msg><line>…jobid 1234…</line></msg>の文字列から抽出するケースもケア - 稀にインラインで logs が返ることがあり、その場合はそのまま entries を返す
- 通常は
-
ポーリング(
action=get, job-id=<id>)- タイムアウト/ポーリング間隔は環境変数または引数で調整可
-
完了判定
-
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に従い、関連のパッケージをインストールします。
npm i
{
"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)で提供します。正確性・完全性・最新性・動作を保証しません。ご利用は自己責任で行ってください。
本記事の利用により生じたいかなる損害・不利益・トラブルについても、法令で認められる範囲内で、筆者および筆者の所属組織は一切の責任を負いません。
本番適用前には必ず十分な検証を行ってください。