Netmiko SSH 自動化
このスキルは、Netmiko を使用してネットワーク機器に接続する Python 自動化コードを記述またはレビューする際に使用します。デフォルトのパスは読み取り専用に保ちます。設定変更には、別途変更ウィンドウ、ピアレビュー、ロールバック計画が必要です。
使用するタイミング
- ルーター、スイッチ、ファイアウォールから
showコマンド出力を収集する場合。 - インターフェース、ルーティング、設定のエビデンスを取得するための小規模な監査スクリプトを構築する場合。
- ネットワーク SSH スクリプトにタイムアウトと例外処理を追加する場合。
- TextFSM テンプレートが存在する場合に、コマンド出力をパースする場合。
- 本番デバイスに影響を与える前に自動化コードをレビューする場合。
安全上のデフォルト
- 最初は読み取り専用の
send_command()収集から始めます。 - インベントリは小さく、明示的に指定します。アドレス範囲全体をスキャンしないでください。
- 環境変数、ボールト、または
getpassを使用します。認証情報をハードコードしないでください。 - 接続タイムアウトと読み取りタイムアウトを設定します。
- 同時実行数を制限して、古いデバイスに過負荷がかからないようにします。
send_config_set()の前に明示的なオペレーターフラグを要求します。- 変更が確認および承認されるまで
save_config()を呼び出さないでください。
読み取り専用接続パターン
import os
from getpass import getpass
from netmiko import ConnectHandler
from netmiko.exceptions import (
NetmikoAuthenticationException,
NetmikoTimeoutException,
ReadTimeout,
)
device = {
"device_type": "cisco_ios",
"host": "192.0.2.10",
"username": os.environ.get("NETMIKO_USERNAME") or input("ユーザー名: "),
"password": os.environ.get("NETMIKO_PASSWORD") or getpass("パスワード: "),
"secret": os.environ.get("NETMIKO_ENABLE_SECRET"),
"conn_timeout": 10,
"auth_timeout": 20,
"banner_timeout": 15,
"read_timeout_override": 30,
}
try:
with ConnectHandler(**device) as conn:
if device.get("secret") and not conn.check_enable_mode():
conn.enable()
output = conn.send_command("show ip interface brief", read_timeout=30)
print(output)
except NetmikoAuthenticationException:
print("認証に失敗しました")
except NetmikoTimeoutException:
print("SSH接続がタイムアウトしました")
except ReadTimeout:
print("コマンド読み取りがタイムアウトしました")
例ではドキュメント用のアドレス範囲からプレースホルダーを使用してください。実際のインベントリは、無視リストに含まれるローカルファイルまたはシークレット管理システムに保存してください。
バッチ収集
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any
def collect_show(device: dict[str, Any], command: str) -> dict[str, Any]:
host = device["host"]
try:
with ConnectHandler(**device) as conn:
output = conn.send_command(command, read_timeout=45)
return {"host": host, "ok": True, "output": output}
except (NetmikoAuthenticationException, NetmikoTimeoutException, ReadTimeout) as exc:
return {"host": host, "ok": False, "error": type(exc).__name__}
results = []
with ThreadPoolExecutor(max_workers=8) as pool:
futures = [pool.submit(collect_show, device, "show version") for device in devices]
for future in as_completed(futures):
results.append(future.result())
デバイスの環境とAAAシステムが高い接続ボリュームを処理できることが確認されていない限り、max_workers は低く保ってください。
構造化パーシング
Netmiko は、サポートされているコマンド出力をパースするために TextFSM、TTP、または Genie に要求できます。パーサーの出力は最適化として扱い、唯一のエビデンス経路としては扱わないでください。
with ConnectHandler(**device) as conn:
parsed = conn.send_command(
"show ip interface brief",
use_textfsm=True,
raise_parsing_error=False,
read_timeout=30,
)
if isinstance(parsed, str):
print("パーサーテンプレートが一致しませんでした。レビューのために生の出力を保存してください")
else:
for row in parsed:
print(row)
パーシングがブロッキング判断を左右する場合は、パース結果と一緒に生のコマンド出力も保存しておくと、オペレーターが不一致を検査できます。
ガード付き設定パターン
import os
commands = [
"interface GigabitEthernet0/1",
"description CHANGE-1234 UPLINK-TO-CORE",
]
apply_changes = os.environ.get("APPLY_NETWORK_CHANGES") == "1"
if not apply_changes:
print("ドライランのみ。候補コマンド:")
print("\n".join(commands))
else:
with ConnectHandler(**device) as conn:
conn.enable()
before = conn.send_command("show running-config interface GigabitEthernet0/1")
output = conn.send_config_set(commands)
after = conn.send_command("show running-config interface GigabitEthernet0/1")
print(before)
print(output)
print(after)
print("スタートアップコンフィグを保存する前に動作を確認してください。")
コンフィグの保存は別の承認ステップです。本番環境では、ロールバックスニペットを含め、変更記録に変更前後のエビデンスを取得してください。
レビューチェックリスト
- スクリプトは明示的なインベントリソースを特定していますか?
- 認証情報はソース、ログ、例外メッセージから除外されていますか?
conn_timeout、auth_timeout、コマンドread_timeoutは設定されていますか?- 失敗はバッチ全体を停止することなく、デバイスごとに報告されていますか?
- スクリプトは広範なスキャンや無制限の同時実行を避けていますか?
- 設定変更はドライランまたは明示的なオペレーターフラグの背後にありますか?
save_config()は初期プッシュとは別で、検証と結びついていますか?
アンチパターン
- パスワード、enable シークレット、または秘密鍵をソースにハードコーディングすること。
- 設定変更コマンドをデフォルトのコードパスとして送信すること。
- レビュー済みのインベントリではなく、CIDR 範囲に対して自動化を実行すること。
- サニタイズなしで完全な running-config を共有システムにログ出力すること。
- パーサーの成功を、デバイスの状態が正しいことの証明として扱うこと。
関連情報
- スキル:
cisco-ios-patterns - スキル:
network-config-validation - スキル:
network-interface-health