Paramiko öffnet SSH-Verbindungen

© dimjul, 123RF

Abhörsicher

Im Python-Universum finden sich nützliche Module für jeden Zweck. Mit dem Paramiko-Modul können Python-Programmierer und Administratoren per SSH auf entfernten Rechnern Kommandos ausführen und sicher Dateien übertragen.
RAID-Technologie verspricht höhere Performance und mehr Sicherheit beim permanenten Speichern von Daten. Die ADMIN-Redaktion gibt einen Überblick über ... (mehr)

Seit die Secure Shell (SSH) vor vielen Jahren einmal Telnet abgelöst hat, kommt kein Administrator mehr ohne sie aus. Um sich in Python-Skripts per SSH mit anderen Rechnern zu verbinden und dort Befehle auszuführen, gibt es eine Reihe von Lösungen [1]. Die bewährteste von ihnen ist das Paramiko-Modul, das dieser Artikel näher vorstellt [2].

Ursprünglich wurde Paramiko von Robey Pointer geschrieben, der unter anderem bei Twitter gearbeitet und dort Open-Source-Software in Scala unter einer freien Lizenz veröffentlicht hat [3]. Ein Python-Modul mit dem Namen "ssh" firmierte als Fork von Paramiko einige Zeit als dessen Nachfolger. Mittlerweile sind die beiden Projekte aber unter dem Originalnamen vereint, und Jeff Forcier hat die Leitung der Entwicklung übernommen. Der aktuellste Code findet sich deshalb auf [4] und Forciers Github-Seite [5], die ausführliche API-Dokumentation aber immer noch unter [2].

Überall zu Hause

Empfohlen wird für die aktuelleste Paramiko-Version (derzeit 1.8.0) die Python-Distribution 2.3 oder neuer, der Support für Python 3 ist noch in Arbeit. Viele Linux-Distributionen bringen zumindest ältere Versionen von Paramiko schon mit, ebenso wie etwa FreeBSD.

Aus dem entpackten Tar-Archiv lässt sich Paramiko als Root systemweit mit dem Befehl »easy_install ./« installieren. Auch eine Installation auf Windows-Betriebssystemen ist möglich, sie setzt jedoch neben Python die vorherige Installation von Pycrypt, am besten als Binärpaket von [6], voraus.

Im einfachsten Fäll lässt sich Paramiko zum Einloggen auf einem Rechner mit nur wenigen Zeilen einsetzen. Nach dem obligatorischen Importieren des Modules erzeugt die Methode »SSHClient« ein neues Client-Objekt, das mit der Methode »connect()« die Verbindung herstellt:

import paramiko
ssh = paramiko.SSHClient()
ssh.connect(Host, username=Username, password=Passwort)

Typischerweise funktioniert das aber nicht, sondern erzeugt eine »SSHException« . Der Grund dafür ist, dass Paramiko wie der Standard-SSH-Client den Host-Key des entfernten Rechners prüft. Weil das Modul aber ohne Weiteres keinen Zugang zu den gespeicherten Host-Keys hat, schlägt der Verbindungsversuch fehl. Ein einfacher Workaround besteht darin, Paramiko bislang unbekannte Host-Keys umstandslos eintragen zu lassen.

ssh.set_missing_host_key_policy(
 paramiko.AutoAddPolicy())

Dies ist natürlich aber nicht im Sinn des Erfinders und tendenziell unsicher, sollte also nur bei Tests in sicheren Netzen verwendet werden. Der korrekte Weg besteht darin, Paramiko die Host-Keys laden zu lassen, auf dass es sie wie gedacht prüfen kann. Dazu dient die Funktion »load_host_keys()« :

client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))

Setzt man diese Zeile im obigen Beispiel vor den Connect-Aufruf, dürfte die Verbindung klappen. Manche Administratoren haben aber aus Sicherheitsgründen auch das SSH-Login per Username und Passwort abgeschaltet und erlauben lediglich die Authentifizierung per Public Key. Wenn der Anwender zur Verwaltung der Private Keys einen SSH-Agent verwendet, macht Paramiko davon Gebrauch. Hat er die Passphrase bisher noch nicht eingegeben, öffnet sich auf Desktop-Linux-Systemen ein Dialog der zur Eingabe auffordert.

Als Parameter muss »client.connect()« dann nur der »username« übergeben werden. Hat man einen sogenannten Channel für die SSH-Verbindung, lassen sich mit »exec_command()« auf dem entfernten Rechner Befehle ausführen. Der Aufruf gibt jeweils einen Dateideskriptor für die Standardeingabe, die Standardausgabe und die Fehlerausgabe zurück. Listing 1 zeigt dafür ein Beispiel, das die Prozesstabelle auf dem entfernten Rechner ausgibt.

Listing 1

Prozesstabelle anzeigen

 

Wer das Default-Verhalten, den Agent zu verwenden, abschalten will, kann der Methode »allow_agent=False« übergeben.

Wer den SSH-Agent nicht verwenden kann oder will, muss sich anders behelfen. Paramiko bietet an, den zum Public Key (der auf dem Server liegt) passenden Private Key selbst zu laden. Dies geht einfach mit der Funktion

pkey = paramiko.RSAKey.from_private_key(pkey_file)

Es funktioniert aber nur, wenn der Private Key nicht mit einer Passphrase geschützt ist. Ist er dies aber, wie etwa dieser Key,

more ~/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED

muss man der obigen Methode die Passphrase als zweites Argument übergeben. Der Code in Abbildung 1 zeigt, wie man die Passphrase von der Standardeingabe liest und den Private Key damit entschlüsselt, bevor man ihn an die Connect-Methode übergibt. Dabei darf man nicht vergessen, das die Eingabe abschließende Linefeed-Zeichen zu entfernen, sonst schlägt die Dekodierung fehl.

Abbildung 1: Paramiko verwendet die Keys des SSH-Agents, kann aber den Private Key auch selbst dekodieren.

Neben solchen SSH-Sessions deckt Paramiko auch die Datenübertragung per SFTP ab. Um eine entsprechende Verbindung zu öffnen, genügt es, die Methode »open_sftp()« des Paramiko-Clients aufzurufen, was wiederum ein SFTP-Objekt zurückliefert. Dieses Objekt bietet eine ganze Reihe von Methoden, die Shell-Befehlen oder den bekannten Kommandos in FTP-Clients ähneln. So wechselt »chdir()« in ein anderes Verzeichnis und »listdir()« gibt den Inhalt eines Verzeichnisses aus.

Es lassen sich aber auch Verzeichnisse anlegen, löschen und umbenennen. Dies übernehmen die Methoden »mkdir()« , »rmdir()« und »rename()« . Eine Datei löscht ein Aufruf von »remove()« oder »unlink()« .

Auch für das Ändern des Dateieigentümers und der Zugriffsrechte bietet der SFTP-Client passende Methoden. Dies sind wie in der Shell »chown()« und »chmod()« . Die beiden Methoden »get()« und »put()« holen eine Datei vom Server respektive speichern sie dort.

Schließlich lässt sich eine Datei auch direkt auf dem Server anlegen, wenn man »file()« verwendet. So können Python-Skripts umstandslos Dateien auf dem Server speichern, ohne vorher lokal eine temporäre Kopie davon anzulegen. Eine vollständige Liste aller Funktionen findet sich in der API-Dokumentation des »SFTPClient« -Objekts unter [2].

Einfacher

Wem dies alles noch zu viel Aufwand ist, der sollte einen Blick auf den Paramiko-Wrapper eines Python-Anwenders verwenden, der sich online nur unter seinem Vornamen Zeth auftritt [7]. Mit seinem Modul gestaltet sich die Benutzung von SSH und SFTP per Python noch einmal einfacher:

import ssh
s = ssh.Connection('my.server.de')
s.put('up.txt')
s.get('down.txt')
s.execute('du -h .')

Der Wrapper ist natürlich nicht so gut getestet wie Paramiko selbst, und man hat weniger Kontrolle darüber, was hinter den Kulissen passiert.

Ähnliche Artikel

comments powered by Disqus

Artikel der Woche

Eigene Registry für Docker-Images

Wer selber Docker-Images herstellt, braucht auch eine eigene Registry. Diese gibt es ebenfalls als Docker-Image, aber nur mit eingeschränkter Funktionalität. Mit einem Auth-Server wird daraus ein brauchbares Repository für Images. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Google+

Ausgabe /2019