Utilização do Módulo Paramiko para Autenticação SSH com Chaves Pública e Privada

Instalação do Módulo Paramiko

O módulo Paramiko fornece funcionalidade para conexão a servidores Linux, permitindo autenticação via usuário/senha ou por meio de chaves pública e privada. Após a autenticação, é possível executar comandos remotamente via código Python, com encapsulamento de operações comuns.

Como é um módulo de terceiros, deve ser instalado via pip:

pip3 install paramiko --index-url https://pypi.tuna.tsinghua.edu.cn/simple/

Conexão Básica com Usuário e Senha

Exemplo de uso com credenciais em texto plano, que pode ser inseguro se o código for exposto:

import paramiko

# Inicializar cliente SSH
cliente_ssh = paramiko.SSHClient()
# Permitir hosts não registrados no known_hosts
cliente_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Estabelecer conexão com o servidor
cliente_ssh.connect(hostname='192.168.1.10', port=22, username='admin', password='minha_senha')
# Executar comando remoto
entrada, saida, erro = cliente_ssh.exec_command('uptime')
# Obter resultado do comando
resultado = saida.read().decode('utf-8')
print(resultado)
# Encerrar conexão
cliente_ssh.close()

Esta abordagem utiliza uma estrutura similar a pipes, comparable ao módulo subprocess do Python.

Autenticação com Chaves Pública e Privada

Para evitar armazenar senhas no código, pode-se utilizar autenticação por chaves assimétricas, que é mais segura tanto para conexões SSH quanto para transferência de arquivos. O processo envolve gerar um par de chaves localmente e copiar a chave pública para o servidor.

Gerando Chaves em Ambiente Windows

No Windows, após instalar o Git, pode-se usar o Git Bash para gerar chaves com o comando:

ssh-keygen -t rsa

É rceomendado definir uma passphrase para proteger a chave privada. Em seguida, copiar a chave pública para o servidor:

ssh-copy-id -i /caminho/para/chave.pub usuario@ip_do_servidor

Após inserir a senha uma vez, conexões futuras usarão a chave privada automaticamente.

Conexão via Paramiko com Chaves

Para usar chaves no Paramiko, carregue a chave privada e conecte-se sem senha:

import paramiko

# Carregar chave privada de arquivo (supondo que não tenha passphrase)
chave_privada = paramiko.RSAKey.from_private_key_file(r'/home/usuario/.ssh/id_rsa')

# Configurar cliente SSH
conexao_ssh = paramiko.SSHClient()
conexao_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Conectar usando chave privada
conexao_ssh.connect(hostname='servidor.exemplo.com', port=22, username='admin', pkey=chave_privada)

# Executar comando
_, saida, _ = conexao_ssh.exec_command('df -h')
resultado_saida = saida.read().decode('utf-8')
print(resultado_saida)
conexao_ssh.close()

Transferência de Arquivos via SFTP

Paramiko também suporta SFTP para upload e download de arquivos:

import paramiko

transporte = paramiko.Transport(('ip_do_servidor', 22))
transporte.connect(username='admin', password='minha_senha')

# Iniciar cliente SFTP
sftp = paramiko.SFTPClient.from_transport(transporte)
# Upload de arquivo local para servidor
sftp.put('/caminho/local/arquivo.txt', '/caminho/remoto/arquivo.txt')
# Download de arquivo remoto para local
sftp.get('/caminho/remoto/dados.log', '/caminho/local/dados.log')
sftp.close()
transporte.close()

Encapsualmento de Funcionalidades em Classe

Para reutilização, pode-se criar uma classe que gerencia conexões SSH e operações SFTP, suportando context manager:

import paramiko

class GerenciadorSSH:
    def __init__(self, servidor, porta, usuario, chave_path=None, senha=None):
        self.servidor = servidor
        self.porta = porta
        self.usuario = usuario
        self.chave_path = chave_path
        self.senha = senha
        self.transporte = None

    def abrir_conexao(self):
        self.transporte = paramiko.Transport((self.servidor, self.porta))
        if self.chave_path:
            chave = paramiko.RSAKey.from_private_key_file(self.chave_path)
            self.transporte.connect(username=self.usuario, pkey=chave)
        else:
            self.transporte.connect(username=self.usuario, password=self.senha)

    def executar_comando(self, comando):
        cliente = paramiko.SSHClient()
        cliente._transport = self.transporte
        _, saida, _ = cliente.exec_command(comando)
        return saida.read().decode('utf-8')

    def enviar_arquivo(self, origem, destino):
        sftp = paramiko.SFTPClient.from_transport(self.transporte)
        sftp.put(origem, destino)
        sftp.close()

    def receber_arquivo(self, origem, destino):
        sftp = paramiko.SFTPClient.from_transport(self.transporte)
        sftp.get(origem, destino)
        sftp.close()

    def fechar_conexao(self):
        if self.transporte:
            self.transporte.close()

    def __enter__(self):
        self.abrir_conexao()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.fechar_conexao()

# Exemplo de uso com context manager
with GerenciadorSSH('ip_do_servidor', 22, 'admin', chave_path='/home/usuario/.ssh/id_rsa') as gerenciador:
    print(gerenciador.executar_comando('ls -la'))
    gerenciador.enviar_arquivo('/local/dados.csv', '/remoto/dados.csv')

Tags: paramiko SSH Python chaves-publicas sftp

Publicado em 6-11 07:40 por Thomas