rsync ssh und Passwort Eingabe

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Abend,

ich bastle gerade an einem python skript um mein Backup durchzuführen. Es soll mehrere Clients mit einem Server synchronisieren. Dafür nutze ich die Tools rsync und ssh in meinem python skript. Das Problem ist, dass ich nach einem Passwort gefragt werde und mir nicht sicher bin welche Möglichkeiten ich alle habe und welcher der einfachste/beste Weg ist. Es gibt glaube ich für ssh eine Möglichkeit das über config Dateien zu lösen. Mehr Möglichkeiten kenne ich nicht. Welche kennt Ihr? Welche empfehlt ihr mir?

Grüße Markus
deets

Public/private key authentifizierung mittels "~/.ssh/authorized_keys" auf dem host. Wenn der key keine Pass-Phrase hat, laeuft dein Programm "einfach so".

Wenn doch, dann bin ich ehrlich gesagt nicht ganz sicher, ob ein mittels ssh-add dem authentication agent bekanntgemachter + entschluesselter key auch fuer kommandozeilenprogramme klappt. UU muesste man da ein bisschen mit dem environ tricksen, aber ich bin mal mutig und behaupte, das geht.

Last but not least gibt's pexpect, mit dem man ssh passworteingabe machen kann - aber das wuerde ich nicht empfehlen, denn dann hast du das Passwort im Klartext irgendwo rumliegen. Da waere dann ein passwort-loser Key die bessere Alternative.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

deets hat geschrieben:Wenn doch, dann bin ich ehrlich gesagt nicht ganz sicher, ob ein mittels ssh-add dem authentication agent bekanntgemachter + entschluesselter key auch fuer kommandozeilenprogramme klappt.
Na klar! Benutze ich staendig fuer ssh, svn, git und Co aus der Kommandozeile. :)
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Habe gerade noch die Möglichkeit statt PExpect das ganze mit Popen.Communicate() oder in meinem Fall subprocess.communicate() zu lösen. Hier ein Link http://www.python-forum.de/viewtopic.ph ... ommunicate im letzten Beitrag steht der fertige Lösung. Die Passwörter müssten dann pro Session nur einmal eingegeben werden. Denn mir schmeckt der Gedanke nicht, dass auf allen Rechnern und allen Benutzern public/private Keys rum fliegen die ungehinderten Zugang zu meinem Server erlauben.

Grüße Markus
deets

Rebecca hat geschrieben:
deets hat geschrieben:Wenn doch, dann bin ich ehrlich gesagt nicht ganz sicher, ob ein mittels ssh-add dem authentication agent bekanntgemachter + entschluesselter key auch fuer kommandozeilenprogramme klappt.
Na klar! Benutze ich staendig fuer ssh, svn, git und Co aus der Kommandozeile. :)
Jein, ich ja auch. Sonst braeuchte man's ja gar nicht ;) Ich weiss halt nur nicht genau, ob es transitiv ist. Also ein Programm zu starten, dass dann ein Programm startet. Das ist ja hier der Fall: ein Python-Skript welches dann den rsync-Prozess startet & der dann SSH. Aber ich denke auch, es geht, solange niemand das environment verpfuscht.
deets

feldmaus hat geschrieben:Habe gerade noch die Möglichkeit statt PExpect das ganze mit Popen.Communicate() oder in meinem Fall subprocess.communicate() zu lösen. Hier ein Link http://www.python-forum.de/viewtopic.ph ... ommunicate im letzten Beitrag steht der fertige Lösung. Die Passwörter müssten dann pro Session nur einmal eingegeben werden. Denn mir schmeckt der Gedanke nicht, dass auf allen Rechnern und allen Benutzern public/private Keys rum fliegen die ungehinderten Zugang zu meinem Server erlauben.
Das tun sie ja auch nicht. Sondern das von mir und Rebecca angesprochene Verfahren mit dem authentication agent loest das Problem dadurch, dass die Keys ihrerseits verschluesselt sind, und sich erst nach eingabe eines Passwortes benutzen lassen. Womit erstmal nicht viel gewonnen scheint. Doch der Trick ist, das mit dem Kommando "ssh-add" man einen Key einmal pro session entschluesselt, und alle nachfolgenden Programme benutzen den dann. Das ist bequemer als deine Loesung (solange du online bist, nur einmal entschluesseln), aber nicht unsicherer.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

deets hat geschrieben:
feldmaus hat geschrieben:Habe gerade noch die Möglichkeit statt PExpect das ganze mit Popen.Communicate() oder in meinem Fall subprocess.communicate() zu lösen. Hier ein Link http://www.python-forum.de/viewtopic.ph ... ommunicate im letzten Beitrag steht der fertige Lösung. Die Passwörter müssten dann pro Session nur einmal eingegeben werden. Denn mir schmeckt der Gedanke nicht, dass auf allen Rechnern und allen Benutzern public/private Keys rum fliegen die ungehinderten Zugang zu meinem Server erlauben.
Das tun sie ja auch nicht. Sondern das von mir und Rebecca angesprochene Verfahren mit dem authentication agent loest das Problem dadurch, dass die Keys ihrerseits verschluesselt sind, und sich erst nach eingabe eines Passwortes benutzen lassen. Womit erstmal nicht viel gewonnen scheint. Doch der Trick ist, das mit dem Kommando "ssh-add" man einen Key einmal pro session entschluesselt, und alle nachfolgenden Programme benutzen den dann. Das ist bequemer als deine Loesung (solange du online bist, nur einmal entschluesseln), aber nicht unsicherer.
Ok, aber wenn Jemand doch meinen Account crackt z.b. über java skripte über meinen Internet Browser und er weiß wie mein Server intern heißt, was kein Problem ist, dann kann er sich auch auf meinem Server einloggen über meinen Client. Daher halte ich es nicht für sinnvoll auf jedem Rechner und für jeden Benutzer solch ein verschlüsseltes public/private key paar zu hinterlegen.

Grüße Markus
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

feldmaus hat geschrieben:Daher halte ich es nicht für sinnvoll auf jedem Rechner und für jeden Benutzer solch ein verschlüsseltes public/private key paar zu hinterlegen.
Das ist gerade der Punkt: Wenn du ein Schlüsselpaar hast kannst du damit ohne den Passphrase nichts anfangen. Wenn der SSH-Agent aber aktiv ist kann der Angreifer ihn u.U. nutzen. Moeglichkeit waeren natuerlich eingeschraenkte User-Accounts auf dem Server, eigenes SSH-Schluesselpaar fuer den Zweck und eigener SSH-Agent. Interessant waere da evtl auch `keychain`.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Ich komme gerade nicht weiter. Also wie gesagt ich wollte zwei-gleisig fahren. Über public/pivate key Authentication und Passwörter direkt eingeben, allerdings sollten die Passwörter nur einmal eingegeben werden müssen. Die Passwörter würden dann in einem Dictionary gespeichert werden. Ich weiß BlackJack es ist unsicher.

So nun habe ich eine Abfrage wo getestet wird ob das Passwort schon im Dictionary ist oder ob auf dem Client ein public/private Key vorliegt:

Code: Alles auswählen

            if benutzer_passwoerter.has_key(BENUTZER) or (subprocess.check_call(['find', '/home/'+BENUTZER+'/.ssh/id*'])==0):
                rsync()
Ich bekomme die Fehlermeldung:

Code: Alles auswählen

Das untersuchte Programm erzeugte die Ausnahme CalledProcessError
"Command '['find', '/home/markus/.ssh/id*']' returned non-zero exit status 1"
Datei: /usr/lib/python2.6/subprocess.py, Zeile: 488
Anhalten?
Das ist ja ok, aber warum macht er an dieser Stelle nicht weiter?

Grüße Markus
BlackJack

@feldmaus: Das ist keine Python-Fehlermeldung. Kann es sein, dass Du das aus einer IDE heraus startest? Vom wem kommt das 'Anhalten?' -- gibt das Dein Programm aus? Wenn nicht welches Programm macht das dann?

`dict.has_key()` ist veraltet und in Python 3 nicht mehr vorhanden. Den Test sollte man mit dem ``in``-Operator ausdrücken. Und muss man für den zweiten Teil der Bedingung wirklich ``find`` starten? Das kann man doch sicher auch mit Python audrücken; zum Beispiel mit dem `glob`-Modul.

Das `check_call()` hier Unsinn ist, sollte eigentlich klar sein. Gibt das überhaupt etwas zurück?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Der `find`-Aufruf ist falsch. Daneben kann man das einfach durch `glob` ersetzen und braucht keinen Prozessaufruf.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

BlackJack hat geschrieben:@feldmaus: Das ist keine Python-Fehlermeldung. Kann es sein, dass Du das aus einer IDE heraus startest? Vom wem kommt das 'Anhalten?' -- gibt das Dein Programm aus? Wenn nicht welches Programm macht das dann?
Ich nutze Eric. Wenn ich es in der Konsole starte, dann bekomme ich:

Code: Alles auswählen

markus@feld-bertlap ~/bin $ ./backup.py 
Moechtest Du eine Sicherung/Zurueckspielen fuer feld-bertlap durchfuehren?(j/n)j
Sichern/Zurueckspielen/Nichts von /home/markus/bin/ (s/z/N)? 
find: "/home/markus/.ssh/id*": Datei oder Verzeichnis nicht gefunden
Traceback (most recent call last):
  File "./backup.py", line 126, in <module>
    if benutzer_passwoerter.has_key(BENUTZER) or (subprocess.check_call(['find', '/home/'+BENUTZER+'/.ssh/id*'])==0):
  File "/usr/lib/python2.6/subprocess.py", line 488, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['find', '/home/markus/.ssh/id*']' returned non-zero exit status 1
`dict.has_key()` ist veraltet und in Python 3 nicht mehr vorhanden. Den Test sollte man mit dem ``in``-Operator ausdrücken. Und muss man für den zweiten Teil der Bedingung wirklich ``find`` starten? Das kann man doch sicher auch mit Python audrücken; zum Beispiel mit dem `glob`-Modul.

Das `check_call()` hier Unsinn ist, sollte eigentlich klar sein. Gibt das überhaupt etwas zurück?
Ok folgende Änderung:

Code: Alles auswählen

    for eintrag in katalog:
        for BENUTZER in katalog[eintrag]['Benutzer']:
            antwort2=raw_input('Sichern/Zurueckspielen/Nichts'+katalog[eintrag]['Frage'][0]+BENUTZER+katalog[eintrag]['Frage'][1])
            if (BENUTZER in benutzer_passwoerter) or (len(glob.glob('/home/'+BENUTZER+'/.ssh/id*'))>0):
                rsync()
            else:
                PASSWORT=raw_input('Bitte Passwort fuer '+BENUTZER+' eingeben:')
                benutzer_passwoerter[BENUTZER]=PASSWORT
                rsync()
Dieser Teil scheint also halbwegs zu funktionieren. Er bleibt nun wieder stecken bei meinem rsync Prozess. Hier der Teil von meinem rsync Prozess:

Code: Alles auswählen

                p=subprocess.Popen(['rsync',
                '--rsh=ssh -l '+BENUTZER,
                '-a',
                '--delete-after',
                '--stats',
                '--progress', 
                exclude_pre,
                exclude_post,
                source,
                target], stdin=subprocess.PIPE, shell=True)
                p.communicate(benutzer_passwoerter[BENUTZER]+'\n')
Die Fehlermeldung ist:

Code: Alles auswählen

rsync error: syntax or usage error (code 1) at main.c(1428) [client=3.0.7]
Wahrscheinlich mag er mal wieder was nicht mit den Sonderzeichen.

Den exclude Ausdruck definiere ich weite oben:

Code: Alles auswählen

        exclude_pre=katalog[eintrag]['Exclude'][0]
        exclude_post=katalog[eintrag]['Exclude'][1]
Und hier der Dictionary Eintrag dazu:

Code: Alles auswählen

                'Exclude':['--exclude', 'Machines/Standard/Snapshots/*'],
Grüße Markus
BlackJack

@feldmaus: Natürlich stimmt das alles nicht mehr wenn ``shell=True`` übergeben wird. Dann muss alles für die Shell escaped werden. Dann kannst Du auch statt einer Liste eine Zeichenkette mit ``+`` zusammen setzen…
deets

feldmaus hat geschrieben: Ok, aber wenn Jemand doch meinen Account crackt z.b. über java skripte über meinen Internet Browser und er weiß wie mein Server intern heißt, was kein Problem ist, dann kann er sich auch auf meinem Server einloggen über meinen Client. Daher halte ich es nicht für sinnvoll auf jedem Rechner und für jeden Benutzer solch ein verschlüsseltes public/private key paar zu hinterlegen.

Grüße Markus
Das ist Unsinn. Wenn jemand deiner Rechner knackt, hat er deswegen noch lange nicht die Informationen, die der authentication agent hat. Die hat er naemlich nur in den Prozessen, die *deine* aktuelle Session beinhaltet.

*Wenn* er da rankaeme, weil er zB einen Webserver Prozess uebernommen hat, dann hat er irgendwie Root-Rechte bekommen, und kann zB den gesamten Speicher dumpen. Dann hat er auch deine pexpect-loesung mit eingegebenem Passwort, bzw. er installiert ein root-kit und faengt einfach deine ganzen Eingaben ab beim naechsten rsync

Es tut mir leid, aber fuer mich sieht es so aus als ob du aus Mangel an Kenntnissen & dem Unwillen, dich mit diesem Thema *wirklich* auseinderzusetzen einfach einen Weg beschreitest, der dir irgendwie angenehmer ist. Und das ist bei Sicherheitsfragen eine eher unguenstige Herangehensweise.
deets

cofi hat geschrieben:
feldmaus hat geschrieben:Daher halte ich es nicht für sinnvoll auf jedem Rechner und für jeden Benutzer solch ein verschlüsseltes public/private key paar zu hinterlegen.
Das ist gerade der Punkt: Wenn du ein Schlüsselpaar hast kannst du damit ohne den Passphrase nichts anfangen. Wenn der SSH-Agent aber aktiv ist kann der Angreifer ihn u.U. nutzen. Moeglichkeit waeren natuerlich eingeschraenkte User-Accounts auf dem Server, eigenes SSH-Schluesselpaar fuer den Zweck und eigener SSH-Agent. Interessant waere da evtl auch `keychain`.
Den SSH-Agenten zu nutzen gelingt nur, wenn man auf beliebige Prozesse zugreifen kann. Wer das kann, hat das System auf einer Ebene uebernommen, bei der die ganze Diskussion voellig sinnlos wird, denn dann installiert er einen Keylogger & Rootkit, und Ende Gelaende.

Den SSH-Agenten zu benutzen, zusammen mit pub/priv-key-authentication hat einfach den Vorteil, dass man Passworteingabe von rsync entkoppelt. Womit weniger zu programmieren ist, und man sich bei den sicherheitskritischen Themen auf Tools verlaesst, die von vielen Menschen schon betrachtet & fuer gut befunden wurden. Das ist keine 100%ige Garantie, aber *immer* besser, als was selbst zu stricken.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

deets hat geschrieben:
feldmaus hat geschrieben: Ok, aber wenn Jemand doch meinen Account crackt z.b. über java skripte über meinen Internet Browser und er weiß wie mein Server intern heißt, was kein Problem ist, dann kann er sich auch auf meinem Server einloggen über meinen Client. Daher halte ich es nicht für sinnvoll auf jedem Rechner und für jeden Benutzer solch ein verschlüsseltes public/private key paar zu hinterlegen.

Grüße Markus
Das ist Unsinn. Wenn jemand deiner Rechner knackt, hat er deswegen noch lange nicht die Informationen, die der authentication agent hat. Die hat er naemlich nur in den Prozessen, die *deine* aktuelle Session beinhaltet.

*Wenn* er da rankaeme, weil er zB einen Webserver Prozess uebernommen hat, dann hat er irgendwie Root-Rechte bekommen, und kann zB den gesamten Speicher dumpen. Dann hat er auch deine pexpect-loesung mit eingegebenem Passwort, bzw. er installiert ein root-kit und faengt einfach deine ganzen Eingaben ab beim naechsten rsync
Du meinst der Einbrecher wartet 2 Monate bis ich mein Update mache und schlägt dann zu. na hoffentlich hat der viel Kaffee zu Hause. :-) Spaß muss sein. :-)

Grüße Markus
BlackJack

@feldmaus: Du weisst aber schon das so ein Angreifer nicht den lieben langen Tag an seinem Rechner sitzt um live anzuschauen was Du tippst, sondern das einem Programm überlassen wird, was ihm die interessanten Daten sammelt und auswertet!?
deets

@feldmaus

Ob du deinen rsync alle 2 Monate machst oder nicht (oder was auch immer du alle zwei Monate so machst) hat doch damit nix zu tun.

Das pub/priv-Key Verfahren hat nur dann ein Sicherheitsproblem, wenn du die Keys nicht mit Passwoertern schuetzt. Womit sich oberflaechlich betrachtet kein Unterschied ergibt zwischen remote mit Passwort einloggen, und remote mit Key einloggen, aber jedesmal erstmal den Key entschluesseln zu muessen.

Und genau deswegen gibt es den SSH-Agenten, der dieses enstschluesseln *einmal* macht wenn du vor deinen Rechner sitzt, und dann machst du das nicht mehr. Ich verbinde mich am Tag dutzende male auf irgendwelche Server-Systeme, und per GIT + SSH nochmal ein paar dutzend mal mehr. Jedesmal ein Passwort einzutippen - da wuerde ich wahnsinnig werden. Wenn man natuerlich Arbeitsintervalle von 2 Monaten hat, ist das wahrscheinlich ein geringeres Problem.

Sobald du deinen Rechner wieder ausschaltest (bzw. dich abmeldest), ist der Key wieder so sicher wie irgendwas.

Ich schreibe das jetzt hier nochmal bewusst langsam, damit du das gruendlich lesen kannst: Wenn der key verschluesselt ist, kommt der hypothetische Angreifer nicht auf deinen Server, auch wenn er den privaten Key hat.

'Nuff said, es steht dir ja immer frei, auf deine eigenen Fuesse das Feuer zu eroeffenen ;)
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Ich glaube ich bin weiter gekommen. Allerdings fragt er mich immer noch nach meinem Passwort.

Code: Alles auswählen

                p=subprocess.Popen(['rsync',
                '--rsh=ssh -l '+BENUTZER,
                '-a',
                '--delete-after',
                '--stats',
                '--progress', 
                exclude_pre,
                exclude_post,
                source,
                target], stdin=subprocess.PIPE)
                p.communicate(benutzer_passwoerter[BENUTZER]+'\n')
Habe ich in meinem Code einen Fehler? Müsste eigentlich hinhauen.
deets

Ah, Klartextpasswoerter im Quelltext. Die Koenigsloesung. Ich rieche blutigen Fuss... aber sei's drum: es geht nicht, weil man dafuer (wie schon mehrfach hier + im von dir referenzierten Thread erwaehnt) fuer sowas pexpect notwendig ist. SSH verweigert die Annahme von Passwoertern ueber die Standardeingabe. Und *nein*, nur weil "sudo passwd" in dem anderen Thread das nicht macht, heisst das noch lange nix fuer SSH.
Antworten