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?
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.