解决 Ansible Sudo 密码缺失问题

AnsibleBeginner
立即练习

介绍

Ansible 是一个强大的自动化工具,它有助于管理和配置服务器,而无需手动干预。然而,许多 Ansible 任务需要提升权限才能正确执行。当运行需要管理员权限的命令时,Ansible 使用 sudo 机制,这可能会提示输入密码。

在这个实验(Lab)中,你将学习如何在 Ansible playbook 中正确配置 sudo 密码设置,了解常见的 sudo 相关问题,并实施最佳实践,以确保你的自动化在具有必要权限的情况下顺利运行。

安装 Ansible 并创建基本 Playbook

在第一步中,我们将安装 Ansible 并创建一个需要 sudo 权限的简单 playbook。这将帮助我们了解使用提升权限运行 Ansible 任务的基本要求。

安装 Ansible

让我们从在系统上安装 Ansible 开始。打开一个终端并运行以下命令:

sudo apt update
sudo apt install -y ansible

安装完成后,验证 Ansible 是否已正确安装:

ansible --version

你应该看到类似这样的输出,显示 Ansible 的版本和配置信息:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (main, Ubuntu, linux/x86_64)
  jinja version = 3.0.3
  libyaml = True

创建一个基本 Ansible Playbook

现在,让我们创建一个需要 sudo 权限的简单 Ansible playbook。此 playbook 将在本地系统上安装 htop 包。

为你的 Ansible 项目创建一个新目录:

mkdir -p ~/project/ansible-sudo-lab
cd ~/project/ansible-sudo-lab

接下来,创建定义 Ansible 将要管理的 hosts 的 inventory 文件。对于这个实验(Lab),我们将使用 localhost:

echo "localhost ansible_connection=local" > inventory

现在,创建一个需要 sudo 权限的基本 playbook。打开 VSCode 编辑器并创建一个名为 basic_playbook.yml 的新文件:

  1. 单击 WebIDE 菜单中的“File”
  2. 选择“New File”
  3. 复制并粘贴以下内容:
---
- name: Basic sudo operation
  hosts: localhost
  become: true ## This enables sudo

  tasks:
    - name: Install htop
      apt:
        name: htop
        state: present
        update_cache: yes
  1. 将文件保存为 ~/project/ansible-sudo-lab/basic_playbook.yml

此 playbook 具有 become: true 指令,该指令告诉 Ansible 使用 sudo 来运行任务。任务本身尝试使用 apt 模块安装 htop 包。

运行 Playbook

现在,让我们运行我们的 playbook 并观察会发生什么:

cd ~/project/ansible-sudo-lab
ansible-playbook -i inventory basic_playbook.yml

由于 labex 用户具有无密码 sudo 访问权限,因此 playbook 应该成功运行,而不会提示输入密码。你应该看到类似这样的输出:

PLAY [Basic sudo operation] ******************************************

TASK [Gathering Facts] **********************************************
ok: [localhost]

TASK [Install htop] ************************************************
ok: [localhost]

PLAY RECAP *********************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Playbook 运行成功,因为我们当前的用户 (labex) 已经配置了无密码 sudo 访问权限。在接下来的步骤中,我们将探讨如何处理需要 sudo 密码的场景。

理解 Ansible 中的 Sudo 密码配置

在上一步中,我们创建了一个基本 playbook,它使用 sudo 权限而无需密码。然而,在许多实际场景中,你需要提供 sudo 密码才能执行特权命令。让我们探讨如何在 Ansible 中处理 sudo 密码。

Ansible 如何处理 Sudo 密码

当 Ansible 需要在远程系统上使用提升的权限运行命令时,它使用 become 功能。默认情况下,Ansible 使用 sudo 命令进行权限提升,但你可以将其配置为使用其他方法,如 supbrunpfexec

如果运行 Ansible 的用户需要密码才能使用 sudo,Ansible 需要知道这个密码。有几种方法可以向 Ansible 提供 sudo 密码:

  1. 命令行选项:-K--ask-become-pass
  2. Playbook 变量:become_password
  3. 配置文件:ansible.cfg
  4. Ansible Vault:用于安全地存储密码

创建一个需要 Sudo 密码的测试用户

为了演示如何处理 sudo 密码,让我们创建一个测试用户,该用户需要密码才能进行 sudo 操作:

sudo adduser ansible_test

当提示时,输入密码 ansible123 并完成用户创建过程。

接下来,让我们给这个用户 sudo 权限,但需要密码:

echo "ansible_test ALL=(ALL) ALL" | sudo tee /etc/sudoers.d/ansible_test

此配置允许 ansible_test 用户使用 sudo,但每次都需要用户的密码。

创建一个带有 Sudo 密码处理的 Playbook

现在,让我们创建一个 playbook,演示如何处理 sudo 密码。在 WebIDE 中创建一个名为 sudo_password_playbook.yml 的新文件:

---
- name: Playbook with sudo password handling
  hosts: localhost
  become: true
  ## We'll provide the become_password when running the playbook

  tasks:
    - name: Get current user
      command: whoami
      register: current_user
      become: false ## This task doesn't need sudo

    - name: Print current user
      debug:
        msg: "Current user is {{ current_user.stdout }}"
      become: false ## This task doesn't need sudo

    - name: Run a command with sudo
      command: apt update
      register: sudo_output

    - name: Print sudo command result
      debug:
        msg: "Command ran with sudo: {{ sudo_output.rc == 0 }}"

将此文件保存为 ~/project/ansible-sudo-lab/sudo_password_playbook.yml

运行带有密码输入的 Playbook

当你希望以需要 sudo 密码的用户身份运行 playbook 时,你可以使用 -K(或 --ask-become-pass)选项来提示输入密码:

ansible-playbook -i inventory sudo_password_playbook.yml -K

由于我们以具有无密码 sudo 的 labex 用户身份运行,因此实际上不会提示你输入密码。但是,在未配置无密码 sudo 的生产环境中,Ansible 会提示你输入 sudo 密码。

为了使用我们的测试用户模拟此场景,你可以运行以下命令(尽管由于缺少 SSH 设置,它在此实验环境中无法完全工作):

ansible-playbook -i inventory sudo_password_playbook.yml -u ansible_test -K

当提示输入 BECOME 密码时,你将输入 ansible123

在 Ansible 变量中指定 Sudo 密码

除了交互式输入密码之外,你还可以在运行 playbook 时将 sudo 密码作为变量提供:

ansible-playbook -i inventory sudo_password_playbook.yml -e "ansible_become_password=ansible123"

这种方法对于无法进行交互式输入的自动化脚本很有用。但是,它会在命令行历史记录中暴露密码,这是一种安全风险。在生产环境中,你应该使用 Ansible Vault 来安全地存储敏感信息。

使用 Ansible Vault 进行安全密码管理

在上一步中,我们探讨了向 Ansible playbooks 提供 sudo 密码的不同方法。然而,将密码存储在纯文本文件中或在命令行中传递它们是不安全的。在这一步中,我们将学习如何使用 Ansible Vault 来安全地管理敏感信息,例如 sudo 密码。

什么是 Ansible Vault?

Ansible Vault 是一项功能,允许你加密敏感数据,例如密码、API 密钥或证书。加密后的文件可以安全地存储在版本控制系统中,而不会暴露敏感信息。Ansible 可以在 playbook 执行期间自动解密这些文件。

创建一个加密的 Vault 文件

让我们创建一个加密文件来存储我们的 sudo 密码:

cd ~/project/ansible-sudo-lab
ansible-vault create vault.yml

系统将提示你创建一个新的 vault 密码。输入 vaultpassword123 并确认它。

设置 vault 密码后,将打开一个编辑器。在编辑器中输入以下内容:

---
vault_sudo_password: ansible123

保存文件并退出编辑器。

现在,如果你尝试查看 vault 文件的内容,你将看到它已被加密:

cat vault.yml

你应该看到类似这样的输出:

$ANSIBLE_VAULT;1.1;AES256
32623438613466396238613731623338376461653866353031313632316237613561393639613131
3562626166616332386265373761653835356134613561380a363761333362323238663136633439
32343032333832313562353261333530666639643239303436643363393630643639316232303564
3962356162356361370a313038333432353162333462323035323262396233333039326535356662
31363539613432656362326565613232336535393232653939323466323131393362

在 Playbook 中使用 Vault 变量

现在,让我们创建一个使用加密的 sudo 密码的 playbook。创建一个名为 secure_sudo_playbook.yml 的新文件:

---
- name: Playbook with secure sudo password
  hosts: localhost
  become: true
  become_password: "{{ vault_sudo_password }}"
  vars_files:
    - vault.yml

  tasks:
    - name: Get sudo user
      command: whoami
      register: sudo_user

    - name: Print sudo user
      debug:
        msg: "Running as {{ sudo_user.stdout }}"

    - name: Check sudo access
      command: apt update
      register: apt_result
      failed_when: false

    - name: Print result
      debug:
        msg: "Sudo access successful: {{ apt_result.rc == 0 }}"

将此文件保存为 ~/project/ansible-sudo-lab/secure_sudo_playbook.yml

运行带有 Vault 的 Playbook

当你运行包含加密 vault 文件的 playbook 时,你需要提供 vault 密码。有几种方法可以做到这一点:

  1. 使用 --ask-vault-pass 选项:
ansible-playbook -i inventory secure_sudo_playbook.yml --ask-vault-pass

当提示时,输入 vault 密码:vaultpassword123

  1. 使用 vault 密码文件:

首先,创建一个包含 vault 密码的文件:

echo "vaultpassword123" > vault_password_file
chmod 600 vault_password_file

然后使用密码文件运行 playbook:

ansible-playbook -i inventory secure_sudo_playbook.yml --vault-password-file vault_password_file

你应该看到类似这样的输出:

PLAY [Playbook with secure sudo password] ***************************

TASK [Gathering Facts] **********************************************
ok: [localhost]

TASK [Get sudo user] ***********************************************
changed: [localhost]

TASK [Print sudo user] *********************************************
ok: [localhost] => {
    "msg": "Running as root"
}

TASK [Check sudo access] *******************************************
changed: [localhost]

TASK [Print result] ************************************************
ok: [localhost] => {
    "msg": "Sudo access successful: True"
}

PLAY RECAP *********************************************************
localhost                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Sudo 密码管理的最佳实践

以下是管理 Ansible 中 sudo 密码时要遵循的一些最佳实践:

  1. 始终使用 Ansible Vault 加密敏感信息
  2. 切勿将 vault 密码存储在版本控制中
  3. 使用安全的方法来分发 vault 密码(例如,密码管理器)
  4. 考虑为不同的环境(开发、暂存、生产)使用 vault ID
  5. 定期轮换 vault 密码

在生产环境中,你可能还考虑使用 HashiCorp Vault 或 AWS Secrets Manager 等工具来实现更安全的密钥管理。

解决常见的 Sudo 密码问题

即使配置正确,你仍然可能在 Ansible 中遇到 sudo 密码问题。在这一步中,我们将探讨常见问题及其解决方案。

常见的 Sudo 密码问题

以下是使用 sudo 与 Ansible 时可能遇到的一些常见问题:

  1. 缺少 sudo 密码:Ansible 找不到 sudo 密码来执行特权命令。
  2. 不正确的 sudo 密码:提供的 sudo 密码不正确。
  3. Sudo 配置问题:目标用户没有正确的 sudo 权限。
  4. Sudo 需要 TTY:某些系统需要分配 TTY 用于 sudo 命令。

让我们探讨一下这些问题及其解决方案。

创建一个用于测试的问题环境

为了更好地理解这些问题,让我们创建一个需要 TTY 的 sudo 场景。编辑我们测试用户的 sudoers 文件:

sudo cp /etc/sudoers.d/ansible_test /etc/sudoers.d/ansible_test.bak
echo 'Defaults:ansible_test requiretty' | sudo tee -a /etc/sudoers.d/ansible_test

此配置使 ansible_test 用户运行 sudo 命令时需要 TTY,这可能会导致 Ansible 出现问题。

创建一个故障排除 Playbook

创建一个名为 troubleshoot_sudo.yml 的新 playbook,其中包含一些常见的 sudo 故障排除技术:

---
- name: Troubleshoot sudo issues
  hosts: localhost
  become: true
  become_method: sudo
  ## We'll provide the become_password when running the playbook

  tasks:
    - name: Check sudo version
      command: sudo --version
      register: sudo_version
      become: false

    - name: Print sudo version
      debug:
        msg: "{{ sudo_version.stdout_lines[0] }}"
      become: false

    - name: Check sudo configuration
      command: sudo -l
      register: sudo_config
      become: false
      failed_when: false

    - name: Print sudo configuration
      debug:
        msg: "{{ sudo_config.stdout_lines }}"
      become: false
      when: sudo_config.rc == 0

    - name: Test sudo command with pty
      command: apt update
      register: sudo_test
      failed_when: false
      vars:
        ansible_become_flags: "-H"

    - name: Print sudo test result
      debug:
        msg: "Sudo command {{ 'succeeded' if sudo_test.rc == 0 else 'failed' }}"

将此文件保存为 ~/project/ansible-sudo-lab/troubleshoot_sudo.yml

运行故障排除 Playbook

运行故障排除 playbook:

ansible-playbook -i inventory troubleshoot_sudo.yml -K

由于我们以具有无密码 sudo 的 labex 用户身份运行,因此 playbook 应该成功执行。

常见的 Sudo 密码问题解决方案

以下是常见 sudo 密码问题的解决方案:

1. 缺少 sudo 密码

如果 Ansible 失败并显示类似“缺少 sudo 密码”的消息,你可以:

  • 使用 -K 选项提示输入 sudo 密码
  • 在你的 inventory 或 playbook 中设置 ansible_become_password 变量
  • 使用 Ansible Vault 安全地存储和提供 sudo 密码

2. 不正确的 sudo 密码

如果 sudo 密码不正确:

  • 仔细检查你提供的密码
  • 验证用户的密码是否已过期或已更改
  • 检查目标系统上的 sudo 配置是否已更改

3. Sudo 配置问题

如果用户没有正确的 sudo 权限:

  • 检查目标系统上的 sudoers 文件
  • 验证用户是否在正确的组中
  • 使用 sudo -l 检查用户的 sudo 权限

4. Sudo 需要 TTY

如果 sudo 需要 TTY:

  • ansible_become_flags: "-H" 添加到你的 playbook 或 inventory
  • 修改 sudoers 文件以删除 requiretty 选项
  • 在你的任务中使用 pty: true 选项

恢复原始的 Sudo 配置

让我们恢复我们测试用户的原始 sudo 配置:

sudo cp /etc/sudoers.d/ansible_test.bak /etc/sudoers.d/ansible_test
sudo rm /etc/sudoers.d/ansible_test.bak

这将删除我们之前添加的 requiretty 选项。

总结

在这个实验中,你已经学习了如何在 Ansible playbooks 中处理 sudo 密码,这是许多管理员和 DevOps 工程师面临的常见挑战。以下是你完成的总结:

  1. 你安装了 Ansible 并创建了一个使用 sudo 权限的基本 playbook
  2. 你学习了向 Ansible playbooks 提供 sudo 密码的不同方法
  3. 你使用 Ansible Vault 安全地存储和管理敏感信息
  4. 你探索了常见的 sudo 密码问题,并学习了如何进行故障排除

这些技能将帮助你创建更安全、更可靠的 Ansible playbooks,这些 playbooks 能够处理不同环境中各种 sudo 配置。

本实验的主要收获:

  • 始终使用 Ansible Vault 等安全方法来存储敏感信息
  • 了解向 Ansible 提供 sudo 密码的不同方法
  • 知道如何解决常见的 sudo 密码问题
  • 遵循 Ansible 中 sudo 密码管理的最佳实践

有了这些技能,你现在可以自信地使用 Ansible 执行需要提升权限的任务,确保你的自动化运行平稳且安全。