14

I have enabled two factor authentication for ssh using duosecurity (using this playbook https://github.com/CoffeeAndCode/ansible-duo ).

How can I use ansible to manage the server now. The SSH calls fail at gathering facts because of this. I want the person running the playbook to enter the two factor code before the playbook is run.

Disabling two factor for the deployment user is a possible solution but creates a security issue which I would I like to avoid.

4

3 回答 3

7

这是一个 hack,但您可以通过启用 2fac 的 SSH 连接来建立非 2fac Ansible SSH 连接。

概述

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

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

您必须只能为某些用户(不是全部)配置 2 因素身份验证。

有关 SSH 隧道的一些信息

在目标机器上:

  1. 创建两个用户:ansibleansible_tunnel
  2. 将您的公钥放入~/.ssh/authorized_keys两个用户
  3. 将 shell 设置ansible_tunnel/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. 设置2 因素身份验证ansible_tunnel
  6. 重启sshd

在运行 Ansible 的机器上:

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

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

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

  2. 一旦隧道启动(检查) ,netstat运行 Ansible和。ansible_ssh_user=ansibleansible_ssh_port=8022ansible_ssh_host=localhost

回顾

  • 只能ansible_tunnel从外部连接,它将使用两个因素进行身份验证
  • 建立隧道后,连接到8022本地机器上的端口与连接到远程机器上的 sshd 相同
  • 仅当通过 localhost 完成时,我们才允许ansible通过 SSH 进行连接,因此仅允许通过隧道连接

规模

由于需要为每台机器打开一个单独的隧道,这需要手动操作,因此这对于多个服务器来说不能很好地扩展。但是,如果您为服务器选择了 2 因素身份验证,则您已经愿意执行一些手动操作来连接到每个服务器,并且此解决方案只会增加一些脚本包装的开销。

[编辑添加]

奖金

为方便起见,我们可能想直接登录维护账户做一些手工工作,而不需要经过建立隧道的过程。在这种情况下,我们可以将 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
于 2015-09-27T21:26:08.663 回答
3

我可以使用 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 配置文件中添加这个(例如,~/.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。这是该方法唯一已知的缺点。

参考:

于 2020-11-03T22:26:59.237 回答
3

使用堡垒主机的解决方案

即使使用 ssh 堡垒主机,我也花了很长时间才能让它工作。如果它对其他人有帮助,这就是我想出的。它使用ControlMasterssh 配置选项,并且由于 ansible 使用常规 ssh,因此可以将其配置为使用相同的 ssh 功能并重新使用与堡垒主机的连接,而不管它与远程主机打开多少连接。我已经看到一般推荐的这些控制选项(如果您有很多主机,可能是出于性能原因),但不是在 2FA 到堡垒主机的上下文中。

使用这种方法,您不需要任何 sshd 配置更改,因此您需要AuthenticationMethods publickey,keyboard-interactive作为堡垒服务器上唯一的身份验证方法设置,并且publickey仅适用于您通过堡垒代理的所有其他服务器。由于堡垒主机是唯一接受来自 Internet 的外部连接的主机,因此它是唯一需要 2FA 的主机,而内部主机依靠代理转发进行公钥身份验证,但不使用 2FA。

在客户端上,我在顶层目录中为我的 ansible 环境创建了一个新的 ssh 配置文件,我从该目录运行 ansible(因此是 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 代理将在可配置的时间(我设置为 10m)之后关闭并删除该套接字。

一旦套接字打开,我就可以像正常一样运行 ansible 命令,例如ansible all -m ping,它们会成功。

于 2017-02-13T19:55:19.613 回答