为Ansible指定sudo密码


224

如何以非交互方式为Ansible指定sudo密码?

我正在运行像这样的Ansible剧本:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username --ask-sudo-pass

但我想这样运行:

$ ansible-playbook playbook.yml -i inventory.ini \
    --user=username` **--sudo-pass=12345**

有办法吗?我想尽可能地使我的项目部署自动化。


Answers:


169

您可以通过在命令行上传递变量--extra-vars "name=value"。Sudo密码变量为ansible_sudo_pass。因此,您的命令如下所示:

ansible-playbook playbook.yml -i inventory.ini --user=username \
                              --extra-vars "ansible_sudo_pass=yourPassword"

2017年更新:Ansible 2.2.1.0现在使用var ansible_become_pass。似乎都可以。


7
从安全角度来看,如果添加以下内容,则是最佳答案:history -c执行yml之后。
kiltek '16

12
@kiltek:在行的开头(以bash开头)添加多余的空格,这*不会*将行写入.bash_history
ccpizza

44
在命令行上传递密码不是一个好习惯。执行命令时,任何人都可以在进程列表中查看密码...
Pavel Chernikov

22
仍然,只是不要这样做。--ask-sudo-pass
JasonG'9

2
@scrutari在某些情况下是完全有效的:例如:从世界知名的默认初始密码更改为注入用户的公共ssh密钥...考虑重新映像系统的初始配置。
Ceredig

236

该文档 强烈建议不要在明文设定sudo的密码,而是使用--ask-sudo-pass命令行上运行时ansible-playbook


2016年更新:

Ansible 2.0(当不是100%时)标记--ask-sudo-pass为已弃用。现在,文档建议--ask-become-pass改用,同时还用替换sudo整个剧本的使用become


16
是的,我明白了为什么建议这样做。但是,当我们将Ansible用作部署过程的一部分时,什么是更好的自动化方法?在部署过程中停止并要求用户输入sudo密码不是很方便。
Slava Fomin II

9
注意--ask-sudo-pass可以缩写为-K,但是,据我所知,无法处理使用不同密码在多台服务器上运行的剧本(它只询问您一次),因此我认为没有密码须藤是要走的路。
威廉·特雷尔

1
似乎不起作用。但是下一个建议(“某些主机ansible_sudo_pass ='foobar'”)可以
nadavkav '16

--ask-sudo-pass在1.9版中已被弃用
克里斯·贝蒂

如果您有答案,我很乐意使用源链接更新答案。
deefour

106

可能是最好的方法-假设您不能使用scottod提供的NOPASSWD解决方案,那就是将Mircea Vutcovici的解决方案与Ansible Vault结合使用。

例如,您可能有一个类似这样的剧本:

- hosts: all

  vars_files:
    - secret

  tasks:
    - name: Do something as sudo
      service: name=nginx state=restarted
      sudo: yes

这里我们包含一个名为的文件secret,其中将包含我们的sudo密码。

我们将使用ansible-vault创建此文件的加密版本:

ansible-vault create secret

这将要求您输入密码,然后打开默认编辑器以编辑文件。你可以把你ansible_sudo_pass放在这里。

例如secret

ansible_sudo_pass: mysudopassword

保存并退出,现在您有了一个加密secret文件,当您运行剧本时Ansible可以解密该文件。注意:您可以使用编辑文件ansible-vault edit secret(并输入创建文件时使用的密码)

难题的最后一部分是为Ansible提供一个--vault-password-file它将用于解密您的secret文件的功能。

创建一个名为的文件,vault.txt并在其中放置创建secret文件时使用的密码。密码应该是存储在文件中的一行字符串。

来自Ansible Docs:

..确保对该文件的许可权使其他人无法访问您的密钥,也不能将您的密钥添加到源代码管理中

最后:您现在可以使用类似

ansible-playbook playbook.yml -u someuser -i hosts --sudo --vault-password-file=vault.txt 

以上假设以下目录布局:

.
|_ playbook.yml
|_ secret
|_ hosts
|_ vault.txt

您可以在这里阅读有关Ansible Vault的更多信息:https ://docs.ansible.com/playbooks_vault.html


5
注意:从ansible 1.9开始,您似乎无法再使用ansible_sudo_pass(或ansible_become_pass)变量:“致命:[...] =>缺少密码”
toast38coza 2015年

6
我在生产中使用此解决方案,jenkins将保险库密码作为混淆的环境变量存储,在运行时将其写入临时文件中,然后继续调用ansible。
simone cittadini '16

6
或更简单地说:ansible-vault create group_vars/all/ansible.yml并在ansible_sudo_pass: yourpassword其中添加。无需更改剧本或广告资源
博克·沃斯提格(Bouke Versteegh)

1
尝试了这个,但是我得到了这个错误:fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
JohnnyQ '16

8
如果将保管库密码以纯文本格式存储在保管库旁边,那么保管库有什么用?
Erik,

44

查看代码(runner/__init__.py),我认为您可能可以在库存文件中进行设置:

[whatever]
some-host ansible_sudo_pass='foobar'

似乎在ansible.cfg配置文件中也有一些规定,但目前尚未实现(constants.py)。


7
安全配置此文件的一种好方法是将其存储在host_varsgroup_vars目录中,然后使用ansible-vault
Kyle

44

我认为Ansible不会让您按照自己的意愿在标志中指定密码。可以在配置中的某处进行设置,但这会使使用Ansible总体上不太安全,因此不建议使用。

您可以做的一件事是在目标计算机上创建一个用户,并向他们授予对所有命令或受限制的命令列表的无密码sudo特权。

如果您运行sudo visudo并输入如下所示的行,则用户“ privilegedUser”在运行类似sudo service xxxx start以下内容时不必输入密码:

%privilegedUser ALL= NOPASSWD: /usr/bin/service

7
@bschlueter,所以您认可不良做法?
斯蒂芬

1
我认为这不是一个好主意。使用--ask-sudo-pass对我来说很有意义。
kgpdeveloper

@simone cittadini我完全同意,因为这就是我要给出的答案。这是一种安全风险。
einarc '02

如果您每天使用无密码sudo部署到暂存/生产,但是要想使用这些答案来跳过必须输入本地笔记本电脑登录密码的情况,则每天每15分钟要跳过一次,因此不必担心输入安全问题。
乔纳森·哈特利

如何使用Ansible添加此行?
马赛厄斯

21

sudo的密码存储为一个叫做变量ansible_sudo_pass。您可以通过以下几种方式设置此变量:

每个主机,在清单主机文件inventory/<inventoryname>/hosts)中

[server]
10.0.0.0 ansible_sudo_pass=foobar

每个组,在您的广告资源组文件inventory/<inventoryname>/groups)中

[server:vars]
ansible_sudo_pass=foobar

每组,分组为varsgroup_vars/<groupname>/ansible.yml

ansible_sudo_pass: "foobar"

每组,已加密ansible-vault create group_vars/<groupname>/ansible.yml

ansible_sudo_pass: "foobar"


14

我当时正在撕头发,现在我找到了一种解决方案,可以满足我的需求:

每个主机1个包含sudo密码的加密文件

/ etc / ansible / hosts:

[all:vars]
ansible_ssh_connection=ssh ansible_ssh_user=myuser ansible_ssh_private_key_file=~/.ssh/id_rsa

[some_service_group]
node-0
node-1

然后为每个主机创建一个加密的var文件,如下所示:

ansible-vault create /etc/ansible/host_vars/node-0

有内容

ansible_sudo_pass: "my_sudo_pass_for_host_node-0"

您如何组织保管库密码(通过--ask-vault-pass输入)或cfg

基于此我怀疑您可以加密整个主机文件...


尽管我很难使用Vault进行加密,但对Vault来说最有意义ansible-playback。我不得不在呼叫中-e @vault/filename.ext使用Vault ansible-playbook
亚历克斯(Alex)

9

一种更精明的方法是将sudo密码存储在安全的保管库(例如LastPassKeePass)中,然后将其传递给ansible-playbook使用,-e@但是您可以使用该结构-e@<(...)在目录中运行命令,而不是对实际文件中的内容进行硬编码。子外壳程序,并将其输出(STDOUT)重定向到匿名文件描述符,从而有效地将密码提供给-e@<(..)

$ ansible-playbook -i /tmp/hosts pb.yml \
   -e@<(echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)")

上面做了几件事,让我们分解一下。

  • ansible-playbook -i /tmp/hosts pb.yml -显然是通过ansible-playbook运行一个剧本
  • $(lpass show folder1/item1 --password)"-运行LastPass CLI lpass并检索要使用的密码
  • echo "ansible_sudo_pass: ...password..." -接受字符串“ ansible_sudo_pass:”,并将其与提供的密码组合 lpass
  • -e@<(..)-将以上内容放在一起,并连接的子外壳<(...)作为ansible-playbook要使用的文件描述符。

进一步改进

如果您不想每次都键入,则可以简单地进行如下操作。首先.bashrc像这样创建一个别名:

$ cat ~/.bashrc
alias asp='echo "ansible_sudo_pass: $(lpass show folder1/item1 --password)"'

现在,您可以像这样运行您的剧本:

$ ansible-playbook -i /tmp/hosts pb.yml -e@<(asp)

参考资料


1
使用subshel​​l是一个非常聪明的主意!对于那些想知道的人,这是1Password的CLI的外观:--extra-vars @<(echo ansible_become_pass: $(op get item <item name> | jq --raw-output '.details.sections[0].fields[] | select(.t=="password").v'))
Diti

1
我喜欢这样,因为当我检查bach历史时,密码不是以明文形式显示的。同样可能的事实是,如果启用了系统审核,则该命令会在读取文件时记录下来,例如/dev/fd/63,因此通过在临时文件描述符中输入密码,就不会公开该命令。
JPvRiel

5

如果您习惯于将密码保存在纯文本文件中,则另一种选择是使用带有--extra-vars参数的JSON文件(确保从源代码管理中排除该文件):

ansible-playbook --extra-vars "@private_vars.json" playbook.yml 

从1.3开始,Ansible支持此选项


5

您可以像这样在主机文件中为您的剧本写sudo密码:

[host-group-name]
host-name:port ansible_sudo_pass='*your-sudo-password*'

5

这里曾多次建议使用Ansible Vault,但我更喜欢git-crypt来加密我的剧本中的敏感文件。如果您使用git来保存您的ansible剧本,那很容易。我用ansible保管库发现的问题是,我不可避免地最终遇到了要使用的文件的加密副本,因此必须先解密才能使用。 git-crypt提供了更好的IMO工作流程。

使用此功能,您可以将密码放在剧本中的var中,并将剧本标记为加密文件,.gitattributes如下所示:

 my_playbook.yml filter=git-crypt diff=git-crypt

您的剧本将在Github上进行透明加密。然后,您只需要在用于运行ansible的主机上安装加密密钥,或按照文档中的说明使用进行设置即可gpg

关于转发gpg密钥(例如您的ssh-agent转发SSH密钥),这里有一个很好的问答:https : //superuser.com/questions/161973/how-can-i-forward-a-gpg-key-via-ssh-agent


3

您可以使用sshpass以下实用程序,

$ sshpass -p "your pass" ansible pattern -m module -a args \
   -i inventory --ask-sudo-pass

3

使用ansible 2.4.1.0及以下版本将起作用:

[all]
17.26.131.10
17.26.131.11
17.26.131.12
17.26.131.13
17.26.131.14

[all:vars]
ansible_connection=ssh
ansible_user=per
ansible_ssh_pass=per
ansible_sudo_pass=per

只需使用以下清单运行剧本

ansible-playbook -i inventory copyTest.yml

3

我的自动化方法是使用环境变量并通过进行访问--extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'"

导出环境变量,但要避免使用bash / shell历史记录(以空格或其他方法开头)。例如:

     export ANSIBLE_BECOME_PASS='<your password>'

在将额外ansible_become_pass变量传递到的同时,查找env var ansible-playbook,例如:

ansible-playbook playbook.yml -i inventories/dev/hosts.yml -u user --extra-vars="ansible_become_pass='{{ lookup('env', 'ANSIBLE_BECOME_PASS') }}'"

好的替代答案:


2

您可以使用ansible保管库,它将密码编码到加密的保管库中。之后,您可以在剧本中使用Vault中的变量。

有关ansible Vault的一些文档:http :
//docs.ansible.com/playbooks_vault.html

我们将其用作每个环境的保管库。要编辑库,我们的命令为:
ansible-vault edit inventories/production/group_vars/all/vault

如果要调用Vault变量,则必须使用具有以下参数的ansible-playbook:
ansible-playbook -s --vault-password-file=~/.ansible_vault.password

是的,我们以纯文本格式将保管库密码存储在本地目录中,但这并不像存储每个系统的root密码那样危险。根密码位于Vault文件中,或者您可以像sudoers文件一样为您的用户/组设置密码。

我建议在服务器上使用sudoers文件。这是组管理员的示例:
%admin ALL=(ALL) NOPASSWD:ALL



1

五年之后,我可以看到这仍然是一个非常相关的主题。我仅在使用ansible工具(没有任何集中式身份验证,令牌或任何其他手段)的情况下,在某种程度上反映了leucos的答案,这是我发现的最佳答案。这假定您在所有服务器上都具有相同的用户名和相同的公用密钥。如果不这样做,那么当然需要更加具体,并在主机旁边添加相应的变量:

[all:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file=home/user/.ssh/mykey
[group]
192.168.0.50 ansible_sudo_pass='{{ myserver_sudo }}'

ansible-vault create mypasswd.yml
ansible-vault edit mypasswd.yml

加:

myserver_sudo: mysecretpassword

然后:

ansible-playbook -i inv.ini my_role.yml --ask-vault --extra-vars '@passwd.yml'

至少通过这种方式,您不必编写更多指向密码的变量。


1

上面@ toast38coza的解决方案为我工作;只是那个sudo:是的,现在Ansible中已弃用。使用变得become_user代替。

tasks:
 - name: Restart apache service
   service: name=apache2 state=restarted
   become: yes
   become_user: root

0

我们还可以在ansible中使用EXPECT BLOCK生成bash并根据您的需要对其进行自定义

- name: Run expect to INSTALL TA
  shell: |
    set timeout 100
    spawn /bin/sh -i

    expect -re "$ "
    send "sudo yum remove -y xyz\n"

    expect "$ "
    send "sudo yum localinstall -y {{ rpm_remotehost_path_for_xyz }}\n"

    expect "~]$ "
    send "\n"

    exit 0
  args:
  executable: /usr/bin/expect

0

很简单,只添加变量文件:

例:

$ vim group_vars/all

并添加以下内容:

Ansible_connection: ssh
Ansible_ssh_user: rafael
Ansible_ssh_pass: password123
Ansible_become_pass: password123

谢谢,但是我认为您的意思是ansible_become_pass而不是Ansible_become_pass。
克里希诺

0

只是一个附录,所以没有人经历我最近所做的烦恼:

AFAIK,最好的解决方案是按照以上toast38coza的常规思路进行解决。如果将您的密码文件和您的剧本静态地绑定在一起是有意义的,则使用vars_files(或include_vars)遵循其模板。如果要将它们分开,则可以在命令行上提供库内容,如下所示:

ansible-playbook --ask-vault-pass -e@<PATH_TO_VAULT_FILE> <PLAYBOOK_FILE>

回想起来,这很明显,但是这里有一些陷阱:

  1. 那个血腥的@符号。如果不进行处理,解析将以静默方式失败,并且ansible-playbook将继续进行,就好像您从来没有指定文件一样。

  2. 您必须通过命令行--extra-vars / -e或在您的YAML代码中明确导入Vault的内容。该--ask-vault-pass标志本身不执行任何操作(除了提示您输入一个可能在以后使用或可能不使用的值)。

可以包含“ @”并节省一个小时。


-3

这对我有用...用NOPASSWD创建文件/etc/sudoers.d/90-init-users文件

echo "user ALL=(ALL)       NOPASSWD:ALL" > 90-init-users

其中“用户”是您的用户名。

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.