使用 SSH 密钥文件与 Fabric

104

如何配置Fabric使用SSH密钥文件连接远程主机(例如Amazon EC2实例)?

8个回答

154

不知道为什么,找到一个带有SSH密钥文件使用实例的简单fabfile并不容易。我写了一篇关于此的博客文章(还有一个相应的gist)。

基本上,使用方法如下:

from fabric.api import *

env.hosts = ['host.name.com']
env.user = 'user'
env.key_filename = '/path/to/keyfile.pem'

def local_uname():
    local('uname -a')

def remote_uname():
    run('uname -a')

重要的部分是设置env.key_filename环境变量,这样Paramiko配置在连接时才能查找它。


4
在实践中,这是更好的答案。 - panchicore
3
env.key_filename 可以包含字符串列表,用于尝试在连接中使用多个密钥文件。 - Carl G
2
我在我的一个任务中使用settings上下文管理器以编程方式设置密钥,但无法识别key_filename,直到我将key_filename='/path/to/key'更改为key_filename=['/path/to/key']。因此,如果其他人遇到问题,将key_filename作为密钥列表可能会解决问题。这是使用fab 1.10.1和Paramiko 1.15.2的情况。 - Jaymon
3
@AseemHegshetye,它在最新的Fabric 2中被移除了。这个答案是针对Fabric 1的。 - Iulian Onofrei
1
我更喜欢显式导入而不是使用import *。 - mit
显示剩余3条评论

71

这里值得一提的是,您可以使用命令行参数来实现此功能:

fab command -i /path/to/key.pem [-H [user@]host[:port]]

这个方法对我没用,但通过先运行 eval 'ssh-agent'(<- 在此处使用反引号,而非引号)然后再运行 ssh-add /path/to/key.pem 把 SSH 密钥添加到我的密钥链中,就可以让我不用 -i 标志运行 fab 了。 - Raoul

67

Fabric 1.4 版本以后的一个很酷的功能是 - 现在支持SSH配置文件

如果您已经在~/.ssh/config文件中设置了所有SSH连接参数,Fabric将本地支持它,你所需要做的只是添加以下内容:

env.use_ssh_config = True

在你的fabfile开头。


2
非常有用!如果你遇到像IOError: [Errno 2] No such file or directory: '/path/to/.ssh/key'或者Login password for 'root':这样的错误,只需确保你的.ssh/config文件中没有空格。例如,应该是User=root而不是User = root... - dennis
@dennis 这在2016年仍然似乎是一个问题..!谢谢! - gabn88

21

在fabfile中使用 fabric2 ,请使用以下内容:

from fabric import task, Connection

@task
def staging(ctx):
    ctx.name = 'staging'
    ctx.user = 'ubuntu'
    ctx.host = '192.1.1.1'
    ctx.connect_kwargs.key_filename = os.environ['ENV_VAR_POINTS_TO_PRIVATE_KEY_PATH']

@task
def do_something_remote(ctx):
    with Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs) as conn:
        conn.sudo('supervisorctl status')

并使用以下命令运行:

fab staging do_something_remote

更新:
对于多个主机(一个主机也可以),您可以使用以下内容:

from fabric2 import task, SerialGroup

@task
def staging(ctx):
    conns = SerialGroup(
        'user@10.0.0.1',
        'user@10.0.0.2',
        connect_kwargs=
        {
            'key_filename': os.environ['PRIVATE_KEY_TO_HOST']
        })
    ctx.CONNS = conns
    ctx.APP_SERVICE_NAME = 'google'

@task
def stop(ctx):
    for conn in ctx.CONNS:
        conn.sudo('supervisorctl stop ' + ctx.APP_SERVICE_NAME)

使用fab或fab2运行它:

fab staging stop

1
这是在 Fabric 2.x 中正确的做法,因为所有其他答案都不起作用。 - Vivek Aditya
如何在此“staging”任务中支持多个主机? - Black_Rider
1
@Black_Rider,我把它加入到我的答案中。 - MikeL

15

对我来说,下面的方法不起作用:

env.user=["ubuntu"]
env.key_filename=['keyfile.pem']
env.hosts=["xxx-xx-xxx-xxx.ap-southeast-1.compute.amazonaws.com"]
或者。
fab command -i /path/to/key.pem [-H [user@]host[:port]]

然而,以下内容确实做到了:

env.key_filename=['keyfile.pem']
env.hosts=["ubuntu@xxx-xx-xxx-xxx-southeast-1.compute.amazonaws.com"]
或者
env.key_filename=['keyfileq.pem']
env.host_string="ubuntu@xxx-xx-xxx-xxx.ap-southeast-1.compute.amazonaws.com"

4
如果您使用env.user="ubuntu"而不是env.user=["ubuntu"]",那么您的第一个示例对我有效。 - Taylor D. Edmiston

7

今天我需要做这个,我的.py文件尽可能简单,就像@YuvalAdam的答案中发布的那样,但我仍然不断被提示输入密码...

查看paramiko(fabric用于ssh的库)日志,我发现了以下行:

不兼容的ssh对等体(没有可接受的kex算法)

我使用以下命令更新了paramiko

sudo pip install paramiko --upgrade

现在它正在工作。


2

对于我在py3.7,fabric2.5.0和paramiko 2.7.1上都无法解决的问题,这些答案都不起作用。

然而,在文档中使用PKey属性确实可行:http://docs.fabfile.org/en/2.5/concepts/authentication.html#private-key-objects

from paramiko import RSAKey
ctx.connect_kwargs.pkey = RSAKey.from_private_key_file('path_to_your_aws_key')
with Connection(ctx.host, user, connect_kwargs=ctx.connect_kwargs) as conn:
    //etc.... 

1
如上所述,Fabric将在某种程度上支持.ssh/config文件设置,但是使用pem文件连接ec2似乎存在问题。也就是说,一个正确设置的.ssh/config文件在命令行中通过“ssh servername”可以工作,但在env.host=['servername']时在“fab sometask”中无法工作。
通过在我的fabfile.py中指定env.key_filename='keyfile'并复制已经存在于我的.ssh/config中的IdentityFile条目来解决了这个问题。
这可能是Fabric或paramiko的问题,在我的情况下是Fabric 1.5.3和Paramiko 1.9.0。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接