Автоматизация установки обновлений: WSUS, Ansible и dnf-automatic

0
16
Обложка статьи: Автоматизация установки обновлений: WSUS, Ansible и dnf-automatic

Пока обновления ставят вручную по памяти администратора, срок на устранение из регламента остаётся пожеланием: сервер забыли, окно пропустили, администратор в отпуске. Автоматизация решает три вещи: обновления ставятся по расписанию, их состояние видно, а у узла, который не обновился, есть повод попасть в список. Ниже для каждой платформы, что ставить, как настроить и как получить отчёт.

Если вы выбираете инструмент для Debian и Ubuntu, подробный разбор в статье про unattended-upgrades. Как тестировать обновления до массовой установки — стенд, кольца, откат. Откуда берутся сроки: управление уязвимостями.

Что чем обновлять

Платформа Средство Что оно делает Чего не умеет
Windows-серверы и рабочие станции в домене WSUS и групповые политики Хранит обновления, позволяет одобрять по группам, показывает, кто что установил Сторонние приложения: для них нужно другое средство
Debian, Ubuntu unattended-upgrades Ставит обновления безопасности по таймеру Не координирует парк: не знает, что узлы нужно обновлять по кольцам
Rocky, Alma, RHEL dnf-automatic Скачивает и ставит обновления безопасности по таймеру Та же причина: каждый узел сам по себе
Весь парк Linux Ansible Кольца, очередность, проверки до и после, перезагрузка, отчёт Без расписания не работает: запуск нужен из планировщика или CI

Для критичных систем выбор простой: автоматика ставит обновление на тестовом и пилотном кольце, а на основных узлах его запускает администратор через Ansible или одобрение в WSUS в согласованное окно. Для остальных узлов допустимо полностью автоматическое обновление безопасности.

Windows: WSUS и групповые политики

Microsoft объявила WSUS устаревающим решением (новых функций не будет), но существующие установки продолжают работать и получать исправления. Для инфраструктуры без доступа к облачным службам обновления он остаётся основным вариантом. Установка на сервере с Windows Server:

Install-WindowsFeature -Name UpdateServices -IncludeManagementTools

# после установки роли: каталог для хранения обновлений
& "C:\Program Files\Update Services\Tools\wsusutil.exe" postinstall CONTENT_DIR=D:\WSUS

Ожидаемо: в диспетчере сервера появится роль «Службы WSUS», команда postinstall завершится без ошибок. Для хранения обновлений нужен отдельный диск: каталог быстро занимает сотни гигабайт. Риск: не ставьте WSUS на контроллер домена и не оставляйте каталог на системном диске.

Дальше два шага. В консоли WSUS создайте группы компьютеров: «Тест», «Пилот», «Основные», «Критичные». Затем групповой политикой направьте клиентов на сервер: Computer Configuration → Administrative Templates → Windows Components → Windows Update.

Параметр политики Значение Зачем
Specify intranet Microsoft update service location http://wsus.example.com:8530 для обновления и статистики Клиенты берут обновления у вас, а не из интернета. Порты WSUS по умолчанию: 8530 (HTTP) и 8531 (HTTPS)
Enable client-side targeting Имя группы, например «Пилот» Клиент сам попадает в нужную группу, вручную их переносить не нужно
Configure Automatic Updates Автоматически скачивать и устанавливать, по расписанию Установка идёт без участия пользователя в согласованное окно
Configure auto-restart / запрет перезагрузки при вошедшем пользователе По политике подразделения Не терять работу пользователя в рабочее время

Одобрение в консоли WSUS делайте по кольцам: сначала «Тест», через сутки «Пилот», затем «Основные». Автоодобрение разрешайте только для группы «Тест». Раз в месяц чистите сервер, иначе он зарастает устаревшими обновлениями:

Invoke-WsusServerCleanup -CleanupObsoleteUpdates -CleanupUnneededContentFiles -DeclineSupersededUpdates -DeclineExpiredUpdates

Ожидаемо: команда выведет число отклонённых и удалённых обновлений и освобождённое место. Ещё одна проверка, которая важна для отчёта: какие клиенты давно не выходили на связь.

Get-WsusComputer -All | Where-Object { $_.LastReportedStatusTime -lt (Get-Date).AddDays(-14) } |
  Select-Object FullDomainName, LastReportedStatusTime

Ожидаемо: список узлов, молчащих больше двух недель. Это либо выключенные машины, либо узлы со сломанным агентом обновления; их надо разобрать отдельно, иначе в отчёте они выглядят как «неизвестно». На самом клиенте проверить установленные обновления можно командой Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 5.

RHEL, Rocky, Alma: dnf-automatic

sudo dnf install dnf-automatic
sudoedit /etc/dnf/automatic.conf

Основные параметры файла:

[commands]
upgrade_type = security
download_updates = yes
apply_updates = yes

[emitters]
emit_via = stdio,email

[email]
email_from = root@host.example.com
email_to = it-ops@example.com
sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timer

Ожидаемо: таймер включён, в списке видно время ближайшего запуска. Параметр upgrade_type = security ограничивает установку обновлениями безопасности, чтобы не ставить новые версии пакетов без необходимости. Перезагрузка после обновлений автоматически не делается: узнать, нужна ли она, можно так.

sudo dnf needs-restarting -r

Код выхода 1 означает, что нужна перезагрузка, и это стоит включить в отчёт, потому что обновлённое ядро или библиотека не работают, пока узел не перезапущен.

Debian и Ubuntu

Для этих систем используйте unattended-upgrades, как описано в отдельной статье: он ставит исправления безопасности по таймеру и умеет писать в журнал. Для Astra Linux и РЕД ОС порядок установки обновлений задаёт производитель, поэтому перед включением автоматики сверьтесь с его документацией и с методикой ФСТЭК для вашего класса защиты.

Весь парк: Ansible, кольца и проверки

Автоматика на каждом узле не знает о других узлах. Если плохое обновление ставится на всех одновременно, вы узнаете об этом по звонкам. Ansible даёт управляемую очередь: сначала тест, затем пилот, затем остальные. В инвентарной описи заведите группы patch_test, patch_pilot, patch_prod. Пример сценария (для Debian и Ubuntu; для RHEL-семейства вместо двух задач ниже используйте модуль dnf с параметром security: true):

---
- name: Обновления безопасности по кольцам
  hosts: "{{ ring | default('patch_test') }}"
  become: true
  serial: "{{ batch | default(1) }}"
  max_fail_percentage: 0
  tasks:
    - name: Обновить индекс пакетов
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600

    - name: Установить обновления безопасности
      ansible.builtin.command: unattended-upgrade -v
      register: upg
      changed_when: "'Packages that will be upgraded' in upg.stdout"

    - name: Нужна ли перезагрузка
      ansible.builtin.stat:
        path: /var/run/reboot-required
      register: reboot_flag

    - name: Перезагрузить, если разрешено окном
      ansible.builtin.reboot:
        reboot_timeout: 600
      when: reboot_flag.stat.exists and (allow_reboot | default(false) | bool)

    - name: Проверить, что узел вернулся и службы работают
      ansible.builtin.command: systemctl is-system-running
      register: state
      failed_when: state.stdout not in ['running', 'degraded']
      changed_when: false

Запускайте так: сначала «в сухую», потом по кольцам.

ansible-playbook patch.yml -e ring=patch_test --check --diff
ansible-playbook patch.yml -e ring=patch_test
# через 1-3 дня, если на тесте всё в порядке
ansible-playbook patch.yml -e ring=patch_pilot -e batch=2
# затем основное кольцо, окно с перезагрузкой
ansible-playbook patch.yml -e ring=patch_prod -e batch=5 -e allow_reboot=true

Ожидаемо: на каждом узле итог «ok» или «changed», остановка очереди при первой ошибке (параметр max_fail_percentage: 0). Риск: перезагрузка серверов баз данных без остановки приложения. Для таких узлов делайте отдельный сценарий с остановкой служб до и проверкой после.

Кольца установки обновленийОбновление проходит стенд, пилотную группу, основную группу и критичные серверы с выдержкой между кольцами.Стендклон боевой ВМсмоук-тестдень 0ПилотИТ и 5–10% узловнаблюдение 1–3 днядень 1–3Основноеостальные узлыпо окнамдень 4–7Критичныесервисы с ПДнс планом откатаокно владельцаДля уязвимостей из KEV на периметре кольца сжимаются до часов, но стенд иоткат не отменяются.
Выдержка между кольцами нужна, чтобы дефектное обновление остановилось на пилоте.

Сценарий запускают по расписанию из планировщика или из CI: тогда у вас остаётся журнал запусков, который можно показать как подтверждение автоматизации.

Отчёт: что ещё не обновлено

Автоматизация без отчёта создаёт иллюзию порядка. Один раз в неделю собирайте состояние: сколько обновлений безопасности ждёт установки на каждом узле и нужна ли перезагрузка.

# Debian и Ubuntu: сколько пакетов ждёт установки
ansible all -b -m shell -a "apt-get -s upgrade | grep -c '^Inst'" -o

# есть ли узлы, ждущие перезагрузки
ansible all -m stat -a "path=/var/run/reboot-required" -o | grep -c '"exists": true'

Для Windows это отчёты WSUS: Reports → Update Status Summary и список клиентов без связи, который мы получили выше. Для руководителя достаточно одной цифры: доля узлов, у которых нет неустановленных обновлений безопасности старше срока из регламента.

Какие артефакты хранить

Что хранить Что показывает
Перечень решений по платформам с ключевыми настройками (политика WSUS, automatic.conf, сценарий Ansible) Для критичных систем есть автоматизированное решение, а не память администратора
Примеры установки обновлений на критичных системах: журнал запуска Ansible, отчёт WSUS за месяц Автоматика работает на практике
Отчёт о текущем состоянии обновлений Установка контролируется, видно, что осталось
Список узлов, исключённых из автоматики, с причиной Исключения не потеряны

Диагностика

Симптом Причина и что делать
Клиенты Windows не появляются в консоли WSUS Не применилась политика или заняты порты. Выполните gpresult /r и проверьте доступность порта 8530
dnf-automatic молчит, письма нет Не настроена почтовая служба на узле. Используйте emit_via = stdio и смотрите журнал: journalctl -u dnf-automatic
Ansible останавливается на первом узле кольца Ошибка на нём. Разберите вывод, это и есть смысл кольца: плохое обновление дальше не пошло
Обновление поставлено, но сканер всё ещё видит уязвимость Не перезапущена служба или узел не перезагружен. Проверьте needrestart и needs-restarting
Каталог WSUS занял весь диск Не делалась очистка. Запустите Invoke-WsusServerCleanup, затем настройте регулярную очистку

Где это в модели зрелости

Материал относится к направлению «Управление уязвимостями» (хаб: уязвимости, карта: карта зрелости). Он закрывает требование второго уровня: для критичных систем обновлениями управляют автоматизированные решения, которые устанавливают, наблюдают и контролируют. Чтобы автоматика не уронила продуктив, ей нужно предшествовать тестирование, см. управление изменениями.

Как проверить

  1. Для каждой платформы вашей инфраструктуры названо средство, и оно настроено, а не только установлено.
  2. На случайном критичном узле видно последнее автоматическое обновление и дату.
  3. Отчёт о состоянии обновлений получен за последнюю неделю и содержит цифры по узлам.
  4. Для узла в статусе «ждёт перезагрузки» есть задача на перезагрузку с датой.

Источники

  • Microsoft Learn, развёртывание WSUS: learn.microsoft.com.
  • Документация dnf-automatic: dnf.readthedocs.io.
  • Документация Ansible, модули apt, dnf, reboot: docs.ansible.com.
  • NIST SP 800-40 Rev. 4, управление корпоративными исправлениями: csrc.nist.gov.

Комментарии закрыты.