我已经使用DuoSecurity为ssh启用了双重身份验证(使用此playbook:https://github.com/CoffeeAndCode/ansible-duo)。
现在如何使用Ansible来管理服务器。由于这个原因,SSH调用在收集信息时失败。我希望运行playbook的人在运行之前输入双重身份验证代码。
禁用部署用户的两步验证是一种可能的解决方案,但这会创建一个安全问题,我想要避免。
我已经使用DuoSecurity为ssh启用了双重身份验证(使用此playbook:https://github.com/CoffeeAndCode/ansible-duo)。
现在如何使用Ansible来管理服务器。由于这个原因,SSH调用在收集信息时失败。我希望运行playbook的人在运行之前输入双重身份验证代码。
禁用部署用户的两步验证是一种可能的解决方案,但这会创建一个安全问题,我想要避免。
这是一种非常规的方法,但你可以通过一个启用了两步验证的SSH连接来隧道传输一个没有启用两步验证的Ansible SSH连接。
我们将设置两个用户:ansible
将是Ansible使用的用户。它应该以Ansible支持的方式进行身份验证(即不包括2步验证)。此用户将受到限制,只能从127.0.0.1
连接,因此无法从机器外部访问。
第二个用户ansible_tunnel
将向外界开放,但需要经过两步验证进行身份验证,并且只允许将SSH连接隧道传输到本地机器。
您必须能够为某些用户配置双重身份验证(而不是全部用户)。
ansible
and ansible_tunnel
~/.ssh/authorized_keys
of both usersansible_tunnel
to /bin/false
, or lock the user - it will be used for tunneling exclusively, not running commandsAdd the following to /etc/ssh/sshd_config
:
AllowTcpForwarding no
AllowUsers ansible@127.0.0.1 ansible_tunnel
Match User ansible_tunnel
AllowTcpForwarding yes
PermitOpen 127.0.0.1:22
ForceCommand echo 'This account can only be used for tunneling SSH sessions'
ansible_tunnel
Before running Ansible, run the following (on the Ansible machine, not the target):
ssh -N -L 8022:127.0.0.1:22 ansible_tunnel@<host>
You will be authenticated using two factors.
netstat
), run Ansible with ansible_ssh_user=ansible
, ansible_ssh_port=8022
and ansible_ssh_host=localhost
.ansible_tunnel
可以从外部连接,并且需要使用两个因素进行身份验证8022
就相当于连接远程机器上的sshdansible
通过本地主机连接SSH,因此只允许通过隧道连接对于多台服务器,这种方法不太适用,因为需要为每台机器单独打开一个隧道,这需要手动操作。但是,如果您已经为服务器选择了双因素身份验证,那么您已经愿意为连接到每台服务器执行一些手动操作,而这种解决方案只会增加一些脚本封装的开销。
[编辑以添加]
为了方便起见,我们可能想直接登录维护帐户以执行一些手动工作,而不必经过设置隧道的过程。在这种情况下,我们可以配置SSH要求进行双因素身份验证,同时保持通过隧道连接而无需进行双因素身份验证的能力:
# All users must authenticate using two factors
AuthenticationMethods publickey,keyboard-interactive
# Allow both maintenance user and tunnel user with no restrictions
AllowUsers ansible ansible_tunnel
# The maintenance user is allowed to authenticate using a single factor only
# when connecting from a local address - it should be impossible to connect to
# this user using a single factor from the outside (the only way to do that is
# having an existing access to the machine, or use the two-factor tunnel)
Match User ansible Address 127.0.0.1
AuthenticationMethods publickey
我可以使用ssh和ansible的ControlMaster
功能以及2FA。
我的本地ssh客户端配置了一个ControlPath
套接字以进行多路连接复用。Ansible被配置为使用相同的套接字。
此配置可为所有连接启用多路复用。我个人将此配置存储在`~/.ssh/config`中:
Host *
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p.socket
ControlPersist 1m
当连接建立时,一个套接字将出现在$HOME/.ssh
目录中。该套接字会在断开连接后持续一分钟。
Ansible被配置为重复使用本地套接字。
在您的ansible配置文件(例如~/.ansible.cfg
)中添加以下内容:
[ssh_connection]
control_path=~/.ssh/master-%%r@%%h:%%p.socket
%
符号。
ssh user@server
),然后进行2FA身份验证;步骤2必须在ControlPersist
配置中执行,或者在另一个终端中启动ansible命令时在终端中保持ssh连接。
您也可以使用ssh -O exit user@server
强制关闭不需要的连接。
请注意,如果您打开第三个终端并运行ssh user@server
,您将不会被要求提供凭据:在步骤1中建立的连接将被重复使用。
有时当您失去连接时,套接字会持久存在。每次进一步的连接都会挂起。您必须手动断开此连接,使用ssh -O exit user@server
。这是此方法已知的唯一缺点。
ANSIBLE_SSH_CONTROL_PATH
使用Bastion主机的解决方案
即使使用ssh Bastion主机,我也花了很长时间才使它正常工作。如果这对其他人有帮助,以下是我的解决方案。它使用ControlMaster
ssh配置选项,因为ansible使用普通的ssh,所以可以配置为使用相同的ssh功能并重新使用与Bastion主机的连接,无论它打开多少个连接到远程主机。我已经在一般情况下推荐使用这些控制选项(假设你有很多主机的性能原因),但在2FA到Bastion主机的情况下没有提到过。
通过这种方法,您不需要进行任何sshd配置更改,因此您需要将AuthenticationMethods publickey,keyboard-interactive
设置为位于Bastion服务器上的唯一身份验证方法设置,并且仅对您要代理访问的所有其他服务器使用publickey
。由于Bastion主机是唯一从互联网接受外部连接的主机,因此它是唯一需要2FA的主机,而内部主机依靠代理转发进行公钥身份验证,但不使用2FA。
在客户端上,我在我从中运行ansible的顶级目录(因此是ansible.cfg的同级目录)中创建了一个用于我的ansible环境的新ssh配置文件,名为ssh.config
。它包含:
Host bastion-persistent-connection
HostName <bastion host>
ForwardAgent yes
IdentityFile ~/.ssh/my-key
ControlMaster auto
ControlPath ~/.ssh/ansible-%r@%h:%p
ControlPersist 10m
Host 10.0.*.*
ProxyCommand ssh -W %h:%p bastion-persistent-connection -F ./ssh.config
IdentityFile ~/.ssh/my-key
然后在ansible.cfg文件中,我有以下内容:
[ssh_connection]
ssh_args = -F ./ssh.config
在本例中,我的私有子网为10.0.0.0/16,与上面的主机通配符选项相对应。跳板代理所有连接到该子网上的服务器的ssh连接。
这有点脆弱,因为由于ProxyCommand
传递了此配置文件的本地路径,所以我只能在此目录中运行ssh或ansible命令。不幸的是,我认为SSH没有映射到当前使用的配置文件的变量,因此我无法自动将相同的配置文件传递给ProxyCommand。根据您的环境,最好使用绝对路径。
唯一的问题是它使得运行ansible更加复杂。不幸的是,据我所知,ansible完全不支持2FA。因此,如果您没有与跳板之间的现有ssh连接,则ansible将为每个私有服务器打印一个Verification code:
,但它实际上并未监听输入,因此无论您做什么都将无法建立连接。
所以我首先运行:ssh -F ssh.config bastion-persistent-connection
这会在~/.ssh/ansible-*
中创建套接字文件,本地的ssh代理将在可配置时间后关闭并删除该套接字(我设置为10m)。
一旦套接字打开,我就可以像平常一样运行ansible命令,例如:ansible all -m ping
,它们会成功执行。
ControlPath ~/.ansible/cp/ansible-ssh-%h-%p-%r
,这对应于 Ansible 的默认 control_path
。http://docs.ansible.com/ansible/intro_configuration.html#control-path - Aidan Feldman