Что Checkov делает
Checkov берёт каталог с .tf файлами и проходит по нему ~2000 встроенных
правил. Каждое правило, конкретная проверка («S3 bucket has encryption»,
«IAM policy not wildcard»). Каждое имеет идентификатор: CKV_AWS_19,
CKV_K8S_8, и т.д. По идентификатору быстро находишь документацию.
Поддерживает: Terraform (HCL и plan.json), CloudFormation, Kubernetes
manifests, Helm, Dockerfile, GitHub Actions, и ещё с десяток форматов.
Здесь, про Terraform.
Минимальный запуск
checkov --directory .
Вывод (упрощённо):
Check: CKV_AWS_19: "Ensure all data stored in the S3 bucket is securely encrypted at rest"
FAILED for resource: aws_s3_bucket.logs
File: /main.tf:1-7
Check: CKV_AWS_53: "Ensure S3 bucket has block public ACLs enabled"
PASSED for resource: aws_s3_bucket.logs
...
Passed checks: 14, Failed checks: 3, Skipped checks: 0
Exit-code: 0, все pass, 1, есть failed. CI ставит exit-check на job.
HCL-режим vs plan.json-режим
| Режим | Команда | Плюсы | Минусы |
|---|---|---|---|
| HCL | checkov -d . | Не нужен terraform init | Видит только статически заданные значения; intercolation через var.x иногда теряется |
| plan.json | checkov -f plan.json | Видит вычисленные значения, computed-атрибуты, локали раскрыты | Требует init+plan, медленнее |
# plan.json режим
terraform init -backend=false
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json
checkov -f plan.json
Production-pipeline обычно использует plan.json, он точнее.
Suppression: пропустить правило
Иногда правило неприменимо. Например, aws_s3_bucket.web_assets
публичный по дизайну, отключаем CKV_AWS_53 («block public ACLs»).
Вариант 1: inline-комментарий. Прямо над ресурсом:
# checkov:skip=CKV_AWS_53: Public on purpose, see ADR-014
resource "aws_s3_bucket" "web_assets" {bucket = "linuxlab-public-assets"
}
Формат: checkov:skip=<CHECK_ID>: <причина>. Причина обязательна, без
неё checkov не примет suppression.
Вариант 2: глобальный skip. Если правило вообще не подходит проекту (например, использование IMDSv2 невозможно в твоей сети):
checkov -d . --skip-check CKV_AWS_79
Лучше зафиксировать в .checkov.yml:
# .checkov.yml
skip-check:
- CKV_AWS_79
Запуск автоматически подхватит файл.
Вариант 3: baseline. «Зафиксировать текущий уровень фейлов, ломать CI только на новых». Полезно для legacy.
checkov -d . --create-baseline
# генерирует .checkov.baseline с текущими findings
Потом в CI:
checkov -d . --baseline .checkov.baseline
Старые findings не fail'ят, новые, да. Постепенно чистишь baseline, поднимаешь планку. См. tf-checkov usage в production.
Конфигурационный файл
.checkov.yml в корне репо:
framework:
- terraform
- terraform_plan
output:
- sarif # для GitHub Security tab
- cli
skip-check:
- CKV_AWS_79
soft-fail-on:
- CKV_AWS_18 # warning, не error
download-external-modules: true # ходить за git/registry-модулями
Скан конкретных ресурсов или checks
Только check'и определённого фреймворка:
checkov -d . --framework terraform
Только одно правило (полезно для отладки):
checkov -d . --check CKV_AWS_19
Несколько:
checkov -d . --check CKV_AWS_19,CKV_AWS_20,CKV_AWS_53
Custom policies, свои правила
Если нужно правило, которого нет («все бакеты должны иметь тег CostCenter»), пишешь Python-класс:
# custom_policies/check_costcenter_tag.py
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckCategories, CheckResult
class CostCenterTagRequired(BaseResourceCheck):
def __init__(self):
super().__init__(
name="Ensure CostCenter tag is set",
id="CKV_CUSTOM_1",
categories=[CheckCategories.GENERAL_SECURITY],
supported_resources=["aws_s3_bucket", "aws_instance", "aws_db_instance"],
)
def scan_resource_conf(self, conf):
tags = conf.get("tags", [{}])[0]if "CostCenter" in tags:
return CheckResult.PASSED
return CheckResult.FAILED
check = CostCenterTagRequired()
Подключение:
checkov -d . --external-checks-dir ./custom_policies
Для большинства команд кастомные правила, это перебор; начни с встроенных и suppression'ов.
SARIF и GitHub Security
Checkov умеет выгружать SARIF, GitHub понимает этот формат и показывает findings в вкладке Security твоего репо.
checkov -d . -o sarif > checkov.sarif
Загрузка через GitHub Action:
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: checkov.sarif
Каждый finding, отдельный alert с location в коде и описанием правила.
Подводные камни
-
Checkov ловит много, но не всё. Правила покрывают известные шаблоны. Бизнес-логику и cross-resource политики (OPA/Rego/terraform-compliance) он не заменяет.
-
Suppression без причины, антипаттерн.
checkov:skip=CKV_AWS_19без объяснения = баг. Reviewer не знает, зачем пропустили. Reasoning обязателен и должен ссылаться на ADR/incident. -
HCL-режим теряет вычислимые значения.
var.encryption_enabled ? "AES256" : null, checkov на HCL может увидеть только null. Plan-mode раскрывает это и проверяет фактическое значение. -
--download-external-modulesходит в интернет. В air-gapped CI отключай или предзагружай. В обычном, без него внешние модули остаются непросканированными. -
Версии checkov ломают совместимость. Между релизами появляются новые правила (новые fails в CI без изменения кода), переименовываются ID'шки. Пиннуй версию в CI (
checkov==3.2.402), обновляй сознательно. -
Checkov не статический анализ HCL целиком. Не проверит синтаксис (
terraform validate), не проверит стиль (terraform fmt), не проверит tflint-правила. Это дополнение к ним, не замена.
См. также в LinuxLab
- bash-strict-mode, без
set -euo pipefailпайпы вокругcheckovмогут глотать ненулевой exit. Еслиcheckov | teeотрабатывает, а CI всё равно зелёный, этоteeпроглотил код возврата. - xargs-and-find-exec, для
pre-commit hooks с
find . -name '*.tf' | xargs checkov -fважно помнитьxargs -rчтобы пустой ввод не запустилcheckovс нулём аргументов.