Всем привет! Я занимаюсь автоматизацией развертывания киберполигонов или, другими словами, цифровых инфраструктур компаний различной архитектуры на платформе Standoff 365. Для тех, кто не знает, Standoff 365 — это платформа для всех, кто хочет на практике проверить и улучшить свои навыки в кибербезопасности.
Перед нами стояла следующая задача: быстро развертывать цифровую инфраструктуру по кнопке. Казалось, уже все есть: инструменты, подходы — бери и используй, но дьявол кроется в деталях. В этой статье я расскажу, как мы готовились к возможности внедрения user-friendly-конфигуратора.
Основная идея — в удобном инструменте (WEB-portal). Желательно в GUI рисовать схему цифровой инфраструктуры и передавать ее в систему развертывания (Deployer).

Что у нас было
Могли выбрать любые инструменты, ОС, ПО и сетевые связности.
Портал должен был что-то передать, чтобы Deployer мог «переварить» сформированную конфигурацию.
Техническое задание — развертывать любые (в разумных пределах) архитектуры «живых» компаний. Что значит «живых»? Инфраструктура полностью готова к работе, все пользователи с нужными правами заведены в сервисы, сервисы настроены и работают в боевом режиме. Если кратко — подготовлены цифровые двойники.
Выбор инструмента
Инструмент особо выбирать не пришлось. Нужны были максимальный охват поддерживаемых платформ, приложений, сетевых инструментов, развитое комьюнити и остальное по мелочи. В общем, остановились на Ansible.
В Ansible основной элемент конфигурации — это inventory. В принципе подходит для возможности конфигурации внешним инструментом, но вот подход к конфигурированию нужно было пересмотреть. Общепринятый, который описан на официальном сайте, основан на объединении хостов в группы по функциональному признаку и по описанию переменных для групп и хостов:
all:
children:
itop:
hosts:
itop32:
gitlab:
hosts:
gitlab1:
os_linux:
hosts:
gitlab1:
itop32:
Если нам нужно запустить какой-то сценарий (плейбук) на всех серверах os_linux, мы просто выбираем нужную группу. Ее еще можно предварительно настроить: указать, к примеру, параметры подключения. Довольно удобно. Но когда нужно прописать в inventory 200–300 разнородных устройств, да еще как-то динамически и не ошибиться, задача превращается в дни конфигурирования и переразвертывания.
Техническое задание для интеграции
Мы подошли к основному вопросу: как средствами Ansible inventory конфигурировать гетерогенные инфраструктуры и «натравливать» плейбуки для развертывания, не урезая функциональности (наследования переменных, приоритизации, прозрачности)? Это и стало техническим заданием для подготовки инструментов конфигурирования.
Описание решения
Самым значимым было отвязать группы Ansible inventory от функциональности, развертываемой на хостах.
В чем заключается такой подход:
Для хоста в Ansible inventory задается роль в общей инфраструктуре. Заводится переменная с полным сценарием, который будет установлен: указывается все — от ОС до мелких параметров приложений.
Группы больше не используются по функциональному разделению, и поэтому их можно применять для инфраструктурного конфигурирования.
Минимальный элемент конфигурирования — хост с конкретным сценарием, расположенный в определенной подсети. Она настроена на шлюзе, который подключен к другому шлюзу, и т. д.
Для конфигурирования взаимодействия хоста с другими хостами вводятся группы переменных:
внешних сервисов по отношению к имеющемуся (к примеру — для хоста задается информация о внешнем DNS);
внутренних сервисов по отношению к имеющемуся (к примеру, задается версия устанавливаемого ПО).

Таким образом, мы получили вполне лаконичное описание инфраструктуры, которое ложится на Ansible inventory:
All:
children:
internet:
hosts:
router1:
servicename: router
subnet_srv:
vars:
external_router: router1
hosts:
gitlab:
servicename: gitlab
serviceversion: "16.11.10"
itop:
servicename: itop
serviceversion: "2.4"
subnet_ws:
vars:
external_router: router1
hosts:
ws-admin:
servicename: admin_windows10
ws-finance:
servicename: finance_windows11
subnet_subnet1:
vars:
external_router: router2
hosts:
router2:
servicename: router
subnet_db:
vars:
external_router: router2
hosts:
mysql:
servicename: mysql_debian11
subnet_is:
hosts:
is:
servicename: is_astra175
Как вы могли заметить, для групп подсетей указывается конкретный роутер, за которым закреплена подсеть. Это формирует связи сетей с роутером. Для сервисов GitLab и iTop задана конфигурация внутреннего сервиса.
Дополнение
Для общего понимания важности подхода отмечу: каждый хост в Ansible inventory имеет все данные о соседних сервисах, их именах, о том, какие сервисы установлены и как сконфигурированы. На этом строится интеграционное конфигурирование между сервисами на хостах (куда хосту «ходить» за DNS, где создавать учётки, какие права настраивать и т. п.).
Основная схема интеграции с WEB-portal получилась следующая.

Ansible inventory стал промежуточным звеном для развертывания инфраструктуры. Работу Deployer в рамках этой статьи рассматривать не будем.
Применение решения
Такой подход позволяет тестировать:
продукты, разрабатываемые для гетерогенных сетей (клиенты антивирусов, ERP-клиенты, SIEM-системы);
глобальные продукты, чтобы не развалить боевую инфраструктуру компании;
маршрутизаторы.
Он применим в случаях, когда нужно развернуть большой объем сервисов и инфраструктур с минимальными затратами.
Итог
Мы сформировали подход к конфигурированию практически любых инфраструктур с имеющимся инструментом и без больших затрат на разработку и реализацию.
От себя хотел бы добавить — не ограничивайте себя функциональностью конкретного инструмента, даже если он уже выбран. Добавив в него небольшие изменения, можно сделать работу намного эффективнее.