Статья SecOps Automation: Использование Ansible и Chef для автоматизированного Hardening ОС (Linux/Windows)

1774564882835.webp

Конфигурация сервера почти никогда не ломается одним громким движением. Гораздо чаще всё портят мелкие отклонения, которые накапливаются неделями: где-то вручную ослабили настройки SSH, где-то временно открыли лишний доступ, где-то забыли вернуть аудит, где-то новый хост подняли “побыстрее”, а потом так и оставили. Через пару месяцев инфраструктура уже вроде бы живёт по одному стандарту, но на деле каждый сервер настроен немного по-своему. Именно в этом месте и начинается настоящий дрейф конфигурации - тихий, скучный и очень дорогой для безопасности.

У hardening есть старая проблема: пока он делается руками, он почти неизбежно расползается. Один администратор правит аккуратно, другой спешит, третий делает исключение “на время”, четвёртый уже не помнит, почему этот узел вообще отличается от остальных. В результате security baseline существует на бумаге, а production живёт по своей логике. Поэтому hardening давно перестал быть задачей “один раз настроить сервер”. Его приходится делать частью нормального цикла поставки и сопровождения, иначе через некоторое время от исходной конфигурации остаётся только название.

Здесь автоматизация даёт не удобство, а дисциплину. Ansible и Chef InSpec хорошо ложатся именно на эту задачу: один применяет базовую конфигурацию, второй проверяет, что она действительно соблюдается и не расползлась после изменений. CIS Benchmarks до сих пор остаются одной из самых частых опор для такого baseline. А разделение на L1 и L2 сразу упирается в практику: где ещё идёт полезное усиление системы, а где уже начинаются ограничения, которые задевают совместимость и эксплуатацию.

Проблема дрейфа конфигурации​

Дрейф конфигурации начинается в тот момент, когда одинаковые по роли серверы перестают быть одинаковыми по настройке. Вчера это был один временно открытый доступ, сегодня - отключённый аудит, завтра - лишняя служба, о которой никто уже не помнит. Через несколько месяцев парк машин вроде бы живёт по одному стандарту, но на деле каждая система уже настроена немного по-своему. Так и расползается baseline - без шума, но с вполне реальными последствиями для безопасности.

Ручная настройка и «уникальные» серверы​

Ручная настройка почти всегда создаёт так называемые «уникальные» серверы - машины, которые формально выполняют одну и ту же роль, но отличаются по пакетам, службам, правам, сетевым правилам, журналированию и десяткам мелких параметров. На бумаге они одинаковые. В эксплуатации - уже нет.

Для безопасности это плохой сценарий. Как только у команды появляется десять, двадцать или сто таких узлов, baseline перестаёт быть эталоном и превращается в пожелание. Проверить всё руками невозможно. Повторить одинаковый hardening на Linux и Windows без ошибок тоже невозможно. А любая проверка после инцидента быстро упирается в вопрос: это штатное отклонение, исторический мусор или кто-то реально изменил систему совсем недавно.

Drift опасен не только сам по себе. Он ломает управляемость. Пока конфигурация расползается, команда перестаёт понимать, как вообще должен выглядеть нормальный сервер этой роли.

CIS Benchmarks как опорная точка​

Именно здесь и появляются CIS Benchmarks. По сути это набор согласованных рекомендаций по безопасной конфигурации конкретной системы или продукта. CIS описывает Benchmarks как практики безопасной настройки для целевой системы; сами рекомендации разрабатываются через консенсусный процесс и доступны для большого числа технологий, включая Linux и Windows.

Для команды ценность CIS обычно не в том, что там есть «идеальная истина», а в том, что появляется общая опорная точка. Не “кто как привык настраивать Ubuntu”, не “что осталось от старого образа Windows Server”, а понятный набор правил, из которого можно собрать свой baseline. Это особенно полезно в смешанных средах, где рядом живут Ubuntu, RHEL и Windows Server, а у каждой платформы свои слабые места, свои службы, свои механизмы аудита и свой набор типичных послаблений.

Важно и то, что CIS Benchmarks сразу делят рекомендации по профилям. В официальном FAQ CIS Level 1 описан как базовый профиль, который можно внедрять сравнительно быстро и без сильного влияния на работоспособность. Level 2 рассматривается как более жёсткий вариант для сред, где безопасность важнее удобства и где часть рекомендаций может затронуть совместимость или эксплуатацию.

Для production это ключевой момент. Hardening почти никогда не сводится к схеме “включили всё подряд и поехали”. Нормальная работа начинается с выбора: что идёт в обязательный базовый слой для всех, а что уходит в более строгий профиль для отдельных ролей, сегментов или систем с повышенными требованиями.

Hardening как постоянный процесс​

Главная ошибка в этой теме - воспринимать hardening как одноразовую настройку сервера при вводе в эксплуатацию. Так это не работает. Даже если стартовая конфигурация была идеальной, её всё равно начнут менять обновления, новые пакеты, временные послабления, аварийные правки, ручные действия администраторов и требования приложений. Если на этом месте автоматизация не включается повторно, baseline начинает расползаться почти сразу.

Поэтому hardening в нормальной инфраструктуре живёт как постоянный цикл. Сначала система получает нужную конфигурацию. Потом кто-то или что-то проверяет, что она действительно применена. Затем изменения в системе сравнивают с ожидаемым состоянием. Если настройки ушли в сторону, их либо возвращают автоматически, либо поднимают это как отклонение. Chef как раз и описывает compliance as code как встраивание правил проверки в рабочие процессы и постоянное выявление неверных настроек ещё до того, как они станут привычной частью среды.

На практике это меняет сам подход. Важно не просто настроить сервер, а удерживать его в нужном состоянии. Для SecOps и DevOps это две очень разные задачи. Первая заканчивается после запуска. Вторая только с запуска и начинается.

1.webp


Где drift бьёт сильнее всего​

Сильнее всего дрейф конфигурации заметен в четырёх местах:
  • удалённый доступ и сетевые правила;
  • журналы и аудит;
  • системные службы и лишние пакеты;
  • локальные исключения, которые никто потом не пересматривает.
На Linux это обычно SSH, sysctl, права на файлы и каталоги, auditd, sudo, firewall и набор активных служб. На Windows - WinRM, локальные политики, Defender, аудит, права пользователей, роли сервера и параметры служб. Именно эти зоны быстрее всего начинают расходиться между “эталоном” и тем, что реально осталось на машине через несколько месяцев жизни.

В статье "Небезопасные настройки брокеров сообщений" хорошо разобрана мысль, которая для hardening вообще базовая: конфигурацию нельзя держать в ручных правках и локальных привычках. Если настройки живут не как шаблоны и код, а как “кто-то когда-то поправил на сервере”, drift рано или поздно станет нормой.

Ansible для hardening по CIS​

Ansible здесь ценен повторяемостью. Один и тот же baseline можно накатывать на новые и уже работающие серверы без ручной доводки на каждом узле. Для Linux это обычно SSH, параметры ядра, аудит, права на файлы и службы. Для Windows - WinRM, локальные политики, Defender, аудит, роли сервера и настройки удалённого доступа. Логика одна: нужное состояние описывается в ролях и переменных, потом одинаково применяется на все узлы нужной роли.

С нуля такой hardening собирают редко. Обычно берут готовую основу под Linux и отдельно под Windows, а потом подгоняют её под свою среду. Полностью самописный baseline быстро превращается в отдельный проект со своей поддержкой, тестами и вечным риском что-нибудь забыть.

2.webp


Сначала стоит нормально разметить узлы. Уже на этом этапе Linux и Windows надо развести отдельно, а внутри них - разбить хосты по ролям.

Код:
[ubuntu_app]
app-01 ansible_host=10.10.20.11
app-02 ansible_host=10.10.20.12

[rhel_db]
db-01 ansible_host=10.10.30.11

[windows_jump]
jump-01 ansible_host=10.10.40.11

[windows_app]
winapp-01 ansible_host=10.10.40.21

[linux:children]
ubuntu_app
rhel_db

[windows:children]
windows_jump
windows_app

[linux:vars]
ansible_user=ansible
ansible_become=true

[windows:vars]
ansible_connection=winrm
ansible_winrm_transport=kerberos
ansible_winrm_scheme=https
ansible_port=5986
ansible_user=svc_ansible@corp.local
Этого уже хватает, чтобы не тащить Ubuntu, RHEL и Windows Server под один шаблон. Дальше baseline раскладывают по ролям, а не держат всё в одном длинном playbook.

Linux: где hardening даёт самый быстрый эффект​

На Linux быстрее всего расползаются одни и те же зоны: SSH, sysctl, аудит, права на важные файлы, список служб. Поэтому baseline обычно начинается именно с них. Не потому что это “весь CIS”, а потому что именно здесь ручные правки чаще всего и превращаются в дрейф конфигурации.

Ниже короткий фрагмент роли. Он показывает главную идею: SSH, сетевые параметры и аудит должны жить в коде, а не в памяти администратора.
YAML:
---
# roles/linux_cis_baseline/tasks/main.yml

- name: Запретить root login по SSH
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^#?PermitRootLogin'
    line: 'PermitRootLogin no'
    backup: true
  notify: restart sshd

- name: Отключить парольную аутентификацию по SSH
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^#?PasswordAuthentication'
    line: 'PasswordAuthentication no'
    backup: true
  notify: restart sshd

- name: Отключить ICMP redirects
  ansible.posix.sysctl:
    name: net.ipv4.conf.all.accept_redirects
    value: '0'
    state: present
    reload: true

- name: Установить auditd
  ansible.builtin.package:
    name: auditd
    state: present

- name: Включить auditd
  ansible.builtin.service:
    name: auditd
    enabled: true
    state: started
Даже такой короткий фрагмент уже убирает часть типичных расхождений: SSH перестаёт жить по разным правилам на разных узлах, сетевые параметры не плавают, аудит не отключается “временно”, а потом навсегда. Дальше роль обычно разрастается в стороны sudo, pam, firewall, journald, пакетов и прав на каталоги.

Различия между Ubuntu и RHEL лучше учитывать сразу. Даже если baseline формально один, часть задач всё равно придётся разводить по платформам: имена пакетов, службы, структура конфигурации, SELinux, firewalld.. Один общий Linux-профиль без оглядки на это долго не живёт.

Windows Server: та же задача, другой набор узких мест​

С Windows логика та же, но болевые точки другие. Здесь важнее локальные политики, UAC, Defender, аудит, WinRM, права пользователей, роли сервера и службы. Ошибка многих команд - тащить на Windows ту же логику, что и на Linux, только с другими модулями. Так почти всегда получается криво.

Ниже тоже не “полный CIS”, а рабочий фрагмент роли. Его смысл простой: управление через WinRM должно быть безопасным, базовые защитные настройки - включёнными, а не оставленными в непонятном состоянии.
YAML:
---
# roles/windows_cis_baseline/tasks/main.yml

- name: Убедиться, что WinRM запущен
  ansible.windows.win_service:
    name: WinRM
    state: started
    start_mode: auto

- name: Запретить Basic-аутентификацию для WinRM
  ansible.windows.win_regedit:
    path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WinRM\Client
    name: AllowBasic
    data: 0
    type: dword

- name: Запретить незашифрованный WinRM-трафик
  ansible.windows.win_regedit:
    path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service
    name: AllowUnencryptedTraffic
    data: 0
    type: dword

- name: Включить UAC
  ansible.windows.win_regedit:
    path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
    name: EnableLUA
    data: 1
    type: dword

- name: Не отключать Microsoft Defender
  ansible.windows.win_regedit:
    path: HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender
    name: DisableAntiSpyware
    data: 0
    type: dword
На Windows такие роли лучше гонять ещё осторожнее, чем на Linux. Жёсткие настройки быстро задевают совместимость с приложением, удалённое управление, доменную интеграцию и старые сервисы. Поэтому здесь особенно нужна тестовая группа: jump host, application server, файловый сервер, терминальный узел. Сначала проверяют их, потом идут дальше.

Где роль обычно начинает ломаться​

Hardening-роль почти никогда не ломается в самом очевидном месте.. Чаще ломается то, что в среде давно считалось “нормальной особенностью”. На Linux это может быть старый SSH-клиент, нестандартный набор шифров, старая служба, странный параметр ядра. На Windows - агент, удалённый доступ, наследованная политика, поведение Defender или особенность роли сервера.

Поэтому роль нельзя считать готовой только потому, что она один раз сошлась на тестовом узле. Её сначала прогоняют на эталонной группе по платформам и ролям, потом смотрят, что реально перестало работать, и только после этого решают, что пойдёт в исключения, а что надо исправлять в самой инфраструктуре.

Как это обычно собирают в рабочий контур​

Рабочая схема выглядит без магии:
  • выбрать базовую роль под Linux и отдельно под Windows;
  • вынести отклонения в переменные, а не править роль хаотично;
  • прогнать её на тестовой группе;
  • проверить повторный прогон;
  • включить hardening в обычное развёртывание новых серверов;
  • периодически прогонять его на уже работающих узлах.
В этот момент hardening перестаёт быть разовой настройкой. Новый сервер сразу получает baseline, а старый не уходит в сторону бесконтрольно.

Что важно удержать​

У Ansible в этой задаче две сильные стороны: повторяемость и явные отклонения через переменные. Обе ломаются очень быстро, если команда начинает править роли как попало.

Поэтому здесь лучше держать три простых правила:
  • одна роль - одна понятная зона ответственности;
  • исключения живут в переменных, а не в хаотичных правках;
  • Linux и Windows ведут отдельно, даже если формально речь идёт об одном baseline.
Если это не соблюдать, hardening через Ansible быстро превращается в тот же дрейф конфигурации, только уже под видом автоматизации.

Аудит с Chef InSpec​

Ansible приводит систему к нужному состоянию. InSpec проверяет, что в итоге реально получилось на сервере. После hardening всегда остаётся некая зона неопределённости. Роль применилась - хорошо. Но все ли настройки дошли до конца, не отвалился ли кусок из-за платформенного исключения, не сломала ли что-то совместимость, не уехал ли один из хостов в сторону после ручной правки. InSpec как раз и нужен для того, чтобы проверять состояние машины уже после применения baseline.

Где InSpec уместен​

InSpec интересен не как ещё один “инструмент под комплаенс”, а как вторая половина hardening-процесса. У тебя есть код, который должен привести Linux или Windows к эталонной конфигурации. Значит, рядом нужен код, который сможет это эталонное состояние проверить. Без этого автоматизация hardening остаётся односторонней: настройки накатываются, но никто системно не подтверждает, что итог действительно совпадает с baseline.

В нормальной схеме InSpec ставят сразу после применения ролей. Сначала сервер разворачивается, потом Ansible накатывает baseline, потом InSpec прогоняет профиль проверки. Если всё зелёное, хост уходит дальше. Если нет - команда получает уже не абстрактное “что-то не так”, а вполне конкретный список проваленных контролей.

Профили: готовая основа и локальные проверки​

Профиль InSpec - это набор контролей, которые проверяют состояние системы. В Chef Automate есть готовые профили под распространённые стандарты, включая CIS, и это удобная точка старта, когда не хочется с нуля собирать весь слой аудита. Одновременно почти в любой живой среде появляется и второй слой - короткие локальные проверки под собственные исключения, которые в общий CIS-профиль не входят.

Нормальная практика выглядит так: берётся готовая основа под нужную платформу, а рядом добавляется локальный профиль с тем, что важно именно для этой инфраструктуры. Например, проверить, что root login по SSH запрещён, что auditd включён, что WinRM не живёт в небезопасной конфигурации, что Defender не отключён, что парольная политика на Windows действительно совпадает с тем baseline, который команда считает обязательным.

Ниже короткий пример такого контроля. Это не полный профиль на всю систему, а просто одна проверка, чтобы было видно, как InSpec вообще мыслит проверками ожидаемого состояния.

Ruby:
control 'linux-ssh-root-login-disabled' do
  impact 1.0
  title 'Root login по SSH должен быть отключён'
  desc 'Проверка базовой настройки SSH для Linux-сервера'

  describe sshd_config do
    its('PermitRootLogin') { should cmp 'no' }
  end
end
Такой подход и удобен в связке с Ansible. Ansible отвечает за применение. InSpec отвечает за проверку. В результате baseline живёт не только как роль, но и как набор проверяемых условий.

Как запускать аудит после hardening​

InSpec хорош тем, что его можно прогонять довольно прямолинейно. Для Linux - по SSH. Для Windows - по WinRM. Результат можно сразу сохранять в читаемом виде для человека и в структурированном виде для конвейера или отчётности. Chef отдельно указывает, что стандартные репортёры включают JSON, HTML и plain text, а при необходимости результат можно отправлять дальше в Automate.

Снизу оставлю вам рабочий пример. Один запуск даёт HTML для просмотра и JSON для дальнейшей обработки.
Bash:
# Linux
inspec exec profiles/ubuntu-baseline \
  -t ssh://ansible@app-01.example.local \
  --reporter cli html:reports/app-01.html json:reports/app-01.json

# Windows
inspec exec profiles/windows-server-baseline \
  -t winrm://svc_audit@winapp-01.example.local \
  --password 'REDACTED' \
  --ssl \
  --reporter cli html:reports/winapp-01.html json:reports/winapp-01.json
Смысл не в том, чтобы гонять аудит вручную каждый день. Смысл в том, что после применения baseline у команды появляется повторяемый шаг проверки. Один и тот же хост можно прогонять после развёртывания, после изменения роли, после обновления образа или по расписанию. Тогда hardening перестаёт быть актом веры.

InSpec как post-provisioning gate​

Лучшее место для InSpec в этой схеме - сразу после подготовки сервера. Не до hardening, не “когда-нибудь потом”, а именно после того, как Ansible уже закончил. В этот момент система должна либо подтвердить baseline, либо вернуть понятный список проваленных контролей. Такой режим удобен тем, что отклонение ловится в ближайшей точке к развёртыванию, а не через три месяца на проде.

Тут важен один практический момент: InSpec не должен быть декоративной галочкой. Если он стоит в конвейере, команда заранее должна решить, на чём именно сборка или подготовка хоста останавливается. На любом fail? Только на high-impact контролях? Только на обязательном подмножестве? Без этого audit step быстро превращается в отчёт, который все вежливо складывают в артефакты и никто потом не открывает.

Что обычно ломает нормальный аудит​

Проблемы здесь почти всегда одни и те же.

Первая - слишком широкий профиль без оглядки на реальную среду. Тогда проверка начинает валить то, что у команды и так оформлено как допустимое исключение.
Вторая - отрыв профиля от baseline. Ansible уже живёт в одной версии роли, а InSpec по-прежнему проверяет старую модель сервера.
Третья - отсутствие нормального деления по ролям. Один и тот же аудит начинают гонять на application server, jump host и database host, хотя у них разные требования и разный набор допустимых отклонений.

Production workflow​

Hardening начинает работать только тогда, когда становится обычной частью развёртывания, а не отдельной задачей “навести порядок после запуска”. В нормальной схеме новый сервер не попадает в production в сыром виде. Сначала его поднимают, потом приводят к baseline, потом проверяют, что он этому baseline действительно соответствует. Если один из этапов проваливается, узел не должен тихо уехать дальше по цепочке как будто всё в порядке.

Самая удобная сборка здесь довольно прямая: Terraform создаёт инфраструктуру, Ansible накатывает baseline, InSpec проверяет результат. Это не “идеальная методология”, а просто рабочий способ разделить роли. Один инструмент отвечает за появление узла. Второй - за нужное состояние системы. Третий - за подтверждение, что состояние действительно совпадает с ожиданием. Проверка не должна жить где-то сбоку. Её ставят сразу после hardening, пока отклонение ещё можно быстро остановить и не тащить дальше в среду.

Вот пример такого контура в конвейере:
YAML:
stages:
  - provision
  - harden
  - audit

provision:
  stage: provision
  script:
    - terraform init
    - terraform apply -auto-approve

harden:
  stage: harden
  script:
    - ansible-playbook -i inventory.ini site-hardening.yml

audit:
  stage: audit
  script:
    - inspec exec profiles/linux-baseline -t ssh://ansible@app-01.example.local
    - inspec exec profiles/windows-baseline -t winrm://svc_audit@win-01.example.local --ssl

3.webp


В production такой конвейер почти всегда режут на роли и платформы. Не надо пытаться одним прогоном покрыть всё подряд. Ubuntu application servers, RHEL database hosts, Windows jump hosts и обычные Windows application servers обычно идут отдельными ветками. Тогда baseline, исключения и аудит не смешиваются в одну бесформенную массу, а остаются привязанными к реальной роли хоста.

Где здесь появляется отчётность​

Как только hardening и аудит становятся регулярными, почти сразу возникает второй вопрос: как это показывать не в виде сотни текстовых отчётов, а в виде нормальной картины по парку машин. Здесь обычно идут двумя путями.

Первый - складывать результаты в Grafana. У неё есть штатное provisionирование источников данных и дашбордов из файлов, которые можно хранить в системе контроля версий. Это удобно, когда команда хочет держать панель соответствия рядом с остальной эксплуатационной визуализацией и обновлять её так же, как обновляет остальную инфраструктурную обвязку.

Второй путь - отправлять результаты в Elastic и собирать картину в Kibana. Elastic заточен на приём данных из разных источников, а Kibana даёт нормальный слой для поиска, фильтрации и дашбордов. Такой путь удобен там, где SecOps уже живёт в Elastic и не хочет плодить ещё одну отдельную систему только ради compliance-отчётности.

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

Drift detection без лишней магии​

Дрейф конфигурации лучше ловить не красивыми обещаниями “непрерывного контроля”, а очень приземлёнными повторными проверками. Здесь хорошо работают две вещи вместе: ansible-playbook --check и InSpec. В check mode Ansible не вносит изменения, а показывает, что он бы изменил, чтобы привести систему к нужному состоянию. Это удобный способ увидеть, что узел уже ушёл от baseline, но ещё не возвращать его автоматически.

Выглядит это обычно так:
Bash:
ansible-playbook -i inventory.ini site-hardening.yml --check
inspec exec profiles/linux-baseline -t ssh://ansible@app-01.example.local --reporter cli json:reports/app-01.json
Такая связка даёт две разные точки зрения на один и тот же хост. Ansible показывает, что именно role-based baseline считает отклонением. InSpec показывает, какие контроли реально не прошли на машине. Если оба результата сходятся, у команды появляется очень внятная картина: не “наверное, что-то уплыло”, а конкретный список того, что изменилось.

Где workflow обычно ломается​

Проблемы здесь почти всегда типовые.

Первая - hardening остаётся отдельной задачей после развёртывания. Сервер уже ушёл в работу, а baseline на него накатывают “когда будет время”. В этот момент весь процесс теряет смысл.

Вторая - аудит живёт как отчёт ради отчёта. Проверка выполняется, артефакт складывается в папку, но на его результат ничего не завязано. Тогда InSpec быстро превращается в красивую формальность.

Третья - drift detection запускают слишком редко или слишком беззубо. Если проверка идёт раз в квартал, drift уже успевает стать нормой. Если check mode и аудит никого ни на что не влияют, команда просто привыкает к постоянному жёлтому шуму и перестаёт его читать.

Что в этой схеме действительно важно​

Рабочий production workflow держится не на количестве инструментов, а на порядке шагов.
Сначала узел создаётся.
Потом получает baseline.
Потом baseline проверяется.
Потом результаты не теряются, а попадают в общую картину по среде.
Потом эти же проверки повторяются, чтобы не пропустить drift.

Если из этой цепочки выпадает хотя бы один шаг, hardening быстро остаётся только на уровне намерения.Формально он есть. По факту - уже нет.

ЭтапЧто происходитЧто ломается, если его нет
ProvisioningУзел создаётся как часть обычного развёртыванияСерверы появляются в среде без общей точки входа
HardeningAnsible приводит систему к baselineКонфигурация снова начинает зависеть от ручных правок
AuditInSpec подтверждает итоговое состояниеКоманда не знает, действительно ли baseline применился
ОтчётностьРезультаты видны по хостам, ролям и платформамCompliance живёт в артефактах, которые никто не открывает
Повторная проверкаCheck mode и аудит ловят driftОтклонения копятся месяцами и становятся новой “нормой”

Когда hardening становится процессом​

Автоматизация hardening нужна не ради удобства и не ради красивого слова compliance. Она нужна потому, что ручная настройка почти всегда проигрывает на дистанции. Пока baseline живёт в голове администратора, в старом чек-листе или в “примерно таких же” серверах, конфигурация всё равно расползётся. Один узел уйдёт в сторону из-за срочной правки, второй - из-за забытого исключения, третий - из-за обновления, после которого никто не вернулся к исходным настройкам. Через какое-то время проблема уже не в отдельном сервере, а в том, что команда теряет управляемость.

Связка Ansible и InSpec решает здесь очень практическую задачу. Ansible даёт повторяемый baseline для Linux и Windows, а InSpec проверяет, что этот baseline действительно держится после развёртывания и не расползается дальше. В таком контуре hardening перестаёт быть разовой настройкой перед вводом хоста в эксплуатацию. Он становится частью обычной жизни инфраструктуры: новый сервер получает нужное состояние сразу, действующий сервер регулярно проверяется, а исключения перестают жить в серой зоне между “временно” и “так исторически сложилось”.

Самый неприятный вопрос здесь довольно простой. У вас baseline действительно живёт в коде и регулярно подтверждается, или он до сих пор существует только на словах, а production уже давно настраивается по памяти, через локальные правки и старые привычки?

В статье "DevSecOps: Путь к Комплексной Безопасности Разработки" тема продолжается уже на уровень шире - как сделать так, чтобы hardening, безопасные базовые образы и проверки не существовали отдельно от процесса разработки и сопровождения. Это хороший материал, если хочется посмотреть на ту же проблему не только со стороны серверов, но и со стороны всей цепочки поставки.
 
Последнее редактирование:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab