Ansible SSH 身份验证和权限提升

在本文中,我们将重点关注两个重要的 Ansible 概念。 第一个概念是基于 SSH 密钥和基于密码的身份验证如何在 Ansible 中工作。 第二个概念是在使用临时命令和剧本时如何提升权限。

我有一个运行 Ubuntu 20.04 LTS 机器的三节点实验室设置,使用 VirtualBox 和流浪汉。 有一篇关于实验室设置的详细文章,您可以从下面的链接中阅读。

  • 在 Linux 中使用 Vagrant 和 Virtualbox 进行自动化 Ansible 实验室设置

Ansible 中基于密钥的身份验证

学习 ansible 时首先要了解的是控制器和托管节点之间的通信是如何发生的。 Ansible 用途 SSH 协议 连接到受管节点并运行任务。

每次运行 playbook 或 ad hoc 命令时,都必须提供 SSH 密码,以便 ansible 通过 SSH 对托管节点进行身份验证。

为了消除这种情况,建议创建一个 SSH 密钥对并与所有节点共享公钥,以便 ansible 可以使用该密钥对进行通信。

我创建了两个名为 first_keysecond_key 使用以下脚本进行演示。

创建一个名为 create_keypair.sh 有以下内容。

#!/usr/bin/env bash

# THIS SCRIPT WILL CREATE SSH KEY PAIR AND DISTRIBUTE ACROSS ALL NODES

read -p "Enter the name for the key : " KEY_NAME
ssh-keygen -b 2048 -t rsa -f /home/vagrant/.ssh/${KEY_NAME} -q -N ""

# LOOPING THROUGH AND DISTRIBUTING THE KEY

for val in controller managed1 managed2; do
    echo "-------------------- COPYING KEY TO ${val^^} NODE ------------------------------"
    sshpass -p 'vagrant' ssh-copy-id -f -i /home/vagrant/.ssh/${KEY_NAME}.pub -o "StrictHostKeyChecking=no" [email protected]$val
done

授予脚本执行权限并运行它。

$ chmod +x path/to/create_keypair.sh
$ ./create_keypair.sh

我已经为我的实验室设置创建了这个脚本。 您可以编辑 for 循环部分并相应地添加您的托管节点名称。

$ tree .ssh/
.ssh/
├── authorized_keys
├── first_key
├── first_key.pub
├── known_hosts
├── second_key
└── second_key.pub

当您使用默认名称(id_rsa)以外的其他名称创建密钥时,ssh 将尝试查找默认密钥名称,如果未找到,它将提示进行基于密码的身份验证。

debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/vagrant/.ssh/id_rsa
debug1: Trying private key: /home/vagrant/.ssh/id_dsa
debug1: Trying private key: /home/vagrant/.ssh/id_ecdsa
debug1: Trying private key: /home/vagrant/.ssh/id_ecdsa_sk
debug1: Trying private key: /home/vagrant/.ssh/id_ed25519
debug1: Trying private key: /home/vagrant/.ssh/id_ed25519_sk
debug1: Trying private key: /home/vagrant/.ssh/id_xmss
debug1: Next authentication method: password
[email protected]'s password:

在这种情况下,您必须使用 -i 旗帜。

$ ssh -v -i /home/vagrant/.ssh/first_key [email protected]

当您运行临时命令或剧本时,您可以使用 --key-file 或者 --private-key 标记并将私钥文件作为参数传递。 在下面 example,您可以看到我已使用两个密钥(first_key & second_key)成功地与托管节点通信。

# USING --key-file FLAG

$ ansible managed1 -m ping --key-file /home/vagrant/.ssh/second_key

managed1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
# USING --private-key FLAG

$ ansible managed1 -m ping --private-key /home/vagrant/.ssh/first_key

managed1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

您也可以添加参数“private_key_file“ 在里面 ansible.cfg 将应用于临时命令和所有 playbook 任务的配置文件。

$ vim ansible.cfg

添加以下行:

Private_key_file = /home/vagrant/.ssh/first_key

代替 /home/vagrant/.ssh/first_key 用你自己的。

私钥文件

您还可以添加 “ansible_ssh_private_key” 库存文件中的参数将优先于 ansible.cfg 文件。 下面是我的库存现在是如何设置的。 节点 托管1 将使用 “第一键”托管2 将使用 “第二键”.

[ubuntu1]
managed1 ansible_ssh_private_key_file=/home/vagrant/.ssh/first_key

[ubuntu2]
managed2 ansible_ssh_private_key_file=/home/vagrant/.ssh/second_key

现在,如果您再次运行 adhoc 命令或 playbook,您可以看到两个密钥都将成功验证。 您可以增加详细程度以检查是否根据我们的输入使用了适当的键。

$ ansible -vvv all -m ping
不同的密钥对

现在您应该对基于密钥的身份验证如何在 ansible 中工作有了很好的理解。 在不同文件中添加参数时,了解优先级很重要。 命令行选项优先级更高,其次是清单文件和 ansible.cfg 配置文件。

Ansible 中基于 SSH 密码的身份验证

当您运行任何任务时,ansible 将使用控制器节点中的当前用户通过 SSH 与托管节点进行通信。 您可以使用 shell 模块并运行“whoami” 命令验证受管节点中的用户名。在我的例子中,用户名是 “流浪汉”. vagrant 用户正在使用我在上一节中设置的密钥进行身份验证。

$ whoami
vagrant
$ ansible all -m shell -a "whoami"
managed2 | CHANGED | rc=0 >>
vagrant
managed1 | CHANGED | rc=0 >>
vagrant

如果您希望以其他用户身份连接到受管节点,您可以使用 --u 或者 --user 标记并将用户名作为参数传递。 如果您看到下图,我尝试使用用户“karthick”,该用户没有 SSH 密钥设置,也没有向受管节点分发密钥,因此连接失败。

$ ansible all -m shell -a "whoami" -u karthick
$ ansible all -m shell -a "whoami" --user karthick
连接错误连接错误

要使用基于密码的身份验证,您可以使用 -k 或者 --ask-pass 旗帜。 它将提示您输入用户 (karthick) 的 SSH 密码。 确保用户的所有节点的密码相同。

$ ansible all -m shell -a "whoami" -u karthick -k
$ ansible all -m shell -a "whoami" -u karthick --ask-pass
SSH 密码提示SSH 密码提示

您还可以将密码存储在文件中并将文件名作为参数传递给 --connection-password-file 或者 --conn-pass-file 旗帜。 这不是推荐的方式,因为您将密码存储在纯文本文件中。 您可以使用 ansible Vault 来加密密码文件,但这是一个单独的主题来讨论。

$ ansible all -m shell -a "whoami" -u karthick --connection-password-file pass.txt
$ ansible all -m shell -a "whoami" -u karthick --conn-pass-file pass.txt

您也可以在清单文件中将用户名和密码作为参数传递。 同样,这不是存储密码的最佳方式。 以下是我的库存文件现在的设置方式。

[ubuntu1]
managed1 ansible_ssh_private_key_file=/home/vagrant/.ssh/first_key ansible_user=vagrant

[ubuntu2]
managed2 ansible_user=karthick ansible_ssh_pass=password
$ ansible all -m shell -a "whoami" -u karthick

managed1 | CHANGED | rc=0 >>
vagrant
managed2 | CHANGED | rc=0 >>
karthick

小心: 我可能正在使用临时命令运行示例,但相同的标志也适用于剧本。

Ansible 中的权限提升

有时您的任务需要提升权限(root)才能成功运行。 为了 example,包管理。 您只能安装、删除或升级软件包作为 root 用户或与 sudo 特权。

当您与 ansible 或 ansible-playbook 一起运行帮助标志时,您会发现如镜像所显示的特权升级部分。

$ ansible --help
$ ansible-playbook --help
权限提升选项权限提升选项

当你想运行任何任务时 root 特权,你应该使用 -b 或者 --become 旗帜。

$ ansible ubuntu1 -m service -a "name=sshd state=restarted" -b

managed1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "name": "sshd",
    "state": "started",

默认情况下, sudo 将用作提权方法。 您可以通过设置更改方法 --become-method 旗帜。 您可以通过运行以下命令获取支持的方法列表。

$ ansible-doc -t become -l

ansible.netcommon.enable     Switch to elevated permissions on a network device                                                             
community.general.doas       Do As user                                                                                                     
community.general.dzdo       Centrify's Direct Authorize                                                                                    
community.general.ksu        Kerberos substitute user                                                                                       
community.general.machinectl Systemd's machinectl privilege escalation                                                                      
community.general.pbrun      PowerBroker run                                                                                                
community.general.pfexec     profile based execution                                                                                        
community.general.pmrun      Privilege Manager run                                                                                          
community.general.sesu       CA Privileged Access Manager                                                                                   
community.general.sudosu     Run tasks using sudo su -                                                                                  
runas                        Run As user                                                                                                   
su                           Substitute User                                                                                               
sudo                         Substitute User DO 

你可能会也可能不会 sudo 受管节点的密码取决于用户的设置方式。 就我而言,我已经设置了用户 流浪汉 跑步 sudo 无需提示输入密码。

如果你的 sudo 用户需要密码才能工作,那么您应该使用 -K 或者 --ask-become-pass 将提示输入的标志 sudo 密码。

从下面的错误中可以看出,当我尝试在不提供 sudo 用户“karthick”的密码,它给我一个错误说 “失踪 sudo 密码”.

$ ansible ubuntu1 -m service -a "name=sshd state=restarted" -i inventory -u karthick -k -b

SSH password:
managed1 | FAILED! => {
    "msg": "Missing sudo password"
}
$ ansible ubuntu1 -m service -a "name=sshd state=restarted" -i inventory -u karthick -k -b -K
对 Sudo 密码提示使用 -K 标志对 Sudo 密码提示使用 -K 标志

sudo 密码可以存储在文件中并作为参数传递给 --become-password-file 或者 --become-pass-file 旗帜。 Ansible vault 可用于加密此文件,但不推荐使用。

$ ansible ubuntu1 -m service -a "name=sshd state=restarted" -i inventory -u karthick -k -b --become-password-file pass.txt

$ ansible ubuntu1 -m service -a "name=sshd state=restarted" -i inventory -u karthick -k -b --become-pass-file pass.txt

您还可以包括 “变得” 在任务级别或游戏级别的剧本中的指令。

下图表示如何 “变得” 指令用于 游戏等级.

这 游戏层面的“成为”指令

下图表示如何 “变得” 指令用于 任务级别.

任务级别的成为指令任务级别的成为指令

从输出中可以看出, ssh 服务在 托管1 节点。

$ ansible-playbook restart_service.yml

PLAY [Restart SSHD service] ***************************************************************************

TASK [Restart SSHD in managed1.anslab.com] ************************************************************
changed: [managed1]

PLAY RECAP ********************************************************************************************
managed1 : ok=1 changed=1    unreachable=0     failed=0 skipped=0    rescued=0 ignored=0   

“成为”指令也可以设置为 ansible.cfg 配置文件和库存文件。 但建议在 playbook 中设置指令。 你可以得到不同的参数 ansible.cfg 从下面的链接文件。

如果要在连接到受管节点后以其他用户身份运行任务,则应使用 --become-user 旗帜。 默认情况下,它设置为 root 用户。

结论

在本文中,我们了解了基于密钥和密码的身份验证如何在 Ansible 中以及支持身份验证的不同标志中工作。 我们还看到了权限提升在 Ansible 中的工作原理。

要深入了解,您应该对不同的权限提升方法如何工作以及根据您的需要设置环境而不影响安全性有一个公平的了解。

阅读下一篇:

  • Ansible 即席命令入门