paramiko mit rsa key ohne passphrase

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
barnybla
User
Beiträge: 3
Registriert: Montag 8. Juni 2020, 13:11

Hallo Zusammen,

ich versuche gerade mit einem Python3.7 Script uns Paramiko über SSH auf einem anderen PC Befehle auszuführen. Mein Script sieht wie folgt aus:

Code: Alles auswählen

import os
import sys
import paramiko
ssh = paramiko.SSHClient()

hostkeytype = None
hostkey = None
hostname = "192.168.100.12"

client = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pkey_file = os.path.expanduser('~/.ssh/id_rsa')
passphrase = sys.stdin.readline().strip('\n')
pkey = paramiko.RSAKey.from_private_key(pkey_file, passphrase)
client.connect(hostname, username="root", pkey=pkey)
stdin, stdout, stderr = client.exec_command('cp /root/test.call /var/log')
for line in stdout:
    print (line.strip)
client.close()
Wenn ich das Script aufrufe, gibt es keine Ausgabe auf dem Schirm, breche ich das Script ab kommt folgende Ausgabe:

Code: Alles auswählen

CTraceback (most recent call last):
  File "Test.py", line 13, in <module>
    passphrase = sys.stdin.readline().strip('\n')
KeyboardInterrupt
Kann mir da jemand helfen, wo der Fehler liegt.

Mfg Bernd
Sirius3
User
Beiträge: 18227
Registriert: Sonntag 21. Oktober 2012, 17:20

Da wartet das Programm darauf, dass irgendwer was eingibt. Eigentlich macht man das mit getpass.getpass, weil Passwörter möchte man nicht gerne auf dem Bildschirm sehen.
barnybla
User
Beiträge: 3
Registriert: Montag 8. Juni 2020, 13:11

Danke für die Antwort.
Aber was will das Programm wissen, es könnte sich ja nur um die passphrase vo rsa key handeln, der key ist aber ohne gespeichert. Bedeutet es dann, dass die Befehle falsch sind, was müsste da denn geändert werden, damit er nich mehr danach fragt?

LG Bernd
Benutzeravatar
__blackjack__
User
Beiträge: 13938
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@barnybla: Ähm, die Zeile 13 liest eine Zeile von der Standardeingabe, entfernt das abschliessende Zeilenendezeichen, und bindet das ganze an den Namen `passphrase`. Das steht so in *Deinem* Programm. Warum schreibst Du das in Dein Programm, wenn Du das gar nicht so haben willst?

Ist auch eine recht umständliche Art, denn was spräche denn hier einfach gegen die `input()`-Funktion?

Der Code erstellt zwei `SSHClient`-Objekte und setzt bei einem die Policy für fehlende Hostkeys — und verwendet das dann gar nicht weiter. Das macht keinen Sinn. Entweder kann man das weg lassen, oder Du wolltest das `SSHClient`-Objekt weg lassen und die Policy auf dem anderen `SSHClient`-Objekt setzen.

`hostkeytype` und `hostkey` werden definiert, aber nirgends verwendet.

`SSHClient`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden.

Das `os.path`-Modul würde ich in neuem Code nicht mehr verwenden wenn die Funktionalität in `pathlib` verfügbar ist.

`pkey_file` ist ein irreführender Name weil es sich gar nicht um eine Datei, sondern um einen Datei*namen* handelt. Man sollte auch keine kryptischen Abkürzungen in Namen verwenden. Wenn man `private_key` meint, sollte man nicht `pkey` schreiben.

`RSAKey.from_private_key` will als erstes Argument ein Dateiobjekt, keinen Dateinamen. Überhaupt solltest Du Dir die Dokumentation zu dieser Methode mal anschauen.

Die `strip()`-Methode muss man schon auch aufrufen. Sonst wird die Zeichenkettenrepräsentation von der Methode ausgegeben, und nicht die Zeichenkette ohne Whitespace am Anfang und am Ende. Man könnte alternativ dem `print()` auch sagen, dass man kein Zeilenende am Ende ausgegeben haben möchte.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from pathlib import Path

import paramiko


def main():
    hostname = "192.168.100.12"

    with paramiko.SSHClient() as client:
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        private_key_filepath = Path.home() / ".ssh" / "id_rsa"
        passphrase = input()
        with private_key_filepath.open(encoding="ascii") as private_key_file:
            private_key = paramiko.RSAKey.from_private_key(
                private_key_file, passphrase
            )
        client.connect(hostname, username="root", pkey=private_key)
        _stdin, stdout, _stderr = client.exec_command(
            "cp /root/test.call /var/log"
        )
        for line in stdout:
            print(line, end="")


if __name__ == "__main__":
    main()
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
barnybla
User
Beiträge: 3
Registriert: Montag 8. Juni 2020, 13:11

@ _blackjack_: danke für deine Antwort, wie du sicher gemerkt hast bin ich Anfänger in der Materie. Ich habe das Script ausprobiert, es läuft so. Wie muss ich es ändern wenn ich keine passphrase für den rsa key brauche, er ist ohne generiert?

LG Bernd
Benutzeravatar
__blackjack__
User
Beiträge: 13938
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wie gesagt, schau Dir mal die Dokumentation von `RSAKey.from_private_key()`. Das sollte die Lösung sehr nahe legen.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
Antworten