Meraki API と Aruba New Central API を使って、ファームウェア更新を“能動的に検知”する仕組み
🧭 はじめに
この記事では、Meraki や Aruba といったネットワーク機器のファームウェア更新を自動で検知・通知・スケジュール させる仕組みを、Google Cloud(Cloud Functions+Scheduler)と Python で構築した話を紹介します。
ネットワーク機器の運用をしていると、「ファームウェア、ちゃんと最新だっけ?」と定期的に確認するの、結構面倒ですよね。
この仕組みで、その手間を自動化してしまいましょう。
🎯 やってほしいこと
ネットワーク機器のファームウェアアップデートを
「管理画面を見に行かなくても」能動的に検知し、可能なら自動でスケジュールまで設定したい ですよね。
この記事で実現するのは、以下の通りです:
- Meraki/Aruba 機器の 現行バージョン (currentVersion) と 推奨版との差分 を検知
- 「新しい推奨版が出たよ(上流更新)」や「推奨版と違うよ(不一致)」を Slack に通知
- Meraki は API 経由で 更新スケジュールを自動設定
- Aruba は検知のみ(APIが自動スケジュールに未対応のため)
🧩 背景と前提
なぜこの仕組みが必要なのか、Meraki と Aruba の「思想」の違いから見ていきます。
Meraki のファームウェア思想
Meraki はちょっと特殊で、各ファームウェアに 「End of Firmware Maintenance(EFM)」 が設定されています。
EFM(保守終了日)が来る前に最新版へ更新することが推奨されており、“基本、常に最新版を使ってね” という運用思想がベースにあります。
この思想に対応するため、Meraki 運用では「EFM期限を迎える前に、計画的に自動更新」できるのが理想です。
APIによる自動検知・スケジュール設定は、まさにそのための仕組みというわけです。
📘 Meraki公式ドキュメント
💡 注意点 (割り切り)
- Staged Upgrade(段階的アップグレード)は、今回の仕組みでは考慮外としています。
- Meraki は一度 API でアップグレード予約を設定すると、GUI/API からキャンセルできないケース があります(仕様です…)。
- そのため本設計では、「スケジュール設定したら、あとは実行を待つ。問題があれば実行後にロールバックで対処する」という割り切りにしています。
Aruba API について
Aruba Central API は、今ちょうど過渡期です。大きく2系統あります。
| 系列 | Python SDK | 概要 |
|---|---|---|
| v1系 |
pycentral 1.x |
旧API。レスポンス形式が古く、段階的に廃止(Deprecated)予定。 |
| v2系 |
pycentral 2.0ax(アルファ版) |
「New Central API」。構造が整理され、今後はこちらが主流に。 |
今回は、将来性を見越して v2 (α版) を利用します。
firmware-details と device-inventory というエンドポイントから
推奨版 (recommendedVersion) と現行版 (softwareVersion) の差分を取得します。
残念ながら、v2 (α版) 時点ではスケジュール設定 API がまだ提供されていないため、「通知のみ」で対応します。
Meraki と Aruba の設計ポリシー差
まとめると、両者のポリシーにはこんな違いがあります。
| 項目 | Meraki | Aruba |
|---|---|---|
| ファームウェア思想 | 最新安定版への追従(EFMで更新推奨) | 推奨版提示型(ベンダーが「これがオススメ」と提示) |
| APIによるスケジュール設定 | ⭕ PUT /networks/{id}/firmwareUpgrades
|
❌ 未対応(v2 α版時点。今後に期待!) |
| 自動スケジュール戦略 | 検知後、ネットワーク・製品単位で設定(例: MX=土曜2時, MS/CS=土曜4時) | 検知のみ |
| キャンセル操作 | ほぼ不可(割り切りが必要) | N/A |
🏗️ システム構成
GCP 上に、サーバレスでシンプルな構成を組みます。
GCP上のアーキテクチャ
- Cloud Scheduler が毎日決まった時間に Cloud Functions を(OIDC認証で)叩きます。
- Cloud Functions (Python) が起動し、Meraki と Aruba の API からファームウェア情報を取得します。
-
Cloud Storage (GCS) に保存されている
state.json(=前回実行時の情報)と今回取得した情報を比較します。 - 差分(新しい推奨版、現行版との不一致など)があれば、Slack に通知します。
- Meraki で更新があれば、そのまま API で更新スケジュールも設定します。
- 最後に、今回の状態を
state.jsonとして GCS に上書き保存します。
⚙️ 環境構築
requirements.txt
google-cloud-storage
google-cloud-logging
meraki
pycentral>=2.0a6
requests
環境変数設定( .env.yaml またはデプロイ時)
# 事前に GCS バケットを作成しておく
export PROJECT_ID="your-gcp-project-id"
export REGION="asia-northeast1"
export FUNC_NAME="network-firmware-monitor"
export GCS_BUCKET_NAME="network-firmware-monitor" # 作成したバケット名
export SERVICE_ACCOUNT_EMAIL="scheduler-invoker@${PROJECT_ID}.iam.gserviceaccount.com" # Schedulerが使うSA
# 実行時に Cloud Functions に設定する環境変数
# (Secret Manager の利用を強く推奨します)
export MERAKI_API_KEY="xxx"
export ARUBA_API_KEY="xxx"
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/xxxx"
🚀 デプロイ手順 (gcloud CLI)
Cloud Functions は 非公開(認証必須) でデプロイし、Cloud Scheduler からの OIDC 認証済みリクエストのみを受け付けるようにします。
# 1. Cloud Functions を非公開でデプロイ
# (APIキーなどは --set-env-vars ではなく Secret Manager を使うのがベストプラクティスです)
gcloud functions deploy $FUNC_NAME \
--project=$PROJECT_ID \
--region=$REGION \
--runtime=python313 \
--trigger-http \
--no-allow-unauthenticated \
--entry-point=main \
--set-env-vars GCS_BUCKET_NAME=$GCS_BUCKET_NAME,SLACK_WEBHOOK_URL=$SLACK_WEBHOOK_URL,MERAKI_API_KEY=$MERAKI_API_KEY,ARUBA_API_KEY=$ARUBA_API_KEY
# 2. Cloud Scheduler のサービスアカウントに Functions の起動権限を付与
gcloud functions add-iam-policy-binding $FUNC_NAME \
--region=$REGION \
--project=$PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
--role="roles/cloudfunctions.invoker"
# 3. Cloud Functions のトリガーURLを取得
FUNCTION_URL=$(gcloud functions describe $FUNC_NAME --region=$REGION --project=$PROJECT_ID --format='value(httpsTrigger.url)')
# 4. Cloud Scheduler を設定(毎朝9時実行)
gcloud scheduler jobs create http firmware-monitor-job \
--schedule="0 9 * * *" \
--uri="${FUNCTION_URL}" \
--oidc-service-account-email="${SERVICE_ACCOUNT_EMAIL}" \
--http-method=POST \
--project=$PROJECT_ID
※ Cloud Scheduler のデフォルトSA (
scheduler-invoker@...) がない場合は、事前にgcloud services enable cloudscheduler.googleapis.comを実行するか、専用のSAを作成してください。
🧪 Meraki ファームウェアスケジュール確認(CLI)
「ちゃんとスケジュール設定されたかな?」と不安なときは、CLI (curl + jq) で確認できます。
# Meraki APIキー
export MERAKI_KEY="xxxx"
# 確認したい Meraki Network ID のリスト
NIDS=("L_123456789012345" "L_234567890123456")
for NID in "${NIDS[@]}"; do
echo "# Network: ${NID}"
curl -sS -X GET "[https://api.meraki.com/api/v1/networks/$](https://api.meraki.com/api/v1/networks/$){NID}/firmwareUpgrades" \
-H "Accept: application/json" \
-H "X-Cisco-Meraki-API-Key: ${MERAKI_KEY}" \
| jq -r '
.products
| to_entries[]
| select(.value.nextUpgrade.time != null)
| [.key, .value.nextUpgrade.time, .value.nextUpgrade.toVersion.shortName]
| @tsv' \
| awk -F'\t' 'BEGIN{print "family\tUTC_time\tversion"} {print}'
done
出力例
(設定されているものだけが family ごとに表示されます)
# Network: L_123456789012345
family UTC_time version
wireless 2025-11-02T07:29:00Z MR 32.1.4
family と機器のマッピング
| family | 実際の機器 |
|---|---|
| appliance | MX (セキュリティ/SD-WAN) |
| switch | MS (スイッチ) |
| switchCatalyst | CS (Catalyst スイッチ) |
| wireless | MR (アクセスポイント) |
| camera | MV (カメラ) |
| cellularGateway | MG (セルラールーター) |
| sensor | MT (センサー) |
💬 Slack通知テンプレート例
requests ライブラリを使って、シンプルに Slack Webhook に POST します。
import os
import requests
def post_slack(msg: str, color: str = "#2eb886"):
"""Slack に通知を送信する"""
webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
if not webhook_url:
print("Slack Webhook URL が設定されていません。")
return
payload = {
"attachments": [
{
"fallback": "Network Firmware Monitor",
"color": color, # 色を変えると通知の見栄えが変わる
"title": "📡 Network Firmware Monitor",
"text": msg,
"mrkdwn_in": ["text"] # メッセージ内で *bold* などが使えるように
}
]
}
try:
requests.post(webhook_url, json=payload)
except Exception as e:
print(f"Slack への通知に失敗しました: {e}")
通知例
✅ 更新スケジュール完了 (Meraki)
:bell: [Meraki] 新しい安定版がリリースされました
MR 32.1.4 → 次回メンテナンス枠 (2025-11-09T04:00:00Z) でスケジュール済み
⚠️ 不一致検知 (Meraki or Aruba)
:warning: [Aruba] 現行ファームウェアが推奨版と異なります
対象: グループA
現在: 10.10.1000 / 推奨: 10.11.0001
(※ Aruba は手動での更新対応が必要です)
🚫 手動対応(Meraki キャンセル不可)
:no_entry: [Meraki] ファームウェア予約キャンセルは不可です
Network: L_123456789012345
UIからロールバック or 次回メンテナンスをお待ちください
🧱 実装スケルトン(抜粋)
実際に API を叩く部分のイメージです。meraki と pycentral のライブラリがよしなにやってくれます。
from meraki import DashboardAPI
from pycentral.base import ArubaCentralBase
# === Meraki の処理イメージ ===
db = DashboardAPI(api_key=MERAKI_API_KEY, suppress_logging=True)
NETWORK_ID = "L_1234567890" # 対象のネットワークID
# ファームウェア情報を取得
fw_info = db.networks.getNetworkFirmwareUpgrades(NETWORK_ID)
# 現行バージョン
print(fw_info["products"]["wireless"]["currentVersion"]["shortName"])
# → MR 31.1.8
# 利用可能な(推奨)バージョン
# availableVersions はリストで、 "stable" が推奨版
stable_version = next(
(v for v in fw_info["products"]["wireless"]["availableVersions"] if v["releaseType"] == "stable"),
None
)
if stable_version:
print(stable_version["shortName"])
# → MR 32.1.4
# スケジュール設定 (例: 2025年11月9日 AM4時 JST)
# JST (UTC+9) の場合、UTC で 11月8日 19:00 を指定する
db.networks.updateNetworkFirmwareUpgrades(
NETWORK_ID,
products={"wireless": {"nextUpgrade": {"time": "2025-11-08T19:00:00Z"}}}
)
# === Aruba の処理イメージ ===
central = ArubaCentralBase(token=ARUBA_API_KEY) # トークン管理は SDK がやってくれる
# ファームウェア詳細を取得 (推奨版などが含まれる)
details = central.command("GET", "network-monitoring/v1alpha1/firmware-details")
print(details["recommendedVersion"])
# 実際の機器インベントリ (現行版が含まれる)
inventory = central.command("GET", "device-inventory/v1alpha1/devices")
for device in inventory.get("devices", []):
print(f"Device {device['serial']}: {device['softwareVersion']}")
🔭 今後の展開
今回は「まず動くもの」を作りましたが、まだ改善の余地はあります。
-
安定版自動追従ロジックの強化
- 「リリースから N 日間様子を見る」といったバッファ機能。
-
Meraki の Staged Upgrade(段階更新)対応
- 特定のタグが付いた機器から順次更新する、より高度な運用への対応。
-
GCS state.json の差分整合性チェック
-
stateが壊れたり、Functions が二重起動した(ないとは思うが)場合のエラーハンドリング。
-
-
Slack通知を Block Kit 対応に
- よりリッチでインタラクティブな通知(「今すぐ実行しますか?」ボタンとか)。
-
Aruba API のスケジュール設定対応
- Aruba API が進化してスケジュール設定が解放されたら、即対応する!
🧩 まとめ
- Meraki は「EFMによる最新版追従」が基本ポリシー。API での自動化と相性が良い。
- Aruba は「推奨版提示型」だが、スケジュール API は(現状)未対応。検知・通知までを自動化する。
- GCP(Cloud Functions + Scheduler)と Python (
meraki,pycentralライブラリ) を使えば、サーバレスで安価に “ネットワーク機器ファームウェアの自動検知・通知” の仕組みが実現できました。
日々の面倒な確認作業はクラウドと API に任せて、SRE/エンジニアはもっとクリエイティブな仕事に集中したいですね!
Discussion