I'm trying to use Paramiko to connect to an SSH server from Python. This is what I tried so far:
>>> import paramiko
>>> import os
>>> privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
>>> mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 198, in from_private_key_file
key = cls(filename=filename, password=password)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/rsakey.py", line 51, in __init__
self._from_private_key_file(filename, password)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/rsakey.py", line 163, in _from_private_key_file
data = self._read_private_key_file('RSA', filename, password)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 280, in _read_private_key_file
data = self._read_private_key(tag, f, password)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 323, in _read_private_key
raise PasswordRequiredException('Private key file is encrypted')
paramiko.PasswordRequiredException: Private key file is encrypted
As you can see, it's failing because my private key is encrypted. However, the password is stored in my OS X login keychain, and when I type ssh host
it won't ask for it (rather, it only asks once, then remembers it until the next reboot). Is there a way to make paramiko
use the password / fetch it from the keychain, like ssh
does?
Paramiko relies on cryptography for crypto functionality, which makes use of C and Rust extensions but has many precompiled options available. See our installation page for details. SSH is defined in RFC 4251, RFC 4252, RFC 4253 and RFC 4254. The primary working implementation of the protocol is the OpenSSH project.
Paramiko is a Python library that makes a connection with a remote device through SSh. Paramiko is using SSH2 as a replacement for SSL to make a secure connection between two devices. It also supports the SFTP client and server model.
The following approach seems to work fine (on OS X, with the usual setup of encrypted private keys that have passphrases stored in the keychain, without any user interaction):
import paramiko
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.connect(HOST, username=USER, look_for_keys=False)
...
ssh.close()
It seems that look_for_keys=False
is not absolutely necessary. However, if you use it you will get much better error messages in the case of an authentication failure ("AuthenticationException" instead of "PasswordRequiredException").
If you really want to use private keys directly, you could do the following:
import os
import paramiko
import keyring
keyfile = os.path.expanduser('~/.ssh/id_rsa')
password = keyring.get_password('SSH', keyfile)
key = paramiko.RSAKey.from_private_key_file(keyfile, password=password)
However, based on my testing, this is not needed. The above solution that uses ssh.connect
in a straightforward manner should be sufficient.
The RSAKey.from_private_key_file()
is inherited from PKey()
; an optional parameter of this method is a password. To quote:
If the private key is encrypted and password is not None, the given password will be used to decrypt the key (otherwise PasswordRequiredException is thrown).
As you're not passing a password and your key is encrypted this exception will always be thrown. There's only one way round this problem, to actually give the method a password. You, therefore, need a way of getting the password out of the OSXKeychain.
You could use the cross-platform Keyring
module to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With