# terraform-compliance: BDD-проверки на plan-файл _Тестирование · TerraformLab Knowledge Base_ **TL;DR:** Утилита terraform-compliance читает plan-файл (`plan.json`) и применяет к нему BDD-правила в Gherkin. «Given a resource of type X, it must contain a property Y», читаемо для не-инженеров, гарантирует политику до apply. Альтернатива OPA/Rego для команд, которые предпочитают естественный язык, но менее мощная, нельзя писать сложные cross-resource проверки. ## Что это и зачем terraform-compliance, open-source утилита, написанная на Python. На вход принимает Terraform plan в JSON, на вход принимает набор `.feature` файлов в Gherkin (как у Cucumber/behave). Проверяет каждый шаг feature против plan. Запуск: ```bash terraform plan -out=plan.tfplan terraform show -json plan.tfplan > plan.json terraform-compliance --planfile plan.json --features ./policies ``` Идея: правила пишутся языком, который читает security/compliance-команда, не инженер. Они могут сами добавлять policies без знания HCL. ## Минимальный feature-файл `policies/s3-buckets.feature`: ```gherkin Feature: S3 buckets must be encrypted Scenario: Encryption is required Given I have aws_s3_bucket defined Then it must contain server_side_encryption_configuration Scenario: Versioning is required Given I have aws_s3_bucket defined Then it must contain versioning And it must contain enabled And its value must be true ``` Выполнение пройдётся по каждому `aws_s3_bucket` в plan и проверит, что правила соблюдены. Если хоть один не encryption'нут, exit 1, CI ломается. ## Структура Gherkin для terraform-compliance Базовые шаги: | Шаг | Что делает | |---|---| | `Given I have defined` | Фильтр: рассматриваем только ресурсы такого типа. | | `When its is "value"` | Дополнительный фильтр, только ресурсы с таким свойством. | | `Then it must contain ` | Утверждение: ресурс должен иметь это поле. | | `Then it must not contain ` | Утверждение наоборот. | | `Then its value must be ` | Сравнение значения. | | `Then its value must match the "regex"` | Regex-match по значению. | Расширенные: | Шаг | Что делает | |---|---| | `Given I have any resource defined` | Все ресурсы. | | `Given I have action_name defined` | Фильтр по модулю. | | `Then it must have tags` | Распространённая проверка тегов. | | `Then it must contain tags ([k1,k2,k3])` | Конкретные ключи в тегах. | ## Теги в фичах Можно пометить scenario и запускать выборочно: ```gherkin @encryption @critical Scenario: Encryption is required Given I have aws_s3_bucket defined Then it must contain server_side_encryption_configuration ``` Запуск только критичных: ```bash terraform-compliance -p plan.json -f ./policies --tags critical ``` ## CI-интеграция GitHub Actions: ```yaml jobs: plan-and-validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: hashicorp/setup-terraform@v3 - run: terraform init - run: terraform plan -out=plan.tfplan - run: terraform show -json plan.tfplan > plan.json - name: Install terraform-compliance run: pip install terraform-compliance==1.3.50 - name: Validate run: terraform-compliance -p plan.json -f ./policies/ ``` Возвращает non-zero exit на любой failed scenario → PR красный. ## Когда terraform-compliance, когда OPA | Аспект | terraform-compliance | OPA + Rego (conftest) | |---|---|---| | Синтаксис | Gherkin, читается английским | Rego, читается как-то | | Кривая обучения | Низкая для писателя правил | Заметная, другой язык | | Cross-resource проверки | Слабо, каждое правило локальное | Сильно, можно проверять связи | | Внешние данные (lookup) | Нет | Да, через data | | Зрелость / экосистема | Меньшая, узко-фокусированная | Шире, OPA общий policy-engine | | Скорость на больших plan'ах | Заметно медленнее | Быстрее | | Поддержка vendor | Open-source, есть мейнтейнер | Open-source, CNCF, vendor-support через Styra | Для маленькой команды, где политики простые («все бакеты с тегом CostCenter») terraform-compliance быстрее запустить. Для зрелой инфраструктуры с десятками сложных правил, для cross-account/cross-region логики, OPA. См. [tf-policy-as-code](/terraform/kb/tf-policy-as-code.md). ## Пример развитой policy-suite ``` policies/ ├── tagging.feature ├── encryption.feature ├── naming.feature ├── public-access.feature └── networking.feature ``` `tagging.feature`: ```gherkin Feature: All resources must have mandatory tags Scenario: CostCenter tag Given I have any resource defined When it contains tags Then it must contain CostCenter Scenario Outline: Allowed environments Given I have any resource defined When it contains tags Then it must contain Environment And its value must be one of Examples: | envs | | dev,stage,prod | ``` Обрати внимание на `Scenario Outline`, таблично-параметризованные правила. ## Подводные камни - **Проверяет только то, что в plan.** Если ресурс уже создан и в plan нет изменений, terraform-compliance его не увидит. Это **не** инструмент аудита текущего state, это gate **на новые изменения**. - **Не понимает выражения.** `tags = local.standard_tags` в plan'е уже раскрыто в map (`{"CostCenter": "foo"}`), это ок. Но если значение `(known after apply)`, terraform-compliance не имеет данных для проверки и считает scenario как «не применимо». Это окно для обхода правила. - **Конкурирующий маркап.** Некоторые шаги от старых версий не работают в новых, документация хорошо отстаёт от changelog'а. Перед adoption зафиксируй версию (`==1.3.50`) и обновляй сознательно. - **CI-integration требует plan-файла.** Это значит pipeline: plan → show -json → terraform-compliance. Если plan уже артефакт между jobs (см. [tf-plan-apply-ci](/terraform/kb/tf-plan-apply-ci.md)) встраивается легко. Если pipeline линейный и plan живёт только в памяти, переделай. - **Не заменяет статический анализ HCL.** `terraform validate`, `tflint`, `checkov` работают на сорсах. terraform-compliance, на plan'е. Это разные слои; они должны быть оба. ## Команды ```bash pip install terraform-compliance ``` Установка. В CI лучше фиксированную версию: ==1.3.50. ```bash terraform plan -out=plan.tfplan && terraform show -json plan.tfplan > plan.json ``` Подготовить JSON-plan. Стандартный preprocessing-шаг. ```bash terraform-compliance -p plan.json -f ./policies ``` Запустить все feature-файлы из ./policies против plan.json. ```bash terraform-compliance -p plan.json -f ./policies --tags critical ``` Выборочно: только сценарии с тегом critical. ## См. также - [OPA + Rego, policy as code для Terraform plan](/terraform/kb/tf-policy-as-code.md) - [Что тестировать в Terraform, а что: не надо](/terraform/kb/iac-testing-theory.md) - [Checkov: статический анализ HCL](/terraform/kb/tf-checkov.md)