如何安全地使用每个主机的密码实现 ansible?

sup*_*cuo 118 security sudo ansible

我想使用ansible来管理一组现有的服务器。我创建了一个ansible_hosts文件,并-K使用仅针对单个主机的命令进行了成功测试(使用选项)

ansible -i ansible_hosts host1 --sudo -K # + commands ...
Run Code Online (Sandbox Code Playgroud)

我现在的问题是每个主机上的用户密码都不同,但是我在 Ansible 中找不到处理此问题的方法。

使用-K,我只被提示预先输入一个 sudo 密码,然后似乎在没有提示的情况下为所有后续主机尝试:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password
Run Code Online (Sandbox Code Playgroud)

迄今为止的研究:

  • 一个StackOverflow 问题,有一个不正确的答案(“使用-K”),作者的一个回答是“发现我需要无密码的 sudo”

  • Ansible 文档,其中说“使用无密码 sudo 使事情更容易自动化,但这不是必需的。” (强调我的)

  • 此安全 StackExchange 问题将其视为NOPASSWD必需的读取

  • 文章“可扩展和可理解的配置...”,其中说:

    “运行 sudo 可能需要输入密码,这是永远阻止 Ansible 的可靠方法。一个简单的解决方法是在目标主机上运行 visudo,并确保 Ansible 用于登录的用户不必输入密码”

  • 文章“Basic Ansible Playbooks”,其中说

    “Ansible 可以以 root 身份登录目标服务器并避免 sudo 的需要,或者让 ansible 用户在没有密码的情况下使用 sudo,但这样做的想法让我的脾脏威胁要跳出我的食道并阻塞我的气管,所以我别”

    我的想法正是如此,但是如何扩展到单个服务器之外?

  • ansible 问题 #1227,“Ansible 应该为剧本中的所有用户要求 sudo 密码”,一年前被 mpdehaan 关闭,评论为“没有看到太多的需求,我认为大多数人只从一个用户帐户或大部分时间使用密钥。”

那么......人们如何在这样的情况下使用 Ansible?设置NOPASSWD/etc/sudoers,跨主机重用密码或启用根SSH登录似乎都在安全,而大幅减少。

小智 61

你肯定已经做了你的研究......

根据我对 ansible 的所有经验,您希望完成的工作不受支持。正如您所提到的,ansible 声明它不需要无密码 sudo,您是对的,它不需要。但是我还没有看到任何在 ansible 中使用多个 sudo 密码的方法,当然也没有运行多个配置。

所以,我无法提供您正在寻找的确切解决方案,但您确实问过...

“那么……人们在这种情况下如何使用 Ansible?在 /etc/sudoers 中设置 NOPASSWD、跨主机重用密码或启用 root SSH 登录似乎都大大降低了安全性。”

我可以给你一种看法。我的用例是在支持全球 SaaS 公司的多个数据中心中的 1k 个节点,由于我们业务的性质,我必须在其中设计/实施一些非常严格的安全控制。安全始终是平衡的行为,更多的可用性与更少的安全性,如果您运行 10 台服务器或 1,000 台或 100,000 台服务器,此过程没有什么不同。

不通过密码或 ssh 密钥使用 root 登录是绝对正确的。事实上,如果服务器插入了网线,就应该完全禁用 root 登录。

再说说密码重用,在大型企业中,要求系统管理员在每个节点上设置不同的密码是否合理?对于几个节点,也许,但是如果我的管理员/工程师必须在 1000 个节点上使用不同的密码,他们就会叛变。实现这一点也几乎是不可能的,每个用户都必须在某处存储自己的密码,希望是密钥,而不是电子表格。每次您将密码放在可以以纯文本形式提取的位置时,您的安全性就会大大降低。我更希望他们记住一两个真正强大的密码,而不是每次他们需要登录或在机器上调用 sudo 时都必须查阅 keypass 文件。

因此,即使在安全的环境中,密码重用和标准化也是完全可以接受和标准化的。否则 ldap、keystone 和其他目录服务就不需要存在了。

当我们转向自动化用户时,ssh 密钥可以很好地让您进入,但您仍然需要通过 sudo。您的选择是自动化用户的标准化密码(在许多情况下是可以接受的)或如您所指出的那样启用 NOPASSWD。大多数自动化用户只执行少数命令,因此启用 NOPASSWD 是很有可能的,当然也是可取的,但仅限于预先批准的命令。我建议使用您的配置管理(在这种情况下是 ansible)来管理您的 sudoers 文件,以便您可以轻松更新无密码命令列表。

现在,一旦您开始扩展以进一步隔离风险,您就可以采取一些步骤。虽然我们有 1000 个左右的节点,但并非所有节点都是“生产”服务器,有些是测试环境,等等。并非所有管理员都可以访问生产服务器,尽管可以像在其他地方一样使用相同的 SSO 用户/密码|密钥. 但是自动化用户更安全,例如,非生产管理员可以访问的自动化工具具有无法在生产中使用的用户和凭据。如果您想在所有节点上启动 ansible,您必须分两批进行,一次用于非生产,一次用于生产。

不过,我们也使用 puppet,因为它是一个强制配置管理工具,因此对所有环境的大多数更改都会通过它推出。

显然,如果您引用的该功能请求重新打开/完成,则将完全支持您要执行的操作。尽管如此,安全还是一个风险评估和妥协的过程。如果您只有几个节点可以记住密码而无需使用便利贴,那么单独的密码会稍微安全一些。但对于我们大多数人来说,这不是一个可行的选择。

  • 但是,关于您关于限制使用“预先批准的”`sudo` 命令的建议(当我发现几乎需要`NOPASSWD` 时,我确实想到了这一点)。不幸的是,这似乎 [完全不受支持](https://groups.google.com/d/msg/ansible-project/YHtTkipp1Ts/yBw9QjZSRQYJ)——ansible 没有承诺调用 *eg* `chown` 或 `mkdir ` 直接编译二进制文件,并且需要能够`sudo /bin/sh` 才能使大多数模块工作。 (17认同)

小智 39

从 Ansible 1.5 开始,可以对 host_vars 和其他变量使用加密的保管库。这至少使您能够安全地存储每个主机(或每个组)的ansible_sudo_pass变量。不幸的是,--ask-vault-pass每次 ansible 调用只会提示输入一个保险库密码,因此您仍然被限制为您将一起使用的所有主机的单个保险库密码。

尽管如此,对于某些用途,这可能比在多个主机上使用单个 sudo 密码有所改进,因为无法访问加密的 host_vars 的攻击者仍然需要为他或她攻击的每台机器(或机器组)提供单独的 sudo 密码。

  • `ansible_sudo_pass` 选项似乎也是新的——而且似乎满足了我的要求。单个保管库密码也非常适合我的目的。谢谢! (3认同)

小智 26

在 Ansible 1.5 中,可以使用以下命令设置ansible_sudo_pass变量lookup('password', …)

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"
Run Code Online (Sandbox Code Playgroud)

我发现这比使用文件更方便host_vars/,原因如下:

  • 我实际上with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" 用于为部署远程用户提供密码(然后需要sudo),因此它们已经存在于文件中(尽管在生成散列值时执行这些纯文本查找会丢失文件中存储的盐值) .

  • 这仅保留文件中的密码(没有ansible_sudo_pass:已知的明文),以提高加密安全性。更重要的是,这意味着您没有加密所有其他特定于主机的变量,因此可以在没有保管库密码的情况下读取它们。

  • 将密码放在单独的目录中可以更轻松地将文件置于源代码控制之外,或者使用git-crypt 之类的工具以加密形式存储它们(您可以将其用于早期缺乏保险库功能的 Ansible)。我使用 git-crypt 并且因为我只在加密的文件系统上以解密的形式签出存储库,所以我不打扰保管库,因此不需要输入保管库密码。(同时使用两者当然会更安全。)

您还可以将查找功能与ansible_ssh_pass一起使用;对于没有ansible_sudo_pass 的早期版本的 Ansible,这甚至可能是可能的。

  • 我*终于*开始尝试这个(谢谢!),但不知道没有`git-crypt`它会如何工作;据我所知。似乎 Ansible [尚无支持](https://github.com/ansible/ansible/issues/7298) 在加密保险库上使用`lookup`。[`password` 模块文档](http://docs.ansible.com/ansible/playbooks_lookups.html#id4) 说有一些尚未公开的加密存储支持,但我还没有找到详细信息。有什么线索吗? (2认同)

fqx*_*qxp 23

使用pass是一种为 ansible 提供 sudo 密码的简单方法。pass 为每个文件存储一个密码,这使得通过 git 或其他方法共享密码变得容易。它也是安全的(使用 GnuPG),如果您使用 gpg-agent,它可以让您使用 ansible,而无需在每次使用时输入密码。

要将作为servers/foo服务器存储的密码提供foo给 ansible,请在清单文件中使用它,如下所示:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"
Run Code Online (Sandbox Code Playgroud)

鉴于您之前解锁了 gpg-agent 的密钥,这将运行 ansible,无需输入任何密码。


更新: Ansible 现在通过passwordstore 插件内置了这个功能。相当于上面的将是:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('passwordstore', 'servers/foo') }}"
Run Code Online (Sandbox Code Playgroud)

如果密码尚不存在,甚至可以创建密码,这非常有用。