Ansible:创建一个带有sudo权限的用户

93

我接管了一个Ubuntu 14.04服务器。它有一个名为“deployer”的用户(与capistrano一起使用),因此需要sudo权限。在这种设置下,我可以登录服务器并执行以下操作:

workstation> ssh deployer@myserver
myserver>  sudo apt-get install git
myserver> exit
workstation>

我正在尝试弄清如何使用 Ansible(版本为 2.0.2.0 和 Python 2.7.3)创建一个名为“deployer”的用户,并能够使用该 ID 登录服务器,然后执行类似于“apt-get install”之类的 sudo 命令。我的 Playbook 如下:

---
- hosts: example
  become: yes
  tasks:
  - name: Update apt cache
    apt:
      update_cache: yes
      cache_valid_time: 3600

  - group: name=sudo state=present

  - name: Add deployer user and add it to sudo
    user: name=deployer
          state=present
          createhome=yes
    become: yes
    become_method: "sudo"

  - name: Set up authorized keys for the deployer user
    authorized_key: user=deployer key="{{item}}"
    with_file:
      - /home/jaygodse/.ssh/id_rsa.pub
在运行此playbook之后,我可以使用“deployer”作为用户名通过ssh登录到机器上(例如ssh deployer@myserver),但是如果我运行sudo命令,则始终要求我输入sudo密码。我知道“deployer”用户最终必须进入visudo用户文件,但我无法找出哪些神奇的Ansible咒语可以调用,以便我可以使用deployer作为用户名通过ssh登录到机器,然后运行sudo命令(例如sudo apt-get install git),而不需要提示sudo密码。我已经四处搜索,但似乎找不到将用户“deployer”添加到sudo组中而又不需要密码的Ansible playbook片段。请问如何实现?

可能是Ansible:维护sudoers列表的最佳实践的重复问题。 - techraf
3个回答

182

有时候重要的是知道该问什么。我并不知道,因为我是一名开发人员,但也承担了一些DevOps的工作。

显然,“无密码”或NOPASSWD登录是一个需要放入/etc/sudoers文件中的内容。

我问题的答案在Ansible:维护sudoers列表的最佳实践中。

我的问题的Ansible playbook代码片段看起来像这样:

- name: Make sure we have a 'wheel' group
  group:
    name: wheel
    state: present

- name: Allow 'wheel' group to have passwordless sudo
  lineinfile:
    dest: /etc/sudoers
    state: present
    regexp: '^%wheel'
    line: '%wheel ALL=(ALL) NOPASSWD: ALL'
    validate: 'visudo -cf %s'

- name: Add sudoers users to wheel group
  user:
    name=deployer
    groups=wheel
    append=yes
    state=present
    createhome=yes

- name: Set up authorized keys for the deployer user
  authorized_key: user=deployer key="{{item}}"
  with_file:
    - /home/railsdev/.ssh/id_rsa.pub

最好的部分是,这个解决方案是幂等的。它不会添加该行。

%wheel ALL=(ALL) NOPASSWD: ALL

在运行playbook的后续时间,将其添加到/etc/sudoers中。是的...我能够作为“deployer” ssh到服务器并且运行sudo命令而无需提供密码。


75
请在你的 lineinfile: 段落末尾添加如下代码:validate: 'visudo -cf %s',以便在保存之前进行验证。弄乱 sudoers 文件将永久锁定您的 sudo 访问权限。 - Simon Woodside
2
自v1.9版本开始,authorized_key模块在key参数中接受字符串形式的密钥。详见官方文档 - Tim
9
您可以在/etc/sudoers.d目录下创建/复制文件,大多数发行版都默认包含相应的配置行... - Gert van den Berg
1
顺便提一下,如果你想知道 validate 中的 %s 是什么意思,它是指应该被修改的文件的目标(dest)或路径。这里是文档 - AdamKalisz
1
从Ansible 2.3版本开始,lineinfile中的dest参数应更改为path。 - Indika K
显示剩余6条评论

23

赋予用户sudo权限的方法是将用户添加到/etc/sudoers文件中,或者将用户加入到/etc/sudoers文件中指定的组。如果想要让该用户无需输入密码即可获得sudo权限,则需要在/etc/sudoers文件中添加NOPASSWD

/etc/sudoers文件示例:

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

## Same thing without a password
%wheel  ALL=(ALL)       NOPASSWD: ALL

我们不需要操纵 /etc/sudoers 文件,而是可以在 /etc/sudoers.d/ 目录中创建一个新文件,因为该目录默认已被包含在 /etc/sudoers 中,这避免了破坏现有 sudoers 文件的可能性,同时也消除了对 /etc/sudoers 内容的依赖。

要在 Ansible 中实现以上内容,请参考以下步骤:

- name: sudo without password for wheel group
  copy:
    content: '%wheel ALL=(ALL:ALL) NOPASSWD:ALL'
    dest: /etc/sudoers.d/wheel_nopasswd
    mode: 0440

您可以将%wheel替换为其他组名,例如%sudoers或其他用户名,例如deployer


1
谢谢您的回答。我添加了validate: '/usr/sbin/visudo -cf%s'以确保语法正确,如果您打错字,它不会阻止您。 - Jack Wire

2

尽管最初的答案很有用且受欢迎,但它可以根据最新的更改进行更新。

  1. 在大多数现代发行版中没有组wheel,但sudo相当普遍
  2. 您不需要触摸(并破坏)/etc目录中的系统文件,而应该使用额外的路径,例如/etc/sudoers.d
  3. 使用true/false布尔变量以与ansible-lint兼容
  4. 我喜欢为任何类型的常规代码使用变量,这些代码可以在项目之间复制/粘贴而无需更改。

这是更新版本:

- name: Add {{ sudo_user }} user
  user:
    name: "{{ sudo_user }}"
    groups: sudo
    append: true
    state: present
    createhome: true

- name: Make sudo without password for {{ sudo_user }} user
  copy:
    dest: /etc/sudoers.d/80-ansible-sudo-user
    content: "{{ sudo_user }} ALL=(ALL) NOPASSWD:ALL"
    mode: 0440

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接