如何使用每台主机密码安全地实施ansible?


108

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

ansible -i ansible_hosts host1 --sudo -K # + commands ...

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

使用-K,只会提示我预先输入一个sudo密码,然后似乎对所有后续主机都尝试了该密码,而不会提示:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

到目前为止的研究:

  • 一个StackOverflow问题,其中有一个错误的答案(“ use -K”)和一个作者说“发现我需要无密码的sudo”的响应

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

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

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

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

  • 文章“基本Ansible剧本”,其中说

    “ Ansible可以以root用户身份登录到目标服务器,而无需sudo,或者让ansible用户使用不带密码的sudo,但是这样做的想法使我的脾脏有可能扬起食道并阻塞我的气管,所以我别”

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

  • ansible问题#1227,“ Ansible应该要求剧本中的所有用户使用sudo密码”,该文件在一年前被mpdehaan关闭,并评论“对这个的需求还不多,我认为大多数人都只从其中一个开始学习用户帐户或大多数时间使用密钥。”

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


2
您不使用SSH密钥是有原因的吗?
Trondh

22
我已经在使用SSH密钥;它们不会影响sudo(仍然需要输入密码)。
supervacuo

1
这可能不完全是您想要的东西,但是在Ubuntu盒子上,我仍然使用密钥,即将我的公共密钥放在/ root / authorized_keys中以直接作为root进入。明显的缺点是允许通过ssh进行root登录...我也不允许通过ssh进行密码登录,并运行fail2ban以提高安全性。
senorsmile

27
@senorsmile感谢您的回复!您介意将其转为答案,以便我不赞成您阅读未回答的问题吗?
supervacuo

4
即,ansible_ssh_password设置仅适用于SSH密码(提示位于名称中...)。&我已经在使用基于密钥的SSH登录了。
supervacuo

Answers:


53

您当然已经完成了研究...

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

因此,我无法提供您正在寻找的确切解决方案,但您确实提出了...

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

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

您绝对正确,不要通过密码或ssh键使用root登录。实际上,如果服务器插入了网络电缆,则应该完全禁用root登录。

让我们谈谈密码重用,在大型企业中,要求sysadmins在每个节点上使用不同的密码是否合理?也许有几个节点,但是如果我的管理员/工程师必须在1000个节点上使用不同的密码,那么他们会发动叛变。要实现这一点几乎也是不可能的,每个用户都必须将自己的密码存储在某个地方,希望是一个密码,而不是电子表格。而且,每次将密码放在可以以纯文本格式拉出的位置时,都会大大降低安全性。我更希望他们内心知道一个或两个很强的密码,而不是每次他们需要登录或调用计算机上的sudo时都要查阅密钥文件。

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

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

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

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

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


@Zeb,谢谢,我曾想过,拥有数十万台服务器的用户还是NOPASSWD出于理智的原因而使用(可能受到更严格的防火墙规则等的支持),但是阅读您的用例和有关威胁的想法是很好的模型。
supervacuo 2013年

16
但是,对于您关于限制使用“预先批准的” sudo命令的建议,有一条评论(当我发现NOPASSWD非常需要此命令时,我确实想到了)。不幸的是,这似乎也完全不受支持 -ansible不保证直接调用eg chownmkdirbinaries,并且需要能够使sudo /bin/sh大多数模块正常工作。
supervacuo 2013年

我似乎回想起我的一位工程师曾经抱怨过这一点,这很烦人。
Zeb 2014年

36

从Ansible 1.5开始,可以对host_vars和其他变量使用加密的保管库。这至少可以使您安全地存储每个主机(或每个组)的ansible_sudo_pass变量。不幸的是,--ask-vault-pass每次可提示的调用仅提示输入一个库密码,因此对于将要一起使用的所有主机,您仍然受到一个库密码的约束。

但是,对于某些用途,这可能是对跨多个主机使用单个sudo密码的一种改进,因为无法访问加密的host_vars的攻击者仍然需要针对其攻击的每台计算机(或计算机组)使用单独的sudo密码。


3
ansible_sudo_pass选项似乎也很新-似乎可以满足我的要求。同样,单个保险库密码也是我理想的选择。谢谢!
supervacuo 2014年

有没有办法避免使用此方法加密所有内容 host_vars?(Alex Dupuy指出的潜在限制)
supervacuo 2015年

1
@supervacuo-为避免对所有主机变量进行加密,只需使用包含main.yml(未加密)和secret.yml(已加密)的主机var目录-请参阅本文档的最后一部分,其中讨论“ raleigh”组-相同的技术适用于主机变量和组变量。我经常使用它,唯一的变化是,如果某些剧本只需要一个秘密,则将其完全存储在不同的树中并通过包含主机名或var名的路径包含它会很有用。
RichVel

1
如果我已经在Vault中加密了“ ansible_ssh_pass”值,那么我还需要复制“ ansible_sudo_pass”值吗?有没有办法让第二个sudo_pass值引用第一个“ ssh_pass”值?
emeraldjava '18

可以在以下位置找到关于使用密码的很好的报道:stackoverflow.com/a/37300030/5025060
CODE-REaD

22

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

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

我发现这比使用文件更方便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,这甚至可能是可行的。


2
终于设法解决了这个(谢谢!),但是看不到没有它怎么工作git-crypt?据我所知。这似乎是Ansible 还没有支持使用lookup上的加密保管库。该password模块文档说,加密存储还存在一些尚未公开的支持,但是我还没有找到详细信息。有什么线索吗?
supervacuo

19

使用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') }}"

鉴于您之前已解锁了gpg-agent的密钥,因此无需输入任何密码即可运行ansible。


3

尽管如此,这是一个很旧的线程:

  • 我们内部使用两种不同的身份验证系统,计算机的管理是通过我团队中的本地工作站完成的。
  • vars_plugin为Ansible 写了一个(可以在https://gist.github.com/mfriedenhagen/e488235d732b7becda81上找到一个比较完整的实现),它区分了几种身份验证系统:
  • 身份验证系统的名称是特定于组的。
  • 使用的登录/ sudo用户是特定于组和管理员的。
  • 因此,我通过密码安全库中的python-keyring库将用户从管理员环境和相应的密码中拉出(我们使用Mac OS X的钥匙串,但也支持文档kwallet Gnome和_win_crypto)。
  • 我对Mac OS X钥匙串中的密码设置了权限,以通知我以下事实:命令行程序安全性要求为主机使用的每个身份验证系统访问密码,因此我运行“ ansible -s all -m ping”并得到两个提示(每个身份验证系统一个),在这里我按空格键,ansible会获取密码。

看起来很整洁,谢谢您-我喜欢不必在两个地方存储密码的想法。目前,我一直在使用KeepassX(因为GNOME密钥环似乎不太便于携带),但是也许我可以python-keepass工作?
supervacuo

据我了解,python-keyring是对此的一种抽象,因此您的同事可能会使用其他操作系统。还是将keepassx数据库存储在USB记忆棒上,并且必须从具有不同操作系统的工作站进行管理?
Mirko Friedenhagen 2015年

理解 我的意思是我已经必须使用KeepassX才能访问非GNOME系统上的密码,因此将其存储在其中gnome-keyring将意味着保留重复的记录。仍然比使用更好的方法NOPASSWD……
supervacuo 2015年

0

一种可行的方法是使用环境变量。

例如

pass1=foo pass2=bar ansible-playbook -i production servers.xml

然后在剧本中,您可以使用以下命令查找sudo密码:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.