Contexte

Pour SFTP sur un autre serveur, j'utilise la commande suivante dans la ligne de commande UNIX:

sftp -i /some_dir/another_dir/key -oPort=12345 user@12.123.456.789

Ce que je veux réaliser

Je souhaite convertir ceci en commande à utiliser avec PySFTP.

Ce que j'ai essayé

import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None

# source: https://pysftp.readthedocs.io/en/release_0.2.7/pysftp.html
srv = pysftp.Connection("user@12.123.456.789", port="12345",  
                         private_key_pass="/some_dir/another_dir/key")

Erreurs rencontrées

File "./aws_sql_dumper.py", line 14, in <module>
    srv = pysftp.Connection("user@12.123.456.789", port="12345",  private_key_pass="/some_dir/another_dir/key")
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 132, in __init__
    self._tconnect['hostkey'] = self._cnopts.get_hostkey(host)
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 71, in get_hostkey
    raise SSHException("No hostkey for host %s found." % host)
paramiko.ssh_exception.SSHException: No hostkey for host user@12.123.456.789 found.
Exception ignored in: <bound method Connection.__del__ of <pysftp.Connection object at 0x7f6067c7ea20>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 1013, in __del__
    self.close()
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 784, in close
    if self._sftp_live:
AttributeError: 'Connection' object has no attribute '_sftp_live'

Recherche effectuée

J'ai lu ce qui suit:

Question

Je pense que je fais quelque chose de fondamentalement mauvais. Comment puis-je adopter la commande SFTP utilisée dans la ligne de commande UNIX pour être acceptée / interprétée par pysftp?


Modifications

J'ai changé quelques choses autour

import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('/home/some_dir/.ssh/known_hosts')

# source: https://pysftp.readthedocs.io/en/release_0.2.7/pysftp.html
srv = pysftp.Connection("user@12.123.456.789", port="12345",  
                         private_key="/some_dir/another_dir/key", cnopts=cnopts)

Sortie après modification

Traceback (most recent call last):
  File "./aws_sql_dumper.py", line 17, in <module>
    srv = pysftp.Connection("user@12.123.456.789", port="12345",  private_key="/some_dir/another_dir/key", cnopts=cnopts)
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 132, in __init__
    self._tconnect['hostkey'] = self._cnopts.get_hostkey(host)
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 71, in get_hostkey
    raise SSHException("No hostkey for host %s found." % host)
paramiko.ssh_exception.SSHException: No hostkey for host user@12.123.456.789" found.
Exception ignored in: <bound method Connection.__del__ of <pysftp.Connection object at 0x7f8120dc6438>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 1013, in __del__
    self.close()
  File "/usr/local/lib/python3.4/dist-packages/pysftp/__init__.py", line 784, in close
    if self._sftp_live:
AttributeError: 'Connection' object has no attribute '_sftp_live
2
3kstc 14 mars 2019 à 07:36

2 réponses

Meilleure réponse

Après de nombreux essais et erreurs, conversion de la commande SFTP suivante placée dans le terminal:

sftp -i /some_dir/another_dir/key -oPort=12345 user@12.123.456.789

Peut être traduit * en:

paramiko.SSHClient().connect(hostname='12.123.456.789', username='user', port=12345,
                             key_filename='/some_dir/another_dir/key')

Le code condensé complet est:

#!/usr/bin/python3

import paramiko

try:
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.WarningPolicy)
    client.connect(hostname='12.123.456.789', username='user', port=12345, 
                   key_filename='/some_dir/another_dir/key')

    # -------------------------- [ just for testing ] --------------------------
    stdin, stdout, stderr = client.exec_command('ls -la')   # THIS IS FOR TESTING
    print(stdout.read())                                    # AND PRINTING OUT

finally:
    client.close()
0
3kstc 27 mars 2019 à 08:49

Vous n'utilisez jamais la variable cnopts. Vous devez le passer au paramètre cnopts de la classe Connection.

Une fois ce problème résolu, vous aurez un problème avec la clé privée, car vous la transmettez au paramètre private_key_pass ("private key passphrase") au lieu de private_key.

srv = pysftp.Connection("user@12.123.456.789", port="12345",  
                         private_key="/some_dir/another_dir/key", cnopts=cnopts)

Bien que vous ne deviez pas faire cnopts.hostkeys = None, car vous perdez la sécurité en le faisant. La bonne solution consiste à vérifier la clé de l'hôte. Consultez ma réponse à la même question pour des solutions correctes.

0
Martin Prikryl 31 oct. 2020 à 09:53