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 como somente leitura; alterações de configuração exigem uma janela de mudança separada, revisão por pares e plano de rollback.
Quando Usar
- Coletar saída de comandos
showem roteadores, switches ou firewalls. - Construir um pequeno script de auditoria para obter evidências de interface, roteamento ou configuração.
- Adicionar timeouts e tratamento de exceções a scripts SSH de rede.
- Analisar saída de comandos com TextFSM quando um modelo existir.
- Revisar automação antes que ela toque 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 inteiras de endereços.
- Use variáveis de ambiente, um cofre ou
getpass; nunca hardcode 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 mudança 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,
)
dispositivo = {
"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(**dispositivo) as conn:
if dispositivo.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("Conexão SSH expirou")
except ReadTimeout:
print("Leitura do comando expirou")
Use endereços de placeholder das faixas de documentação nos exemplos. Mantenha o inventário real em um arquivo local ignorado ou em um sistema gerenciado de segredos.
Coleta em Lote
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any
def coletar_show(dispositivo: dict[str, Any], comando: str) -> dict[str, Any]:
host = dispositivo["host"]
try:
with ConnectHandler(**dispositivo) as conn:
output = conn.send_command(comando, 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__}
resultados = []
with ThreadPoolExecutor(max_workers=8) as pool:
futures = [pool.submit(coletar_show, dispositivo, "show version") for dispositivo in dispositivos]
for future in as_completed(futures):
resultados.append(future.result())
Mantenha max_workers baixo, a menos que o parque de dispositivos e os sistemas AAA sejam
conhecidos por suportar maior volume 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 como o único caminho de evidência.
with ConnectHandler(**dispositivo) 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 modelo de parser correspondente; armazene a saída bruta para revisão")
else:
for linha in parsed:
print(linha)
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 discrepâncias.
Padrão de Configuração Protegida
import os
comandos = [
"interface GigabitEthernet0/1",
"description CHANGE-1234 UPLINK-TO-CORE",
]
aplicar_mudancas = os.environ.get("APPLY_NETWORK_CHANGES") == "1"
if not aplicar_mudancas:
print("Apenas simulação. Comandos candidatos:")
print("\n".join(comandos))
else:
with ConnectHandler(**dispositivo) as conn:
conn.enable()
antes = conn.send_command("show running-config interface GigabitEthernet0/1")
output = conn.send_config_set(comandos)
depois = conn.send_command("show running-config interface GigabitEthernet0/1")
print(antes)
print(output)
print(depois)
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 da mudança.
Lista de Verificação 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 flag de simulação ou flag explícita de operador?
save_config()está separado do envio inicial e vinculado à verificação?
Anti-Padrões
- Hardcodar 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