O que Automação SSH com Netmiko faz?
Use esta skill ao escrever ou revisar automação Python que se conecta a dispositivos de rede com Netmiko. Mantenha o caminho padrão somente leitura; alterações de configuração exigem uma janela de mudança separada, revisão por pares e plano de rollback.
Quando Usar
- Coletando saída de comandos
showem roteadores, switches ou firewalls. - Construindo um pequeno script de auditoria para evidências de interface, roteamento ou configuração.
- Adicionando timeouts e tratamento de exceções a scripts SSH de rede.
- Parseando saída de comandos com TextFSM quando um template existe.
- Revisando automação antes de tocar em dispositivos de produção.
Padrões de Segurança
- Comece com coleta somente leitura usando
send_command(). - Mantenha o inventário pequeno e explícito; não varra faixas de endereços inteiras.
- Use variáveis de ambiente, um cofre ou
getpass; nunca codifique credenciais. - Defina timeouts de conexão e leitura.
- Limite a concorrência para que dispositivos mais antigos não sejam sobrecarregados.
- Exija uma flag explícita de operador antes de
send_config_set(). - Não chame
save_config()até que a alteração tenha sido verificada e aprovada.
Padrão de Conexão Somente Leitura
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("Usuário: "),
"password": os.environ.get("NETMIKO_PASSWORD") or getpass("Senha: "),
"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("Falha na autenticação")
except NetmikoTimeoutException:
print("Tempo limite da conexão SSH excedido")
except ReadTimeout:
print("Tempo de leitura do comando excedido")
Use endereços placeholder de faixas de documentação nos exemplos. Mantenha o inventário real em um arquivo local ignorado ou em um sistema gerenciado por segredos.
Coleta em Lote
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())
Mantenha max_workers baixo, a menos que o parque de dispositivos e os
sistemas AAA sejam conhecidos por suportar um volume maior de conexões.
Parsing Estruturado
O Netmiko pode solicitar que TextFSM, TTP ou Genie analisem a saída de comandos suportados. Trate a saída do parser como uma otimização, não o único caminho de evidência.
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("Nenhum template de parser correspondeu; armazene a saída bruta para revisão")
else:
for row in parsed:
print(row)
Se o parsing orientar uma decisão crítica, mantenha a saída bruta do comando junto com o resultado analisado para que um operador possa inspecionar divergências.
Padrão de Configuração Protegida
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("Apenas simulação. Comandos candidatos:")
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("Verifique o comportamento antes de salvar a configuração inicial.")
Salvar a configuração é uma etapa de aprovação separada. Em produção, inclua um trecho de rollback e capture evidências de antes/depois no registro de alteração.
Checklist de Revisão
- O script identifica uma fonte de inventário explícita?
- As credenciais estão ausentes do código-fonte, logs e mensagens de exceção?
conn_timeout,auth_timeouteread_timeoutdo comando estão definidos?- As falhas são relatadas por dispositivo sem interromper todo o lote?
- O script evita varreduras amplas e concorrência ilimitada?
- As alterações de configuração estão atrás de uma simulação ou flag explícita de operador?
save_config()está separado do push inicial e vinculado à verificação?
Anti-Padrões
- Codificar senhas, enable secrets ou chaves privadas no código-fonte.
- Enviar comandos de configuração como o caminho de código padrão.
- Executar automação contra uma faixa CIDR em vez de um inventário revisado.
- Registrar configurações completas em execução em sistemas compartilhados sem sanitização.
- Tratar o sucesso do parser como prova de que o estado do dispositivo está correto.
Veja Também
- Skill:
cisco-ios-patterns - Skill:
network-config-validation - Skill:
network-interface-health