К основному содержанию
скилл CX Codex

tf-best-practices — скилл для Claude Code: правила AWS Terraform

Задаёт правила безопасности для генерируемого AWS Terraform и после записи проверяет каталог terraform/ на соответствие политике. Только чтение: файлы не правит.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add aws/agent-toolkit-for-aws --skill tf-best-practices -a claude-code
Открыть на GitHub

Что делает tf-best-practices

Скилл работает в двух точках. Перед тем как агент начнёт писать terraform/, он загружает часть с правилами: что вообще допустимо выпускать в AWS-конфиге. После записи — запускает проверку и выдаёт вердикт. Вызывающий сам сообщает, в какой точке он находится.

Правила разбиты на три уровня. Первый проверяется статически: TLS на ALB, отсутствие публичных баз данных, шифрование RDS и ElastiCache, запрет wildcard в IAM. Второй уровень проверкой не ловится, но всё равно обязателен: deletion_protection, пароль мастера через Secrets Manager, приватные подсети, бэкапы. Третий включается, когда вызывающий объявляет soc2, pci, hipaa или fedramp — тогда добавляются VPC flow logs, логирование доступа к S3, ротация секретов и customer-managed KMS.

Проверка запускается скриптом validate-terraform-policy.py из каталога плагина, путь к terraform/ передаёт вызывающий. Коды выхода простые: 0 — POLICY_OK, 1 — POLICY_FAIL с перечнем нарушений, 2 — ошибка. Скилл ничего не редактирует и не решает, завершена ли фаза: правки, цикл повторных попыток и запись состояния остаются на стороне вызывающего. Он дополняет terraform fmt, init и validate, а не заменяет их — это повод держать оба шага в пайплайне.

Какие задачи решает

  • проверить сгенерированный AWS Terraform на дыры в безопасности до деплоя
  • задать агенту единые правила выпуска конфигов перед записью terraform/
  • получить машинно-читаемый вердикт для validation-report.json
  • поймать публичный порт базы данных или wildcard в IAM
  • включить требования compliance-фреймворка в генерацию

Примеры запросов агенту

  • Загрузи tf-best-practices перед тем, как писать terraform/, и следуй правилам безопасности
  • terraform/ готов — прогони policy-гейт tf-best-practices и покажи вердикт
  • Проверь сгенерированный terraform/ скиллом tf-best-practices, объявленные фреймворки: soc2

Как установить tf-best-practices

1Через Skills CLI (Vercel)

npx skills add aws/agent-toolkit-for-aws --skill tf-best-practices -a claude-code

2Вручную: положить файлы

~/.claude/skills/tf-best-practices/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/tf-best-practices/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о tf-best-practices

Как установить tf-best-practices в Claude?

Выполните npx skills add aws/agent-toolkit-for-aws --skill tf-best-practices -a claude-code. Скилл окажется в ~/.claude/skills/tf-best-practices/SKILL.md.

Что делает tf-best-practices?

Перед генерацией объясняет, какую security-политику должен соблюдать AWS Terraform, а после записи каталога запускает проверку и выдаёт вердикт с перечнем нарушений.

Скилл сам правит .tf файлы?

Нет. Он только читает и сообщает результат. Исправления, повторные прогоны и решение о завершении фазы остаются за вызывающим скиллом.

Исходный текст

SKILL.md · Apache-2.0
---
name: tf-best-practices
description: >-
  Best-practice authoring guidance AND a read-only policy gate for AWS Terraform generated by a
  migration skill. Load during any phase that writes a terraform/ directory — first as the "what to
  emit" posture rules + security-baseline spec, then after writing as the deterministic policy verdict.
  Read-only: it reports whether the generated Terraform passes; it never edits .tf files, never touches
  .phase-status.json, and never decides phase completion. Complements (does not replace) terraform
  fmt/init/validate.
---

# tf-best-practices — Generated-IaC posture rules + read-only policy gate

A **shared authoring guide and verdict producer**, not a workflow. It answers two
questions for a phase that generates AWS Terraform:

1. **Before writing** — "what security posture must the generated `terraform/` follow?"
   (the posture rules + the `baseline.tf` account-hardening spec)
2. **After writing** — "does the generated `terraform/` pass policy?" (a deterministic,
   **read-only** verdict + a machine-readable report)

## Routing — load the part that matches your context

This skill is entered at two touchpoints in the caller's Generate flow, with the caller's
own terraform-authoring work in between. **The caller states which touchpoint it is at when it
loads this skill**, and reads the corresponding part:

| Caller context                                              | Load                                                                                                      | Why                                                                                               |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| **About to author `terraform/`** (before writing)           | Part 1 → [`references/security-posture-rules.md`](references/security-posture-rules.md)                   | The "what to emit" AWS authoring rules (gate-enforced + authoring-only + compliance-conditional). |
| **`terraform/` written, ready to validate** (after writing) | Part 2 → [`references/terraform-validation.md`](references/terraform-validation.md) + run the gate script | The `fmt → init → validate → policy` protocol and the read-only verdict.                          |

Everything this skill states is **source-cloud-agnostic** (pure AWS Terraform). Any GCP/Heroku
detection or artifact reading is the caller's job; where a rule needs a caller-known fact (e.g.
declared compliance frameworks), the caller passes it as a **caller-context signal** — see
`references/security-posture-rules.md` § _Caller-context signals_.

## Boundary (read this first)

This unit is a **verdict producer, never a mutator**. Its entire write surface is the
JSON verdict it is asked to emit. Specifically it **MUST NOT**:

- edit, format, or rewrite any `.tf` file (the caller owns remediation),
- read or write `.phase-status.json` or any run-state file (interpreter-owned),
- decide whether a phase may complete, or prompt the user (caller policy).

The caller (a migration skill's Generate phase) owns: the fix-and-retry loop that edits
the `.tf` it generated, `terraform fmt` auto-apply, the retry/skip/abort prompt, the
Phase Completion gate, and every `.phase-status.json` write. See the consuming skill's
generate phase for how the verdict feeds those decisions.

> **Consumers:** `gcp-to-aws` (prose Generate) and `heroku-to-aws` (DSL Generate). The
> contract is source-agnostic; each caller wires the two touchpoints in its own Generate
> idiom — gcp-to-aws as prose steps, heroku-to-aws as a fragment step plus a fail-closed
> `_postconditions` assert enforced by the interpreter.

## Part 1 — Authoring posture (load before writing `terraform/`)

Emit generated Terraform that satisfies the posture in
[`references/security-posture-rules.md`](references/security-posture-rules.md).

These are the "what good AWS Terraform looks like" rules. Following them makes the Part 2 gate
pass by construction. This unit does not read the caller's artifacts — it consumes only
caller-context signals the caller passes in.

> **Scope.** `security-posture-rules.md` covers, in three tiers:
>
> - **Gate-enforced** (Part 2 verifies statically): ALB TLS, no-public-database, RDS +
>   ElastiCache encryption-at-rest, no-public-DB-port ingress, no-public admin/datastore-port
>   ingress, no-wildcard-IAM.
> - **Authoring-only** (not gate-checkable, still required): `deletion_protection`,
>   master-password-via-Secrets-Manager, S3 hardening, Fargate/EKS/ECR settings, private-subnet
>   placement, backups, baseline monitoring.
> - **Compliance-conditional** (emitted when the caller declares `soc2`/`pci`/`hipaa`/`fedramp`):
>   VPC flow logs, S3 access logging, secret rotation, customer-managed KMS.
>
> Still the **caller's** own generation concern (candidates to migrate here later): the
> account-hardening `baseline.tf` layer (CloudTrail, GuardDuty, Config, Security Hub).

## Part 2 — Policy gate (run after writing `terraform/`)

Run the read-only checker against the generated directory. Resolve the script path relative to
the plugin root (`$PLUGIN_ROOT/skills/tf-best-practices/scripts/...`), the same convention the
plugin uses for its other scripts:

```bash
python3 "$PLUGIN_ROOT/skills/tf-best-practices/scripts/validate-terraform-policy.py" "$TERRAFORM_DIR" --json "$VERDICT_PATH"
```

- `$TERRAFORM_DIR` — **required, caller-supplied**: the generated `terraform/` directory
  (e.g. `$MIGRATION_DIR/terraform`). This skill never defaults or discovers it — the caller
  always passes the path it wrote Terraform to.
- `--json $VERDICT_PATH` — optional; writes a machine-readable verdict the caller can merge
  into its own `validation-report.json`.

The policy check is one stage of a larger validation flow (`fmt → init → validate → policy`).
The full protocol — including offline-fallback behavior and how the policy verdict maps into a
`validation-report.json` — is documented in
[`references/terraform-validation.md`](references/terraform-validation.md). That protocol is
descriptive: the **caller** owns the fmt/init/validate execution, the fix-and-retry loop, and
the report write; this unit contributes only the read-only policy stage + verdict shape.

### Exit codes → caller action

| Exit | stdout        | Meaning            | Caller does                                                                     |
| ---- | ------------- | ------------------ | ------------------------------------------------------------------------------- |
| `0`  | `POLICY_OK`   | posture satisfied  | proceed                                                                         |
| `1`  | `POLICY_FAIL` | violations present | read `violations[]`, edit the named `.tf` sites, re-run (caller's retry budget) |
| `2`  | (usage error) | bad path / IO      | surface to user; do not treat as pass                                           |

### Verdict shape (`--json`)

```json
{
  "check": "policy",
  "policy_status": "POLICY_OK | POLICY_FAIL",
  "violations": [
    {
      "check": "policy",
      "rule": "alb_https_listener | alb_http_redirect | no_tf_files",
      "file": "compute.tf",
      "line": 7,
      "severity": "error",
      "summary": "human-readable violation",
      "fix_hint": "concrete remediation the caller can apply"
    }
  ]
}
```

Each `violations[]` entry is **actionable evidence** — `file` + `line` + `fix_hint` tell the
caller exactly what to edit. The caller applies the edit; this unit only reports.

## Policy rules enforced today

Every rule is **fail-open on ambiguity** — it fires only on unambiguous, in-block literal
evidence, so a valid stack is never falsely blocked (a `POLICY_FAIL` is a hard completion gate
for the caller, so a false positive would block a real migration).

**Internet-facing ALB TLS posture** (an ALB is internet-facing when `internal` is absent,
`false`, or variable-driven — fail-safe):

- **`alb_https_listener`** — must have an HTTPS listener on `443` with `certificate_arn` and a
  `forward` action.
- **`alb_http_redirect`** — an HTTP `:80` listener must `redirect` to HTTPS, never `forward`
  to targets. Internal ALBs (`internal = true`) are exempt.

> **Elastic Beanstalk ALBs are invisible to these rules.** The ALB rules inspect standalone
> `aws_lb_listener` blocks. An EB **LoadBalanced** environment provisions its ALB from
> `aws_elastic_beanstalk_environment` `setting` blocks, which the static checker does not read —
> so a pure-EB design passes the ALB rules **vacuously** (no listener to inspect). EB listener/TLS
> posture is therefore authoring-only, not gate-enforced. (Fixtures `good-heroku-eb-only`
> and `good-heroku-eb-singleinstance` document this; `good-heroku-eb-loadbalanced` carries a
> standalone ALB so the listener rules are exercised on real blocks.)

**Managed database exposure & encryption** (`aws_db_instance`, `aws_rds_cluster`):

- **`rds_not_public`** — must not set `publicly_accessible = true` (absent/variable → fail-open).
- **`rds_encryption_at_rest`** — must set `storage_encrypted = true`; missing or literal `false`
  fires (RDS defaults to unencrypted), variable-driven fails open. S3 is not checked (default
  SSE-S3 since Jan 2023).

**ElastiCache encryption** (`aws_elasticache_replication_group`, Redis `aws_elasticache_cluster`):

- **`elasticache_encryption_at_rest`** — a replication group must set
  `at_rest_encryption_enabled = true`; missing or literal `false` fires, variable-driven fails
  open.
- **`elasticache_cluster_encryption`** — a Redis-engine `aws_elasticache_cluster` (single-node:
  `engine = "redis"`, no `replication_group_id`) must set BOTH `at_rest_encryption_enabled = true`
  and `transit_encryption_enabled = true`; missing or literal `false` on either fires,
  variable-driven fails open. `engine = "memcached"` clusters (and variable-driven/absent engine)
  are exempt — Memcached does not support these attributes.

**Security group ingress:**

- **`db_sg_no_public_ingress`** — an inline `aws_security_group` ingress covering `5432`/`3306`
  must not allow `0.0.0.0/0` or `::/0`.
- **`sg_no_public_admin_ingress`** — an inline ingress must not open a curated never-public
  admin/datastore port (`22`, `3389`, `6379`, `11211`, `27017`, `9200`/`9300`, `5601`) to
  `0.0.0.0/0` or `::/0`. Web (`80`/`443`) and app/game ports are not flagged; DB ports are
  handled by the rule above. Both check `cidr_blocks` and `ipv6_cidr_blocks` independently, so a
  benign IPv4 list does not mask an open IPv6 one. Both: separate `aws_security_group_rule` /
  `aws_vpc_security_group_ingress_rule` resources fail open (not correlated).

**IAM least-privilege** (`aws_iam_policy`, `aws_iam_role_policy`, `aws_iam_group_policy`,
`aws_iam_user_policy`):

- **`no_wildcard_iam`** — an `Allow` statement must not use `Action`/`Resource` `"*"`.
  The one narrow exception is an isolated
  `elasticbeanstalk:CreateStorageLocation` statement with `Resource = "*"` because
  AWS does not support resource-level permissions for that action.
  `aws_iam_policy_document` data sources and assume-role trust policies fail open.

> The checker is a zero-dependency static HCL reader (no `terraform init`, no provider
> download) — it runs even when the registry is unreachable. It uses brace-depth matching
> for nested blocks, so a valid HTTPS listener written with a nested `forward { ... }`
> block is **not** a false failure.

## Fixtures (also the checker's regression suite)

`fixtures/terraform-policy/` holds **intentionally-shaped** Terraform used by
`scripts/test_validate_terraform_policy.py`:

- `bad-http-forward/` — internet-facing ALB that forwards plaintext HTTP → MUST `POLICY_FAIL`.
- `internal-alb-only/` — internal ALB on HTTP → MUST `POLICY_OK` (HTTP allowed internally).
- `good-https-redirect/` — the correct pattern → `POLICY_OK`.

These are deliberately non-compliant test data (never deployed). They are excluded from the
repo-wide `checkov` scan via `.checkov.yaml` `skip-path`; do **not** "harden" them — doing so
breaks the tests that assert the failure paths.

## Verification

```bash
# from skills/tf-best-practices/
uv run --python 3.12 --with pytest python -m pytest scripts/test_validate_terraform_policy.py -q
```

© aws · Apache-2.0 · aws/agent-toolkit-for-aws

Похожие скиллы

Всё по теме «DevOps и инфраструктура» →
terraform-engineer https://github.com/Jeffallan Скилл для написания и управления инфраструктурой через Terraform. Помогает проектировать модули, настраивать удалённое состояние, валидировать код и применять изменения безопасно. CX Codex +1 5 400установок iac-terraform-data-engineering reason-machines Скилл для Claude и других ИИ-агентов: помогает описывать инфраструктуру AWS под данные в Terraform — бакеты S3, инстансы EC2, роли IAM. CX Codex +1 1 800установок iac-data-engineering-terraform reason-machines Скилл с готовыми шаблонами Terraform для дата-инженерии: бакеты S3, инстансы EC2 и роли IAM. Пригодится, когда нужно поднять инфраструктуру под пайплайны декларативно. CX Codex +1 1 800установок terraform-aws devops-skills Разворачивает инфраструктуру AWS через Terraform, настраивает модули и хранение стейта. Пригодится при декларативном описании облачных ресурсов. CX Codex +1 387установок aws-well-architected-review официальный github Проводит аудит инфраструктурного кода по 6 столпам AWS Well-Architected Framework и заводит задачи в GitHub с готовыми рецептами исправлений. 84установок firewall-config devops-skills Скилл для настройки хостовых и облачных фаерволов: правила iptables, nftables, UFW и security groups. Пригодится, когда закрываешь периметр сервера или делишь сеть на зоны. CX Codex +1 458установок

Из того же набора133

amazon-eventbridge-event-bus Скилл для сборки и отладки приложений на новых кастомных шинах событий EventBridge. Пригодится, когда события расходятся по подписчикам и что-то не доходит. CX Codex +1 1 000установок aws-marketplace-metering Скилл разворачивает и отлаживает usage-based метринг AWS Marketplace: SAM-пайплайн, ResolveCustomer, BatchMeterUsage, разбор записей и ошибок. CX Codex +1 983установок testing-mwaa-workflow Скилл запускает и проверяет пайплайны в Amazon MWAA до финального статуса. Он помогает протестировать Python DAG или Serverless-сценарий перед сдачей в работу. CX Codex +1 861установок agents-pay Настраивает оплату x402-защищённого контента агентом во время задачи и ограничивает расходы правилами и бюджетом сессии. CX Codex +1 809установок aws-lambda-web-functions Помогает собрать и выложить Node.js HTTP-приложение на AWS Lambda Web Functions: Express, Fastify или Hono, локальный запуск, упаковка и деплой через CLI. CX Codex +1 507установок agent-advisor Ведёт от идеи агента до исполняемого POC на AWS: подбирает рантайм по баллам и планирует миграцию существующих нагрузок. CX Codex +1 316установок aws-data-analytics Плагин от AWS добавляет в Claude скиллы для работы с озёрами данных, каталогами и ETL на стороне Amazon. ★ 3 282звёзд репо aws-agents-for-devsecops Плагин связывает Claude с AWS DevOps Agent и AWS Security Agent: разбор инцидентов, проверка релиза, сканирование кода и пентест. ★ 3 282звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой