Политики как код
Updated Jul 2026
Почему политики должны быть кодом
Инструменты статического анализа выявляют то, что terraform validate не может: ошибки конфигурации безопасности, нарушения комплаенса и несоответствия организационным политикам. Ключевой вывод: политики, записанные в документации, игнорируются, тогда как политики, записанные в коде, применяются автоматически при каждом коммите.
Политики как код превращают утверждения вроде «все S3-бакеты должны быть зашифрованы» из вики-страницы, которую разработчики забывают читать, в автоматический рубеж, блокирующий несоответствующую инфраструктуру от попадания в продакшен.
Сравнение инструментов
| Инструмент | Язык | Область применения | Скорость | Пользовательские правила | Интеграция с CI |
|---|---|---|---|---|---|
| tfsec | Go | Только Terraform | Очень быстро | Rego, YAML | Нативный GitHub Action |
| Checkov | Python | Terraform, CloudFormation, K8s, Helm, Dockerfiles | Быстро | Python | Все основные CI-системы |
| Trivy (режим config) | Go | Terraform, CloudFormation, K8s, Dockerfiles | Очень быстро | Rego | GitHub Action, шаблон GitLab |
| OPA/Conftest | Rego | Любые структурированные данные (JSON, YAML, HCL) | Быстро | Rego (нативно) | Любой CI через CLI |
| Bridgecrew | SaaS + Python | Множество фреймворков | Быстро | Python (расширяет Checkov) | Полная платформа + CLI |
| Snyk IaC | SaaS + CLI | Terraform, CloudFormation, K8s, ARM | Умеренно | Через UI | Все основные CI-системы |
Выбор между этими инструментами зависит от вашего стека, навыков команды и требований комплаенса. Многие команды используют несколько инструментов в комбинации — например, Checkov для широкого покрытия плюс OPA для пользовательских организационных политик.
OPA/Rego: универсальный движок политик
Open Policy Agent (OPA) оценивает структурированные данные по политикам Rego. Это наиболее гибкий подход, потому что он работает с любым форматом инфраструктуры — планами Terraform, манифестами Kubernetes, файлами Docker Compose или любой конфигурацией в JSON/YAML.
Написание политик на Rego
# policy/terraform/s3.rego
package terraform.s3
# Deny S3 buckets without encryption
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
not has_encryption(resource)
msg := sprintf("S3 bucket '%s' must have server-side encryption enabled", [resource.address])
}
has_encryption(resource) {
resource.change.after.server_side_encryption_configuration[_].rule[_].apply_server_side_encryption_by_default[_].sse_algorithm
}
# Deny public ACLs
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
acl := resource.change.after.acl
acl != "private"
msg := sprintf("S3 bucket '%s' has ACL '%s' -- must be 'private'", [resource.address, acl])
}
# Deny buckets without versioning
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
not has_versioning(resource)
msg := sprintf("S3 bucket '%s' must have versioning enabled", [resource.address])
}
has_versioning(resource) {
resource.change.after.versioning[_].enabled == true
}
Запуск OPA с Conftest
Conftest — это CLI-инструмент, который запускает политики OPA на конфигурационных файлах:
# Run policy against a Terraform plan
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
conftest test tfplan.json --policy policy/terraform/
# Run against Kubernetes manifests
conftest test k8s/deployment.yaml --policy policy/kubernetes/
# Run against Dockerfiles
conftest test Dockerfile --policy policy/docker/
# Run with multiple policy directories
conftest test tfplan.json \
--policy policy/security/ \
--policy policy/compliance/ \
--policy policy/cost/
Организация политик Rego по категориям
Хорошо организованный репозиторий политик разделяет ответственности:
policy/
terraform/
s3.rego # Правила для S3
rds.rego # Правила для RDS
iam.rego # Правила IAM-политик
networking.rego # Правила VPC, групп безопасности
tagging.rego # Требования к тегированию ресурсов
kubernetes/
security.rego # Безопасность подов, RBAC
resources.rego # Лимиты CPU/памяти
networking.rego # Сетевые политики
docker/
best_practices.rego # Линтинг Dockerfile
common/
helpers.rego # Общие вспомогательные функции
Продвинутые паттерны Rego
# policy/terraform/iam.rego
package terraform.iam
# Deny IAM policies with wildcard actions
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_iam_policy"
policy_doc := json.unmarshal(resource.change.after.policy)
statement := policy_doc.Statement[_]
statement.Effect == "Allow"
statement.Action[_] == "*"
msg := sprintf("IAM policy '%s' grants wildcard actions (*). Use specific actions.",
[resource.address])
}
# Deny IAM policies with wildcard resources on mutating actions
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_iam_policy"
policy_doc := json.unmarshal(resource.change.after.policy)
statement := policy_doc.Statement[_]
statement.Effect == "Allow"
statement.Resource[_] == "*"
action := statement.Action[_]
not is_readonly_action(action)
msg := sprintf("IAM policy '%s' uses wildcard resource with mutating action '%s'",
[resource.address, action])
}
is_readonly_action(action) {
endswith(action, ":Get*")
}
is_readonly_action(action) {
endswith(action, ":List*")
}
is_readonly_action(action) {
endswith(action, ":Describe*")
}
Checkov: всё включено
Checkov поставляется с более чем 1000 встроенных правил и не требует конфигурации для начала обнаружения проблем. Он особенно хорош для команд, которым нужна немедленная отдача без написания собственных политик.
Быстрый старт
# Scan a Terraform directory
checkov -d ./terraform/ --framework terraform
# Output example:
# Passed checks: 42, Failed checks: 3, Skipped: 0
#
# Check: CKV_AWS_18: "Ensure the S3 bucket has access logging enabled"
# FAILED for resource: aws_s3_bucket.data
# File: /main.tf:15-22
#
# Check: CKV_AWS_145: "Ensure S3 bucket is encrypted with KMS"
# FAILED for resource: aws_s3_bucket.data
# File: /main.tf:15-22
# Run only specific checks
checkov -d ./terraform/ --check CKV_AWS_18,CKV_AWS_145
# Skip specific checks (with justification)
checkov -d ./terraform/ --skip-check CKV_AWS_18 \
--skip-check-reason "Access logging handled by CloudTrail"
# Output as JSON for CI parsing
checkov -d ./terraform/ --output json > checkov-results.json
# Scan multiple frameworks at once
checkov -d . --framework terraform,kubernetes,dockerfile
Пользовательские политики Checkov на Python
Когда встроенных проверок недостаточно, пишите собственные политики на Python:
# custom_checks/s3_naming_convention.py
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
class S3NamingConvention(BaseResourceCheck):
"""Ensure S3 bucket names follow organizational naming convention."""
def __init__(self):
name = "Ensure S3 bucket follows naming convention: {team}-{env}-{purpose}"
id = "CUSTOM_S3_001"
supported_resources = ["aws_s3_bucket"]
categories = [CheckCategories.CONVENTION]
super().__init__(name=name, id=id, categories=categories,
supported_resources=supported_resources)
def scan_resource_conf(self, conf):
bucket_name = conf.get("bucket", [""])[0]
# Pattern: team-environment-purpose
parts = bucket_name.split("-")
if len(parts) < 3:
return CheckResult.FAILED
valid_envs = ["dev", "staging", "prod", "test"]
if parts[1] not in valid_envs:
return CheckResult.FAILED
return CheckResult.PASSED
check = S3NamingConvention()
Интеграция с pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/bridgecrewio/checkov
rev: '3.2.0'
hooks:
- id: checkov
args: ['--compact', '--framework', 'terraform']
Комбинирование инструментов в CI-пайплайне
Наиболее надёжный подход использует несколько инструментов, каждый из которых выявляет разные классы проблем:
# .github/workflows/iac-policy.yml
name: IaC Policy Checks
on:
pull_request:
paths:
- 'terraform/**'
- 'k8s/**'
jobs:
policy-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: tfsec (fast, Terraform-specific)
uses: aquasecurity/tfsec-action@v1.0.0
with:
working_directory: ./terraform/
soft_fail: false
- name: Checkov (broad coverage, multi-framework)
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: terraform,kubernetes,dockerfile
output_format: cli,json
output_file_path: console,checkov-results.json
- name: OPA/Conftest (custom organizational policies)
run: |
terraform -chdir=terraform plan -out=tfplan
terraform -chdir=terraform show -json tfplan > tfplan.json
conftest test tfplan.json --policy policy/ --output json > opa-results.json
- name: Trivy config scan (Dockerfiles + K8s)
uses: aquasecurity/trivy-action@master
with:
scan-type: 'config'
scan-ref: '.'
severity: 'HIGH,CRITICAL'
Выбор комбинации
| Профиль команды | Рекомендуемый стек | Обоснование |
|---|---|---|
| Небольшой стартап, только Terraform | tfsec + Checkov | Быстрая настройка, широкое покрытие, пользовательские политики не нужны |
| Корпорация, мультиоблако | Checkov + OPA/Conftest | Checkov для широких проверок, OPA для пользовательского комплаенса |
| Фокус на безопасности | tfsec + OPA + Snyk IaC | Глубокая защита, несколько движков сканирования |
| Kubernetes-ориентированные | Checkov + Polaris + OPA | Специализированные проверки K8s + пользовательские политики |
Ключевой принцип: статические проверки политик должны выполняться менее чем за 60 секунд и блокировать слияние при критических нарушениях. Это ваш наиболее экономически эффективный рубеж контроля качества.