Почему правила управления инфраструктурой должны быть кодом
В вашей команде есть правило: ни одна группа безопасности не должна открывать SSH (порт 22) для всего интернета. Все согласны. Это записано в документации. Кто-то даже распечатал это и повесил на стену.
Но в пятницу после обеда разработчик создает новую группу безопасности для быстрого теста. Он указывает CIDR-блок 0.0.0.0/0 на порту 22, потому что хочет просто быстро что-то проверить. Изменение проходит. Никто не замечает до утра понедельника, когда команда безопасности получает оповещение об открытом SSH-порте.
Такой сценарий повторяется в разных командах каждую неделю. Не потому что люди невнимательны, а потому что ручное соблюдение политик не масштабируется. Когда изменения инфраструктуры происходят несколько раз в день, полагаться на человеческую память или правила в документах — верный путь к пробелам в безопасности.
Проблема политик в документах
Большинство команд начинают с хранения политик в документах. Google Doc, страница в Confluence или PDF в общей папке. В этих документах описано, что должно и не должно происходить: «Все S3-бакеты должны быть зашифрованы», «Можно использовать только одобренные AMI», «У каждого ресурса должен быть тег с кодом центра затрат».
Проблема в том, что документы ничего не enforcing. Они описывают намерения, но не выполняют их. Когда кто-то вносит изменение, нарушающее политику, документ не может его остановить. Он просто лежит, молча ожидая, пока кто-то вспомнит его проверить.
Документы также устаревают. Кто-то обновляет политику, но старая версия остается в закладках. Или команда растет, и новые участники даже не знают о существовании документа. Со временем разрыв между тем, что задокументировано, и тем, что реально развернуто, только увеличивается.
Что значит писать политики как код
Policy as Code — это превращение правил в формат, который машины могут читать и выполнять. Вместо документа «не открывайте SSH для всего мира» вы пишете правило, которое автоматически проверяет каждое изменение инфраструктуры на соответствие этому ограничению.
Политика живет в файле, как и ваш код приложения. Она проходит через систему контроля версий. Она проверяется в pull request'ах. Ее можно тестировать, обновлять и откатывать. Когда кто-то предлагает изменение, нарушающее политику, пайплайн перехватывает его до создания ресурса.
Этот переход от документа к коду меняет то, как команды взаимодействуют с правилами. Политики становятся частью инженерного процесса, а не запоздалой мыслью, которую кто-то проверяет во время аудита.
Конкретный пример с Open Policy Agent
Давайте сделаем это осязаемым. Open Policy Agent (OPA) — популярный инструмент для написания политик как кода. Он использует язык Rego. Вот как выглядит простое правило, блокирующее SSH-доступ отовсюду:
deny if {
input.resource.type == "aws_security_group_rule"
"0.0.0.0/0" in input.resource.cidr_blocks
input.resource.port == 22
}
Это правило гласит: если кто-то пытается создать правило группы безопасности, открывающее порт 22 для всех IP-адресов, пометить его как запрещенное. Файл политики находится в вашем репозитории. Когда приходит pull request, добавляющий правило группы безопасности, CI-пайплайн запускает OPA для проверки предложенных изменений. Если правило срабатывает, пайплайн падает, и разработчик получает немедленную обратную связь.
Вы также можете написать обратное правило, разрешающее только определенные CIDR-блоки для SSH:
allow if {
input.resource.type == "aws_security_group_rule"
input.resource.cidr_blocks[_] != "0.0.0.0/0"
}
Точный синтаксис зависит от вашего инструмента и языка политик, но паттерн одинаков: правила — это код, и код выполняется автоматически.
Другой подход: Sentinel для пользователей Terraform
Если ваша команда активно использует Terraform, HashiCorp Sentinel предлагает более тесную интеграцию. Политики Sentinel пишутся специально для контекста выполнения Terraform. Вот то же ограничение SSH в Sentinel:
import "tfplan"
allowed_cidrs = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
main = rule {
all tfplan.resource_changes as _, change {
change.type is "aws_security_group_rule" implies
change.change.after.cidr_blocks all allowed_cidrs
}
}
Эта политика проверяет, что каждое правило группы безопасности использует только частные IP-диапазоны. Если кто-то попытается использовать публичный CIDR-блок, политика заблокирует изменение.
Разница между OPA и Sentinel в основном в экосистеме. OPA — универсальный инструмент, работающий со многими инструментами помимо Terraform. Sentinel глубоко интегрирован с продуктами HashiCorp, что упрощает настройку, если вы уже в этой экосистеме. Но основная идея идентична: политики — это код, который выполняется в вашем пайплайне.
Где хранить файлы политик
У вас есть два основных варианта размещения файлов политик:
В том же репозитории, что и код инфраструктуры. Это держит политики рядом с ресурсами, которыми они управляют. Когда кто-то изменяет инфраструктуру, он видит соответствующие политики в том же pull request'е. Это хорошо работает для политик, специфичных для команды.
В выделенном репозитории политик. Это централизует все политики в организации. Платформенная команда поддерживает репозиторий, а несколько репозиториев инфраструктуры забирают политики из него. Это лучше работает для правил соответствия на уровне организации, которые не должны различаться между командами.
Оба подхода валидны. Начните с подхода «один репозиторий», если вы новичок в Policy as Code. Переходите к выделенному репозиторию, когда вам нужно последовательно применять политики в нескольких командах.
Практический чеклист для начала
Прежде чем погружаться в написание политик, пройдитесь по этому чеклисту:
- Определите три самых нарушаемых политики. Не пытайтесь кодифицировать всё сразу. Выберите правила, которые причиняют больше всего боли или риска.
- Выберите один инструмент. Начните с OPA, если вам нужна гибкость между инструментами. Начните с Sentinel, если вы глубоко инвестировали в Terraform.
- Напишите одну политику и протестируйте ее вручную. Запустите ее против известного нарушения, чтобы убедиться, что она ловит проблему.
- Добавьте проверку политики в ваш CI-пайплайн. Сделайте так, чтобы она блокировала сборку, а не просто предупреждала. Предупреждения игнорируются.
- Проверяйте и итерируйте. Через неделю проверьте, не поймала ли политика что-то неожиданное. Исправьте ложные срабатывания.
Реальная ценность в рабочем процессе
Выбранный инструмент имеет меньшее значение, чем принятый рабочий процесс. Когда политики — это код, они получают такое же обращение, как и код приложения. Они проверяются, тестируются, версионируются и улучшаются со временем. Когда политика вызывает ложное срабатывание, кто-то открывает pull request для ее исправления. Когда появляется новое требование соответствия, кто-то пишет новое правило и отправляет его через тот же пайплайн.
Этот рабочий процесс устраняет разрыв между намерением политики и фактическим ее применением. Правило «не открывать SSH для всего мира» больше не является документом, который кто-то может забыть проверить. Это строка кода, которая выполняется каждый раз при изменении инфраструктуры. В этом разница между надеждой, что ваша команда следует правилам, и уверенностью, что она это делает.