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