🔐 Ansible SSH аутентификация и повышение привилегий

Мануал

В этой статье мы сосредоточимся на двух важных концепциях Ansible.

Первая концепция заключается в том, как в Ansible работает аутентификация на основе ключей SSH и паролей.

Вторая концепция – как повысить привилегии при работе со специальными командами и плейбуками.

Аутентификация на основе ключей в Ansible

Первое, что вы должны понять при изучении Ansible, это то, как происходит обмен данными между контроллером и управляемыми нодами.

Ansible использует протокол SSH для подключения к управляемым нодам и выполнения задач.

Каждый раз, когда вы запускаете playbook или специальные команды, вам необходимо указать пароль SSH, чтобы Ansible мог аутентифицироваться на управляемых нодах по SSH.

Чтобы избежать этого, рекомендуется создать пару ключей SSH и поделиться открытым ключом со всеми узлами, чтобы ansible мог взаимодействовать с помощью пары ключей.

Я создал две пары ключей с именами first_key и second_key с помощью приведенного ниже скрипта для демонстрации.

#!/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" vagrant@$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
vagrant@managed1's password:

В этом случае необходимо явно указать файл закрытого ключа с помощью флага -i.

$ ssh -v -i /home/vagrant/.ssh/first_key vagrant@managed1

Когда вы запускаете специальную команду или playbook, вы можете использовать флаг –key-file или –private-key и передать файл закрытого ключа в качестве аргумента.

В приведенном ниже примере видно, что я использовал оба ключа (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, который будет применяться к adhoc-командам и всем задачам playbook.

$ vim ansible.cfg

Добавьте следующую строку:

Private_key_file = /home/vagrant/.ssh/first_key

Замените /home/vagrant/.ssh/first_key на свой собственный.

Вы также можете добавить параметр “ansible_ssh_private_key” в файл inventory, который будет иметь больший приоритет над файлом ansible.cfg.

Ниже показано, как настроен мой инвентари.

Нода managed1 будет использовать “first_key”, а managed2 – “second_key”.

[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.

Аутентификация на основе пароля SSH в Ansible

Когда вы запускаете любую задачу, Ansible будет использовать текущего пользователя на ноде контроллера для связи с управляемыми нодами по SSH.
Вы можете использовать модуль shell и выполнить команду “whoami” для проверки имени пользователя на управляемых нодах.
В моем случае имя пользователя – “vagrant”.
Пользователь 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.
Будет предложено ввести пароль SSH для пользователя (karthick).
Убедитесь, что пароль одинаковый на всех нодах для данного пользователя.
$ ansible all -m shell -a "whoami" -u karthick -k
$ ansible all -m shell -a "whoami" -u karthick --ask-pass

Вы также можете хранить пароль в файле и передавать имя файла в качестве аргумента для флага –connection-password-file или –conn-pass-file.

Этот способ не рекомендуется, поскольку вы храните пароль в обычном текстовом файле.

Вы можете использовать ansible vault для шифрования файла паролей, но это отдельная тема для обсуждения.

🔐 Как использовать 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). Например, управление пакетами.

Вы можете устанавливать, удалять или обновлять пакеты только от имени пользователя root или с привилегиями sudo.

Если вы запустите флаг help вместе с 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 для управляемых нод в зависимости от того, как настроен пользователь.

В моем случае я настроил пользователя vagrant для запуска sudo без запроса пароля.

Если ваш пользователь sudo требует пароль для работы, то вам следует использовать флаг -K или –ask-become-pass, который запросит пароль sudo.

Как видно из приведенной ниже ошибки, когда я пытаюсь запустить sudo без указания пароля sudo для пользователя “karthick”, выдает ошибку “Missing sudo password”.

$ 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 может храниться в файле и передаваться в качестве аргумента для флага –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

Вы также можете включить директиву “become” в плейбук.

Как видно из вывода, служба ssh перезапущена нормально на ноде managed1.

$ 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
Директива “become” также может быть установлена в конфигурационном файле ansible.cfg и в файле инвентари.
Но рекомендуется устанавливать директиву в плейбуке.

Заключение

В этой статье мы рассмотрели, как работает аутентификация на основе ключа и пароля в Ansible, а также различные флаги, поддерживаемые для аутентификации.
Мы также рассмотрели, как работает эскалация привилегий в Ansible.
см. также:

Добавить комментарий