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


我想用 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问题 一个错误的答案(“使用 -K“)和作者的一个回应说”发现我需要无密码的sudo“

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

  • 这个安全StackExchange问​​题 把它当作读取 NOPASSWD 是必须的

  • 文章 “可扩展且易于理解的配置......” 其中说:

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

  • 文章 “基本的Ansible Playbooks”,说

    “Ansible可以以root用户身份登录到目标服务器,避免使用sudo,或者让ansible用户没有密码sudo,但想到做任何一个让我的脾脏威胁到我的食道跳起来阻挡我的气管,所以我别”

    我的想法完全正确,但接下来如何扩展到单个服务器?

  • 安塞问题#1227,“Ansible应该为剧本中的所有用户索取sudo密码”,一年前由mpdehaan关闭,评论“没有看到太多的需求,我想大多数人只是在一个用户帐户或使用sudoing大部分时间都是按键。“

那么......人们如何在这样的情况下使用Ansible?设置 NOPASSWD 在 /etc/sudoers,在主机之间重用密码或启用root SSH登录都会显着降低安全性。


97
2017-12-09 11:49




您是否有使用SSH密钥的原因? - Trondh
我已经在使用SSH密钥;他们没有影响 sudo (应该仍然需要密码)。 - supervacuo
这可能不是你想要的,但在Ubuntu盒子上我仍然使用密钥,即将我的公钥放在/ root / authorized_keys中直接以root身份进入。明显的缺点是允许root登录ssh ...我也禁止通过ssh进行密码登录并运行fail2ban以增加安全性。 - senorsmile
@senorsmile感谢您的回复!你是否介意把它变成一个答案,所以我可以因为你没有阅读这个问题而投票给你? - supervacuo
即 该 ansible_ssh_password 设置仅适用于SSH密码(线索在名称中......)。我已经在使用基于密钥的SSH登录了。 - supervacuo


答案:


你当然完成了你的研究......

根据我对ansible的所有经验,您不希望得到什么。正如你所提到的,ansible声明它不需要无密码的sudo,而你是正确的,它没有。但是我还没有看到在ansible中使用多个sudo密码的任何方法,当然不需要运行多个配置。

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

“那么......人们如何在这样的情况下使用Ansible?设置   / etc / sudoers中的NOPASSWD,在主机之间重用密码或启用   root SSH登录似乎都显着降低了安全性。“

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

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

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

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

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

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

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

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


52
2017-12-30 16:53



谢谢,@ Zeb - 我曾经想过拥有数十到数千台服务器的用户会使用 NOPASSWD 无论如何,出于理智的原因(可能是由更严格的防火墙规则支持) 等等),但阅读您的用例和威胁模型的想法是很好的。 - supervacuo
但是,有一条评论是关于限制“预先批准”的建议 sudo 命令(当我发现它时确实发生过 NOPASSWD 非常需要)。不幸的是,这似乎是 完全不受支持  - ansible对呼叫没有任何承诺 例如  chown 要么 mkdir 二进制文件直接,并且需要能够 sudo /bin/sh 使大多数模块工作。 - supervacuo
我似乎记得我的一位工程师抱怨说有一段时间,这很烦人。 - Zeb


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

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


36
2018-05-10 20:32



该 ansible_sudo_pass 选项似乎也是新的 - 而且似乎做了我要求的。单个保管库密码也是我的理想选择。谢谢! - supervacuo
有没有办法避免加密 所有  host_vars 用这种方法? (Alex Dupuy指出的潜在限制) - supervacuo
@supervacuo - 为了避免加密所有主机变量,只需使用包含main.yml(未加密)和secret.yml(加密)的主机var目录 - 请参阅最后一部分 这个doc部分 它谈论“raleigh”组 - 相同的技术适用于主机变量和组变量。我经常使用它,唯一的变化是,如果某些剧本只需要一个秘密,那么完全将它存储在另一个树中并通过包含主机或var名称的路径包含它会很有用。 - RichVel
如果我已经加密了保险库中的'ansible_ssh_pass'值,那么我还需要复制'ansible_sudo_pass'值吗?有没有办法让第二个sudo_pass值重新获得第一个'ssh_pass'值? - emeraldjava


使用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" 为...提供密码 部署 远程用户(然后需要 须藤) 所以他们已经存在于文件中 (尽管进行这些明文查找会失去盐值 生成散列值时存储在文件中)。

  • 这只保留文件中的密码(没有 ansible_sudo_pass: 已知明文)对于加密安全性的某些epsilon增加。 更重要的是,这意味着您没有加密所有其他特定于主机的变量, 所以他们可以在没有保险箱密码的情况下阅读。

  • 将密码放在一个单独的目录中可以更容易地将文件保持在源代码控制之外,或者使用类似的工具 混帐隐窝 以加密形式存储它们(您可以在缺少Vault功能的早期Ansible中使用它)。 我使用git-crypt,因为我只在加密文件系统上以解密形式检出存储库,我不打扰保险库,因此不需要输入保险库密码。 (使用两者当然会更安全。)

你也可以使用 抬头 功能 ansible_ssh_pass;对于没有的早期版本的Ansible,这甚至可能实现 ansible_sudo_pass


22
2018-05-26 19:33



一世 最后 试着这个(谢谢!),但看不出它如何工作 git-crypt;据我所知。好像是Ansible 还没有支持 使用 lookup 在加密的保险库上。该 password 模块文档 说有一些尚未记录的加密存储支持,但我还没有找到细节。有什么线索吗? - supervacuo


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

提供存储为的密码 servers/foo 对于服务器 foo 要安塞,请在库存文件中使用它,如下所示:

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

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


17
2018-01-19 19:51



这么棒的解决方案 - 谢谢! - Leng


尽管如此,这是一个相当古老的主题:

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

3
2018-03-03 17:33



这看起来非常整洁,谢谢 - 我喜欢不必在两个地方存储密码的想法。目前我被困在使用KeepassX(因为GNOME密钥环似乎不太便携)但也许我可以制作 python-keepass 工作? - supervacuo
据我所知,python-keyring是对此的抽象,因此您的同事可能会使用其他操作系统。或者您将keepassx数据库存储在USB记忆棒上并且必须使用不同操作系统的工作站进行管理? - Mirko Friedenhagen
了解;我的意思是我已经必须使用KeepassX来访问非GNOME系统上的密码,因此将它们存储在 gnome-keyring 意味着保留重复的记录。仍然比使用更好 NOPASSWD虽然...... - supervacuo


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

例如

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

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

lookup('env', 'pass1') 
lookup('env', 'pass2') 

0
2017-07-21 08:57