如何使用ansible进行双因素身份验证?

时间:2014-04-16 16:56:35

标签: ssh ansible ansible-playbook two-factor-authentication

我已经使用duosecurity为ssh启用了双因素身份验证(使用此playbook https://github.com/CoffeeAndCode/ansible-duo)。

如何使用ansible立即管理服务器。由于这个原因,SSH调用在收集事实时失败。我希望运行剧本的人在播放剧本之前输入两个因子代码。

为部署用户禁用两个因素是一种可能的解决方案,但会产生一个安全问题,我希望避免这种情况。

3 个答案:

答案 0 :(得分:7)

这是一个黑客攻击,但您可以通过支持2fac的SSH连接隧道连接非2fac Ansible SSH连接。

概述

我们将设置两个用户:ansible将是Ansible将使用的用户。它应该以Ansible支持的方式进行身份验证(即,不是2fac)。此用户将受到限制,因此无法从127.0.0.1以外的任何地方进行连接,因此无法从计算机外部访问。

第二个用户ansible_tunnel将对外开放,但将通过两个因素进行身份验证,并且只允许将SSH连接隧道连接到本地计算机。

您必须只能为某些用户(并非所有用户)配置双因素身份验证。

Some info on SSH tunnels

在目标计算机上:

  1. 创建两个用户:ansibleansible_tunnel
  2. 将您的公钥放入两个用户的~/.ssh/authorized_keys
  3. ansible_tunnel的shell设置为/bin/false,或锁定用户 - 它将专门用于隧道,而不是运行命令
  4. 将以下内容添加到/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'
    
  5. ansible_tunnel
  6. 设置双因素身份验证
  7. 重新启动sshd
  8. 在运行Ansible的机器上:

    1. 在运行Ansible之前,运行以下命令(在Ansible机器上,而不是目标):

      ssh -N -L 8022:127.0.0.1:22 ansible_tunnel@<host>
      

      您将使用两个因素进行身份验证。

    2. 隧道启动后(使用netstat查看),使用ansible_ssh_user=ansibleansible_ssh_port=8022ansible_ssh_host=localhost运行Ansible。
    3. 小结

      • 只有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客户端

此配置启用所有连接的多路复用。我个人将此配置存储在`〜/ .ssh / config中:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h:%p.socket
    ControlPersist 1m

建立连接后,套接字将出现在$HOME/.ssh目录中。在断开连接后的一分钟内,此套接字仍然存在。

配置ansible

Ansible配置为重新使用本地套接字。

将此添加到您的ansible configuration file中(例如~/.ansible.cfg):

[ssh_connection]

control_path=~/.ssh/master-%%r@%%h:%%p.socket

请注意,双%代表可变替代。

用法

  1. 使用ssh常规命令(ssh user@server)连接到您的服务器,并执行2FA;
  2. 像往常一样启动您的ansible命令。

步骤2必须在ControlPersist配置中执行,或者在另一个命令中启动ansible命令时在终端中保持ssh连接。

您还可以使用ssh -O exit user@server强制关闭不需要的连接。

请注意,如果您打开第三个终端并运行ssh user@server,则不会要求您提供凭据:在1.中建立的连接将被重新使用。

缺点

如果网络状况不好

有时,当您断开连接时,套接字仍然存在。所有其他连接均挂起。您必须使用ssh -O exit user@server手动断开此连接。这是此方法唯一已知的缺点。

参考文献: