Netmiko SSH Automation
이 스킬은 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("Username: "),
"password": os.environ.get("NETMIKO_PASSWORD") or getpass("Password: "),
"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("명령 읽기 시간 초과")
예제에서는 문서화된 테스트 범위의 플레이스홀더 주소를 사용하세요. 실제 인벤토리는 .gitignore에 추가된 로컬 파일이나 시크릿 관리 시스템에 보관하세요.
배치 수집
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())
max_workers는 장치 환경과 AAA 시스템이 더 높은 연결 볼륨을 처리할 수 있다는 것이 확인되지 않았다면 낮게 유지하세요.
구조화된 파싱
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 범위에 대해 자동화 실행.
- 전체 실행 구성을 삭제하지 않고 공유 시스템에 로깅.
- 파서 성공을 장치 상태가 올바르다는 증거로 취급.
참고
- 스킬:
cisco-ios-patterns - 스킬:
network-config-validation - 스킬:
network-interface-health