简体   繁体   中英

How to decrypt passphrase-protected SSH key using Fabric and fabfile?

I'm in the process of GettingStarted with Fabric 2.4.0 and I cannot figure out an elegant and secure way to decrypt my SSH key to pass it to Fabric. My code is as follows:

#!/usr/bin/env python3
"""fabfile"""
from fabric import Connection

c = Connection('user@ip.address')
result = c.run('uname -s')

On this simple example, running python fabfile.py I get the error:

File "/Users/user.name/GitHub/app_name/fabfile.py", line 6, in <module>
result = c.run('uname -s')
File "<decorator-gen-3>", line 2, in run
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/fabric/connection.py", line 29, in opens
self.open()
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/fabric/connection.py", line 615, in open
self.client.connect(**kwargs)
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/client.py", line 437, in connect
passphrase,
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/client.py", line 749, in _auth
raise saved_exception
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/client.py", line 720, in _auth
filename, pkey_class, passphrase
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/client.py", line 571, in _key_from_filepath
key = klass.from_private_key_file(key_path, password)
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/pkey.py", line 206, in from_private_key_file
key = cls(filename=filename, password=password)
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/rsakey.py", line 55, in __init__
self._from_private_key_file(filename, password)
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/rsakey.py", line 175, in _from_private_key_file
data = self._read_private_key_file("RSA", filename, password)
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/pkey.py", line 279, in _read_private_key_file
data = self._read_private_key(tag, f, password)
File "/Users/user.name/anaconda/envs/virtual_env/lib/python3.6/site-packages/paramiko/pkey.py", line 329, in _read_private_key
raise PasswordRequiredException("Private key file is encrypted")
paramiko.ssh_exception.PasswordRequiredException: Private key file is encrypted
  1. How can I get Fabric and paramiko to ask me for my Encryption passphrase running the fabfile above?
  2. Is python fabfile.py an acceptable syntax to run the commands above?
  3. What is the best security practice for automatically passing an SSH key from a user's computer to a script in 2018? Is using os.environ() acceptable?

I see in the docs on authentication , Fabric notes The connect_kwargs.passphrase config option is the most direct way to supply a passphrase to be used automatically.

But then immediately afterward it says:

Using actual on-disk config files for this type of material isn't always wise, but recall that the configuration system is capable of loading data from other sources, such as your shell environment or even arbitrary remote databases.

I'm concerned about setting this up the wrong way from a security standpoint. Is using environment variables to pass the ssh passphrase secure enough? If so, what does a working code snippet look like to get this command to work with an SSH key that is encrypted?

#!/usr/bin/env python3
"""fabfile"""
from fabric import Connection

c = Connection('user@ip.address')
result = c.run('uname -s')

A user of your script can be prompted for a passphrase for the SSH key before executing commands with the CLI option.

This takes care of merging the passphrase in theconnect_kwargs options forwarded to Paramiko.

fab --prompt-for-passphrase <command>

The issue with the above approach is having to enter the passphrase every time you run a command.

As advised in the docs, you can export an environment variable in your shell session. eg

export SSH_PASSPHRASE="gongo-aso!"

This can then be read from and used in the connect_kwargs options passed to the constructor for the Connection object.

#!/usr/bin/env python3
"""fabfile"""
from os import getenv
from fabric import Connection

connect_kwargs = {
    'passphrase': getenv('SSH_PASSPHRASE')
}

c = Connection('user@ip.address', connect_kwargs=connect_kwargs)
result = c.run('uname -s')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM