Skip to content

Глава 19. Политика как код

«Если политика не в Git — её не существует.»

Zero Trust требует сотен политик: сетевых, identity-based, data access, compliance. Ручное управление ими не масштабируется. Policy as Code (PaC) — подход, при котором политики безопасности описываются в машиночитаемом формате, версионируются в Git и применяются автоматически.


19.1 Зачем: от ручных политик к автоматизации

Типичная организация управляет политиками через:

  • Таблицы в Confluence
  • Ручные чек-листы при деплое
  • Регулярные аудиты (раз в квартал)

Проблемы: политики устаревают, не применяются единообразно, аудит отстаёт от изменений.

Policy as Code решает три задачи:

ЗадачаРучной процессPolicy as Code
ОпределениеДокумент в WikiRego, Cedar, YAML
ПрименениеЧеловек проверяетCI/CD pipeline, admission controller
АудитКвартальная проверкаКаждый commit = проверка

NIST SP 800-207, тенет 4: «Access to resources is determined by dynamic policy.» Dynamic policy подразумевает автоматизацию — ручное одобрение каждого запроса невозможно при тысячах микросервисов.


19.2 Языки политик

OPA / Rego

Open Policy Agent (CNCF Graduated, январь 2021) — универсальный движок политик. Текущая версия: OPA v1.13.1 (январь 2026).

Rego v1 — язык политик OPA с улучшенным синтаксисом:

hcl
package terraform.security

import rego.v1

# Запретить S3 бакеты без шифрования
deny contains msg if {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket"
    not has_encryption(resource)
    msg := sprintf("S3 bucket '%s' must have encryption enabled", [resource.name])
}

has_encryption(resource) if {
    resource.change.after.server_side_encryption_configuration
}

Где используется OPA:

  • Kubernetes admission control (Gatekeeper, см. главу 13)
  • Terraform validation (conftest)
  • API authorization (Envoy ext_authz)
  • Data access control (см. главу 17, Lab)

Источник: openpolicyagent.org/docs/latest/policy-language

Cedar

Cedar — язык авторизации от AWS. Открыт в мае 2023 (Apache 2.0), с октября 2025 — проект CNCF Sandbox. Текущая версия: v4.9.0.

hcl
// Разрешить аналитикам читать данные своего отдела
permit (
    principal in Role::"Analyst",
    action == Action::"Read",
    resource
)
when {
    principal.department == resource.department &&
    context.device_compliant == true
};

Ключевые отличия Cedar от Rego:

ХарактеристикаOPA / RegoCedar
МодельGeneral-purpose policyAuthorization-focused
СинтаксисDatalog-likepermit/forbid statements
ВерификацияНетФормальная верификация (Cedar Analysis)
ПроизводительностьМиллисекундыМикросекунды (Rust)
ЭкосистемаCNCF Graduated, широкаяCNCF Sandbox, растущая

Где используется Cedar:

  • AWS Verified Access (см. главу 11)
  • AWS Verified Permissions
  • Cloudflare, MongoDB, StrongDM

Источник: docs.cedarpolicy.com, github.com/cedar-policy/cedar

Sentinel (HashiCorp)

Sentinel — проприетарный язык политик для Terraform Cloud/Enterprise. Не open source.

Три уровня применения:

УровеньПоведение при отказеПрименение
AdvisoryПредупреждение, run продолжаетсяИнформационные проверки
Soft-mandatoryБлокировка (с возможностью override)Важные политики
Hard-mandatoryБлокировка без overrideКритические требования
python
# sentinel: S3 bucket должен иметь versioning
import "tfplan/v2" as tfplan

main = rule {
    all tfplan.resource_changes as _, rc {
        rc.type is "aws_s3_bucket" implies
            rc.change.after.versioning[0].enabled is true
    }
}

Для организаций, использующих Terraform OSS (не Cloud), conftest + OPA — открытая альтернатива Sentinel.


19.3 Infrastructure as Code для Zero Trust

Terraform (v1.14.4, январь 2026) — стандарт для провизионирования ZT-инфраструктуры.

Паттерн: модульная ZT-инфраструктура

hcl
# modules/zt-vpc/main.tf — Zero Trust VPC
resource "aws_vpc" "main" {
  cidr_block           = var.cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name        = "${var.environment}-zt-vpc"
    ManagedBy   = "terraform"
    ZTComponent = "network"
  }
}

# Ни одна подсеть не должна быть public по умолчанию
resource "aws_default_security_group" "deny_all" {
  vpc_id = aws_vpc.main.id
  # Пустые ingress/egress = deny all по умолчанию
}

# Flow Logs для наблюдаемости (глава 18)
resource "aws_flow_log" "vpc" {
  vpc_id               = aws_vpc.main.id
  traffic_type         = "ALL"
  log_destination      = var.security_lake_s3_arn
  log_destination_type = "s3"
  max_aggregation_interval = 60
}

Ключевые провайдеры:

ОблакоПровайдерВерсия
AWShashicorp/awsv6.31.0
GCPhashicorp/googlev7.18.0
Azurehashicorp/azurermv4.x

19.4 GitOps для security policies

GitOps — паттерн, при котором Git-репозиторий является единственным источником истины для состояния кластера.

ArgoCD

ArgoCD (CNCF Graduated) — GitOps controller с UI. Текущая версия: v3.3.0 (февраль 2026).

Важно: ArgoCD v2.x достиг end-of-life в ноябре 2025 (v2.14 — последний релиз v2.x). Миграция на v3.x обязательна.

Применение security policies через ArgoCD:

yaml
# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: security-policies
  namespace: argocd
spec:
  project: security
  source:
    repoURL: https://github.com/org/security-policies.git
    targetRevision: main
    path: policies/production
  destination:
    server: https://kubernetes.default.svc
    namespace: kyverno
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Структура Git-репозитория:

security-policies/
├── policies/
│   ├── production/
│   │   ├── kyverno/           # Admission policies (глава 13)
│   │   ├── cilium/            # Network policies (глава 10)
│   │   └── istio/             # AuthorizationPolicy (глава 12)
│   └── staging/
├── compliance/
│   └── checkov/               # IaC validation rules
└── tests/
    └── policy-tests/          # OPA/Rego unit tests

Flux CD

Flux (CNCF Graduated) — GitOps toolkit. Текущая версия: v2.7.5.

yaml
# flux: Kustomization для security policies
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: security-policies
  namespace: flux-system
spec:
  interval: 5m
  path: ./policies/production
  prune: true
  sourceRef:
    kind: GitRepository
    name: security-policies
  healthChecks:
    - apiVersion: kyverno.io/v2
      kind: ClusterPolicy
      name: require-labels

ArgoCD занимает ~50% рынка GitOps, Flux ~11%. Оба CNCF Graduated, выбор зависит от предпочтений команды.


19.5 Compliance as Code

Автоматическая проверка IaC на соответствие стандартам безопасности.

Инструменты

ИнструментВерсияЧто проверяетЛицензия
Checkov3.2.500Terraform, K8s, CloudFormation, DockerfileApache 2.0
Trivyv0.69.1Контейнеры, IaC, SBOM, секретыApache 2.0
KICSv2.1.15Terraform, K8s, Docker, AnsibleApache 2.0

Консолидация: tfsec (Aqua Security) интегрирован в Trivy. Для новых проектов используйте Trivy.

Checkov в CI/CD

yaml
# GitHub Actions: проверка Terraform на безопасность
name: Security Scan
on: [pull_request]

jobs:
  checkov:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Checkov
        uses: bridgecrewio/checkov-action@v12
        with:
          directory: terraform/
          framework: terraform
          output_format: sarif
          # Пропуск конкретных проверок (с обоснованием)
          skip_check: CKV_AWS_144  # Cross-region replication not needed for lab

Trivy для IaC

bash
# Сканирование Terraform-конфигурации
trivy config --severity HIGH,CRITICAL ./terraform/

# Сканирование Kubernetes-манифестов
trivy config --severity HIGH,CRITICAL ./k8s/

# Генерация SBOM + проверка уязвимостей
trivy image --format spdx-json --output sbom.json myapp:latest

Источник: trivy.dev/latest/docs


19.6 Лаборатория: Terraform + OPA для валидации ZT-инфраструктуры

Цель

Настроить валидацию Terraform-планов с помощью conftest (OPA) для обеспечения Zero Trust требований.

Предварительные требования

  • Terraform CLI (v1.x)
  • conftest (brew install conftest)
  • OPA CLI (brew install opa)

Шаг 1: Terraform-конфигурация

bash
mkdir -p zt-policy-lab/terraform zt-policy-lab/policy

Файл terraform/main.tf:

hcl
terraform {
  required_version = ">= 1.0"
}

# Пример: S3 бакет (для проверки политикой)
resource "aws_s3_bucket" "data" {
  bucket = "zt-lab-data-bucket"
}

resource "aws_s3_bucket_versioning" "data" {
  bucket = aws_s3_bucket.data.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
  bucket = aws_s3_bucket.data.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "aws:kms"
    }
    bucket_key_enabled = true
  }
}

resource "aws_s3_bucket_public_access_block" "data" {
  bucket                  = aws_s3_bucket.data.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# Пример нарушения: Security Group с 0.0.0.0/0
resource "aws_security_group" "bad_example" {
  name        = "overly-permissive"
  description = "This should be flagged by policy"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # Нарушение: SSH открыт всему миру
  }
}

Шаг 2: Политики OPA

Файл policy/zt_security.rego:

hcl
package main

import rego.v1

# ZT-1: Запретить Security Groups с 0.0.0.0/0 на SSH
deny contains msg if {
    resource := input.resource_changes[_]
    resource.type == "aws_security_group"
    ingress := resource.change.after.ingress[_]
    ingress.cidr_blocks[_] == "0.0.0.0/0"
    ingress.from_port <= 22
    ingress.to_port >= 22
    msg := sprintf(
        "ZT-1: Security group '%s' allows SSH from 0.0.0.0/0. Use ZTNA instead.",
        [resource.name]
    )
}

# ZT-2: S3 бакеты должны иметь шифрование
deny contains msg if {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket"
    not has_encryption_config(resource.name)
    msg := sprintf(
        "ZT-2: S3 bucket '%s' must have server-side encryption.",
        [resource.name]
    )
}

has_encryption_config(bucket_name) if {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket_server_side_encryption_configuration"
    resource.change.after.bucket == bucket_name
}

# ZT-3: S3 бакеты должны блокировать публичный доступ
deny contains msg if {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket"
    not has_public_access_block(resource.name)
    msg := sprintf(
        "ZT-3: S3 bucket '%s' must have public access block.",
        [resource.name]
    )
}

has_public_access_block(bucket_name) if {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket_public_access_block"
    resource.change.after.bucket == bucket_name
    resource.change.after.block_public_acls == true
    resource.change.after.block_public_policy == true
}

Шаг 3: Генерация плана и проверка

bash
cd terraform

# Генерация плана в JSON
terraform init
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json

# Проверка плана политикой OPA
conftest test tfplan.json --policy ../policy/

# Ожидаемый результат:
# FAIL - tfplan.json - main - ZT-1: Security group 'bad_example' allows SSH
#   from 0.0.0.0/0. Use ZTNA instead.
#
# 2 tests, 1 passed, 0 warnings, 1 failure

Шаг 4: Интеграция в CI/CD

yaml
# .github/workflows/zt-policy-check.yaml
name: ZT Policy Check
on: [pull_request]

jobs:
  policy-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Init & Plan
        run: |
          cd terraform
          terraform init
          terraform plan -out=tfplan
          terraform show -json tfplan > tfplan.json

      - name: Install conftest
        run: |
          LATEST=$(curl -s https://api.github.com/repos/open-policy-agent/conftest/releases/latest | jq -r .tag_name)
          curl -sL "https://github.com/open-policy-agent/conftest/releases/download/${LATEST}/conftest_${LATEST#v}_Linux_x86_64.tar.gz" | tar xz
          sudo mv conftest /usr/local/bin/

      - name: Run ZT Policy Check
        run: conftest test terraform/tfplan.json --policy policy/

Очистка

bash
cd terraform && rm -f tfplan tfplan.json

19.7 Чек-лист

  • [ ] Политики безопасности описаны как код (Rego, Cedar, YAML)
  • [ ] Политики хранятся в Git с code review процессом
  • [ ] CI/CD pipeline включает валидацию политик (conftest, Checkov, Trivy)
  • [ ] GitOps controller (ArgoCD / Flux) применяет политики к кластерам
  • [ ] Terraform-конфигурации проверяются на ZT-соответствие перед apply
  • [ ] Compliance checks автоматизированы (CIS benchmarks, PCI DSS)
  • [ ] Sentinel или OPA enforcement настроен для critical policies (hard-mandatory)
  • [ ] Policy tests написаны и выполняются при каждом изменении

19.8 Итоги

Policy as Code — это операционная основа Zero Trust:

  1. Git = единый источник истины — все политики версионируются, ревьюятся и аудитируются через Git
  2. OPA + Rego — универсальный движок для Kubernetes, Terraform, API, data access (CNCF Graduated)
  3. Cedar — специализированный язык авторизации с формальной верификацией (CNCF Sandbox, растёт быстро)
  4. GitOps — ArgoCD/Flux обеспечивают автоматическое применение политик к кластерам
  5. Compliance as Code — Checkov, Trivy, KICS проверяют IaC до деплоя, ловя нарушения на этапе PR

Ключевой принцип: политика, которая не проверяется автоматически — не политика, а пожелание.

В следующей главе мы рассмотрим реагирование на инциденты в контексте Zero Trust: как принцип «предполагай взлом» меняет IR-процессы.

Опубликовано под лицензией CC BY-SA 4.0