我已经使用duosecurity为ssh启用了双因素身份验证(使用此playbook https://github.com/CoffeeAndCode/ansible-duo)。
如何使用ansible立即管理服务器。由于这个原因,SSH调用在收集事实时失败。我希望运行剧本的人在播放剧本之前输入两个因子代码。
为部署用户禁用两个因素是一种可能的解决方案,但会产生一个安全问题,我希望避免这种情况。
答案 0 :(得分:7)
这是一个黑客攻击,但您可以通过支持2fac的SSH连接隧道连接非2fac Ansible SSH连接。
我们将设置两个用户:ansible
将是Ansible将使用的用户。它应该以Ansible支持的方式进行身份验证(即,不是2fac)。此用户将受到限制,因此无法从127.0.0.1
以外的任何地方进行连接,因此无法从计算机外部访问。
第二个用户ansible_tunnel
将对外开放,但将通过两个因素进行身份验证,并且只允许将SSH连接隧道连接到本地计算机。
您必须只能为某些用户(并非所有用户)配置双因素身份验证。
ansible
和ansible_tunnel
~/.ssh/authorized_keys
ansible_tunnel
的shell设置为/bin/false
,或锁定用户 - 它将专门用于隧道,而不是运行命令将以下内容添加到/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
在运行Ansible之前,运行以下命令(在Ansible机器上,而不是目标):
ssh -N -L 8022:127.0.0.1:22 ansible_tunnel@<host>
您将使用两个因素进行身份验证。
netstat
查看),使用ansible_ssh_user=ansible
,ansible_ssh_port=8022
和ansible_ssh_host=localhost
运行Ansible。ansible_tunnel
可以从外部连接,并且将使用两个因素进行身份验证8022
与连接到远程计算机上的sshd相同ansible
仅在通过本地主机完成时通过SSH连接,因此只允许通过隧道连接的连接由于需要为每台计算机打开一个单独的隧道,因此需要手动操作,因此无法很好地扩展多台服务器。但是,如果您为服务器选择了双因素身份验证,那么您已经愿意采取一些手动操作来连接到每个服务器,而这个解决方案只会增加一些脚本包装的开销。
[已加入编辑]
为方便起见,我们可能希望直接登录维护帐户进行一些手动操作,而无需完成设置隧道的过程。在这种情况下,我们可以将SSH配置为需要2fac身份验证,同时保持无需2fac通过隧道连接的能力:
# 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
答案 1 :(得分:3)
使用堡垒主机的解决方案
即使使用ssh堡垒主机,我也花了很长时间才开始工作。万一它可以帮助其他人,这就是我想出的。它使用ControlMaster
ssh配置选项,因为ansible使用常规ssh,它可以配置为使用相同的ssh功能并重新使用与堡垒主机的连接,而不管它向远程主机打开多少连接。我已经看到了一般推荐的这些控制选项(大概是出于性能原因,如果你有很多主机)但不是在2FA到堡垒主机的情况下。
使用这种方法,您不需要任何sshd配置更改,因此您希望AuthenticationMethods publickey,keyboard-interactive
作为堡垒服务器上唯一的身份验证方法设置,而publickey
仅适用于所有您通过堡垒代理的其他服务器。由于堡垒主机是唯一接受来自互联网的外部连接的主机,因此它是唯一需要2FA的主机,内部主机依靠代理转发进行公钥认证,但不使用2FA。
在客户端上,我在顶级目录中为我的ansible环境创建了一个新的ssh配置文件,该目录是我运行的(所谓的ansible.cfg兄弟),名为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连接。
这有点脆弱,我只能在这个目录中运行我的ssh或ansible命令,因为ProxyCommand
将本地路径传递给此配置文件。不幸的是,我不认为有一个ssh变量映射到当前正在使用的配置文件,因此我可以自动将相同的配置文件传递给ProxyCommand。根据您的环境,最好使用绝对路径。
一个问题是它使得运行ansible变得更加复杂。不幸的是,从我所知的情况来看,ansible对2FA没有任何支持。因此,如果您没有与堡垒的现有ssh连接,ansible将为其连接的每个私人服务器打印一次Verification code:
,但它实际上并没有收听输入,所以无论如何你做连接会失败。
所以我先运行:ssh -F ssh.config bastion-persistent-connection
这将在~/.ssh/ansible-*
中创建套接字文件,并且本地ssh代理将关闭&amp;在可配置的时间(我设置为10米)之后移除该套接字。
套接字打开后,我可以像正常一样运行ansible命令,例如ansible all -m ping
他们成功了。
答案 2 :(得分:0)
我可以使用ssh和ansible的ControlMaster
功能将ansible与ssh和2FA一起使用。
我的本地ssh客户端配置为转储ControlPath
套接字以进行多路复用连接。 Ansible配置为使用相同的套接字。
此配置启用所有连接的多路复用。我个人将此配置存储在`〜/ .ssh / config中:
Host *
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p.socket
ControlPersist 1m
建立连接后,套接字将出现在$HOME/.ssh
目录中。在断开连接后的一分钟内,此套接字仍然存在。
Ansible配置为重新使用本地套接字。
将此添加到您的ansible configuration file中(例如~/.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