Тема не учебная для галочки: на экзамене RHCE (EX294) раздача SSH-ключей через authorized_key - прямая задача из главы про управление пользователями. Там реально просят: создай пользователя на всех узлах и положи ему публичный ключ. Кто путает, чей ключ кладёт и куда, теряет баллы на ровном месте.
Зачем вообще ansible authorized_key, а не shell
Можно ведь просто скопировать файл в ~/.ssh/authorized_keys через ansible.builtin.copy. Можно. Но тогда ты управляешь файлом целиком: либо затираешь всё, что там было, либо не трогаешь чужие ключи вообще. А жизнь между этими крайностями. Модуль ansible.posix.authorized_key понимает структуру файла: он добавляет конкретный ключ, не ломая остальные, проверяет, есть ли он уже (идемпотентность), и умеет режим "только эти ключи и никаких других". Плюс сам создаёт каталог .ssh с правильными правами 0700 и сам файл с 0600 - а на эти права болезненно реагирует sshd и SELinux в RHEL/Fedora.
Модуль живёт в коллекции ansible.posix, поэтому полное имя (FQCN) - ansible.posix.authorized_key. Если коллекции нет, ставится так:
Код: Выделить всё
ansible-galaxy collection install ansible.posix
- user - чьи authorized_keys правим (обязательный). Это пользователь НА УЗЛЕ, не тот, под кем подключаешься.
- key - сам публичный ключ строкой, или несколько ключей, или даже URL вида https://github.com/username.keys.
- state - present (добавить) или absent (убрать). По умолчанию present.
- exclusive - если true, в файле останутся ТОЛЬКО ключи из этой таски, всё остальное вычищается. Мощно и опасно.
- path - нестандартный путь к файлу ключей, если authorized_keys лежит не в дефолтном месте.
- key_options - опции ограничения: from="10.0.0.0/24", command="...", no-agent-forwarding и прочее.

Практика: раздаём ключ админа на парк серверов
Сначала ключ нужно иметь. Сгенерировать пару на своей машине - обычный ssh-keygen, ничего ansible-специфичного:
Код: Выделить всё
ssh-keygen -t ed25519 -C "admin@cyberlake" -f ~/.ssh/id_admin
Теперь типовой плейбук. Сначала заводим пользователя автоматизации через ansible.builtin.user, потом кладём ему ключ. Связка ansible user ssh - именно про это: пользователь и его ключ управляются вместе, в одном плейбуке, иначе получится таска, которая падает на несуществующем юзере.
Код: Выделить всё
---
- name: Раскатка админского SSH-доступа на парк серверов
hosts: all
become: true
vars:
admin_user: deploy
tasks:
- name: Создаём пользователя автоматизации
ansible.builtin.user:
name: "{{ admin_user }}"
shell: /bin/bash
state: present
- name: Кладём публичный ключ админа
ansible.posix.authorized_key:
user: "{{ admin_user }}"
state: present
key: "{{ lookup('ansible.builtin.file', '~/.ssh/id_admin.pub') }}"
Запускаем по всему инвентарю:
Код: Выделить всё
ansible-playbook -i inventory site.yml
exclusive: наводим жёсткий порядок в ключах
Самое интересное в задаче "ansible ssh ключи на парке" - это уборка. Допустим, политика такая: на сервере должны лежать ровно два ключа, админский и CI-раннера, и больше ничего. Любой ключ, который кто-то добавил руками, должен исчезнуть при следующем прогоне. Для этого exclusive: true, причём оба ключа передаются ОДНОЙ строкой через перевод строки:
Код: Выделить всё
- name: Только разрешённые ключи, остальное вычистить
ansible.posix.authorized_key:
user: deploy
state: present
exclusive: true
key: |
{{ lookup('ansible.builtin.file', '~/.ssh/id_admin.pub') }}
{{ lookup('ansible.builtin.file', '~/.ssh/id_ci.pub') }}
Убрать конкретный ключ уволенного без exclusive - чисто state: absent:
Код: Выделить всё
- name: Отозвать ключ бывшего сотрудника
ansible.posix.authorized_key:
user: deploy
state: absent
key: "ssh-ed25519 AAAA...старый_ключ... ivan@old"
Раскатать ключи - половина дела. Пока на сервере разрешён вход по паролю, ключи дают удобство, но не защиту: брутфорс пароля root по ssh никуда не делся. После того как ключевой доступ проверен и работает (проверь обязательно, иначе закроешь себе вход), выключаем парольную аутентификацию через sshd. На RHEL/Fedora правим конфиг и перезапускаем демон:
Код: Выделить всё
- name: Запретить вход по паролю
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
validate: 'sshd -t -f %s'
notify: restart sshd
handlers:
- name: restart sshd
ansible.builtin.service:
name: sshd
state: restarted
Маленькая заметка про другие дистрибутивы: на Ubuntu/Debian модуль authorized_key работает ровно так же, отличается только установка пакетов (apt вместо dnf) и иногда имя сервиса (ssh вместо sshd). На RED OS и Astra Linux всё ближе к RHEL-семейству, sshd и systemd на месте.
Типичные грабли
- Путают user в таске. user - это владелец authorized_keys НА УЗЛЕ, а не аккаунт подключения Ansible. Хочешь ключ для deploy - пиши user: deploy.
- Передают приватный ключ вместо публичного. В authorized_keys идёт ТОЛЬКО .pub. Приватный там - дыра размером с сервер.
- Забывают про exclusive scope. Несколько exclusive-тасок на одного юзера затирают друг друга. Все ключи - в одну таску.
- SELinux и контекст. Если создавал .ssh нестандартно, контекст ssh_home_t может слететь, и вход не пойдёт. Модуль сам ставит права, но при ручных манипуляциях спасает restorecon -Rv ~/.ssh.
- become забыли. Чтобы писать в чужой ~/.ssh, нужен become: true, иначе таска упрётся в права.
Повтори руками на двух тестовых узлах:
- Сгенерируй пару ed25519 через ssh-keygen, не задавая passphrase.
- Напиши плейбук: ansible.builtin.user создаёт юзера automation, ansible.posix.authorized_key кладёт ему публичный ключ.
- Прогони дважды, убедись что второй раз - ok, а не changed.
- Добавь второй ключ с exclusive: true одной строкой, проверь cat ~automation/.ssh/authorized_keys - лишнего нет.
- Отзови один ключ через state: absent.
- Отключи PasswordAuthentication с validate, перезайди по ключу и убедись, что пароль больше не спрашивают.
- Чем ansible.posix.authorized_key лучше копирования файла authorized_keys целиком?
- Что делает exclusive: true и почему опасно ставить его в нескольких тасках для одного пользователя?
- Какой ключ - публичный или приватный - идёт в параметр key и почему?
- Зачем нужен validate в таске правки sshd_config и что будет без него?
ansible.posix.authorized_key превращает раздачу SSH-доступа из ручной рутины в воспроизводимое состояние: один плейбук - и весь парк синхронизирован. Связка с ansible.builtin.user даёт полный цикл "завести пользователя и выдать ему ключ", exclusive держит файл в чистоте, а отключение парольной аутентификации закрывает дыру. Для EX294 это базовый навык, который должен отскакивать от зубов: создать юзера, положить ключ, проверить идемпотентность. Отработай мини-лабу - и эта задача на экзамене станет одной из самых быстрых.