Przejdź do głównej zawartości

Infrastruktura jako kod z agentami AI

Infrastruktura jako kod z agentami AI działa wtedy, gdy agent pisze i planuje zmianę, ale nigdy jej nie aplikuje. Claude Code, Codex lub Cursor tworzą Terraform, CloudFormation, CDK albo Pulumi na podstawie aktualnych schematów dostawców; deterministyczne bramki, maszynowo czytany plan i cykliczna kontrola dryfu dowodzą wyniku, a CI aplikuje zmianę po akceptacji planu przez wskazanego właściciela.

Dziedziczysz repozytorium Terraform bez dokumentacji, inżynier platformy, który je napisał, już odszedł, a replikę odczytu w drugim regionie trzeba mieć do piątku. Agent przeczyta moduły i napisze zmianę w kilka minut. Ryzyko kryje się gdzie indziej: w argumencie dostawcy wymyślonym na podstawie nieaktualnych danych treningowych, w zmianie nazwy, którą plan zamienia w destroy, albo w agencie z twoim profilem administratora, który uruchamia terraform apply, bo w prompcie padło „wdróż to”.

Ta strona jest dla deweloperów, którzy zmieniają infrastrukturę z pomocą agenta, i dla tech leadów, którzy decydują, czego agent może dotykać.

  • Podział pracy, w którym agent pisze i planuje, CI aplikuje, a człowiek akceptuje plan zamiast czytać każdą linię HCL.
  • Zabezpieczenia dla wszystkich trzech narzędzi: tożsamość chmurową tylko do odczytu, instrukcje w repozytorium i reguły poleceń blokujące apply i destroy.
  • Konfigurację MCP i skilli, która opiera odpowiedzi agenta na aktualnym Terraform Registry i dokumentacji AWS IaC, razem z nazwami pakietów, które są błędne.
  • Zestaw bramek dla każdego narzędzia IaC (Terraform lub OpenTofu, CloudFormation, CDK, Pulumi), uruchamianych, zanim ktokolwiek spojrzy na zmianę.
  • Cztery prompty do skopiowania: brief z ograniczeniami, zmianę za bramkami, podsumowanie planu dla recenzenta i triaż dryfu.
  • Kroki naprawcze dla blokad stanu, rozjechanych wersji dostawcy, ukrytych zastąpień zasobów i dryfu.

Szybkość agenta jest bezpieczna tylko wtedy, gdy niebezpieczne kroki są poza jego zasięgiem. Ustal podział przed pierwszym promptem:

KrokAgentCICzłowiek
Czytanie repozytorium, sprawdzanie schematów dostawcyTak
Pisanie HCL, szablonów albo kodu CDK/PulumiTak
fmt, validate, linter, skan bezpieczeństwa, testyUruchamia lokalnieUruchamia ponownie jako bramkę
plan / preview / synthLokalnie, z tożsamością tylko do odczytuWiążący plan na pull requeście
Podsumowanie planu i oznaczenie usunięćTakPrzerywa build przy niezatwierdzonych usunięciachPorównuje podsumowanie z planem
apply / up / deployNigdyPo akceptacji, z zapisanego planuAkceptuje; odpowiada za rollback
Operacje na stanie (force-unlock, state rm)Nigdy bez pytaniaDecyduje

Akceptuje właściciel zmienianego workspace’u lub stacka, a nie autor promptu. Akceptacja dotyczy planu (tego, co zmieni się w chmurze), który jest mniejszym i uczciwszym artefaktem niż diff.

  1. Daj agentowi tożsamość tylko do odczytu. Utwórz w chmurze rolę lub profil, który może czytać zasoby i stan, ale nie może ich zmieniać, i niech to będzie jedyne poświadczenie w środowisku, w którym działa agent. Żadnego produkcyjnego profilu administratora, żadnego długowiecznego klucza do wdrożeń na tej maszynie. W AWS do planowania wystarczy rola z zarządzaną polityką ReadOnlyAccess plus dostęp do bucketu ze stanem (przy use_lockfile plan zapisuje też obiekt blokady obok stanu). Tę samą konfigurację dla AWS, Azure i Google Cloud opisuje strona o serwerach MCP chmury z tożsamościami tylko do odczytu.

  2. Zapisz reguły w instrukcjach repozytorium. Umieść je w AGENTS.md dla Codeksa, w CLAUDE.md dla Claude Code (który sięga po AGENTS.md tylko wtedy, gdy nie ma CLAUDE.md, od v2.1.277 w kanale latest) i w regule projektu w katalogu .cursor/rules/ dla Cursora (format pliku i frontmatter opisuje strona o regułach projektu w Cursorze):

    ## Infrastructure rules
    - Never run terraform apply, destroy, import or force-unlock, pulumi up or destroy, or cdk deploy. CI applies.
    - Before writing a resource, look up its arguments for the provider version pinned in versions.tf.
    - Every change must pass: terraform fmt -check, terraform validate, tflint, trivy config, terraform test.
    - Renaming or moving a resource requires a moved block. A plan with an unexplained replace is a failed change.
    - No wildcard IAM actions, no 0.0.0.0/0 ingress, encryption at rest on every storage resource.
  3. Wzmocnij instrukcje regułami poleceń. Instrukcje można zignorować, reguł poleceń nie. Każde narzędzie robi to inaczej:

    W .claude/settings.json:

    {
    "permissions": {
    "deny": [
    "Bash(terraform apply)",
    "Bash(terraform apply *)",
    "Bash(terraform destroy *)",
    "Bash(terraform import *)",
    "Bash(terraform force-unlock *)",
    "Bash(tofu apply)",
    "Bash(tofu apply *)",
    "Bash(tofu destroy *)",
    "Bash(tofu import *)",
    "Bash(tofu force-unlock *)",
    "Bash(pulumi up)",
    "Bash(pulumi up *)",
    "Bash(pulumi destroy *)",
    "Bash(cdk deploy)",
    "Bash(cdk deploy *)",
    "Bash(cdk destroy *)",
    "Bash(npx cdk deploy)",
    "Bash(npx cdk deploy *)",
    "Bash(npx cdk destroy *)"
    ],
    "ask": [
    "Bash(terraform state rm *)",
    "Bash(terraform state mv *)",
    "Bash(terraform state push *)",
    "Bash(tofu state rm *)",
    "Bash(tofu state mv *)",
    "Bash(tofu state push *)"
    ]
    }
    }

    Lista zawiera zarówno samo polecenie (terraform apply), jak i formę z argumentami (terraform apply *), więc reguła nie zależy od tego, czy końcowy wildcard pasuje też do polecenia bez argumentów. Reguły ask sprawiają, że Claude Code zatrzymuje się i pyta przed operacjami na stanie, tak jak reguła prompt w Codeksie poniżej.

Modele piszą argumenty dostawców z danych treningowych, które nie nadążają za dostawcami. Dostawca AWS dla Terraform był we wrześniu 2026 na linii 6.x, zgodnie z jego changelogiem; model, który wpisuje ~> 5.0, zgaduje. Większość tego problemu usuwa serwer MCP czytający registry plus skille od producenta.

StosNa czym go oprzećCo to daje
Terraform / OpenTofuSerwer MCP Terraform od HashiCorp (obraz Dockera hashicorp/terraform-mcp-server)Zapytania do registry: wersje dostawców, dokumentacja zasobów, moduły. Workspace’y HCP Terraform z tokenem
Styl TerraformSkille HashiCorp (hashicorp/agent-skills)terraform-style-guide, terraform-test, refactor-module, terraform-search-import
CloudFormation / CDKawslabs.aws-iac-mcp-server (PyPI)Walidacja cfn-lint, zgodność cfn-guard, diagnoza nieudanych stacków, dokumentacja i przykłady CDK
Pulumi@pulumi/mcp-server (npm 0.2.0, ostatnia publikacja 2025-09)Zapytania do registry, preview, refresh. Udostępnia też pulumi-cli-up i deploy-to-aws (zwraca instrukcje, które kierują agenta do tworzenia zasobów AWS; oba sprawdzone w pakiecie 0.2.0), a reguły poleceń powłoki nie łapią żadnego z nich: zablokuj same narzędzia (w Claude Code dodaj mcp__pulumi__pulumi-cli-up i mcp__pulumi__deploy-to-aws do permissions.deny, o ile serwer zarejestrowano pod nazwą pulumi, na przykład przez claude mcp add pulumi -- npx @pulumi/mcp-server@0.2.0 stdio; prefiks to mcp__<nazwa-serwera>__) albo nie rejestruj serwera i oprzyj się na tożsamości tylko do odczytu, która blokuje je w obu przypadkach
Odczyty z żywego AWSAgent Toolkit for AWSOdczyty konta przez zarządzany AWS MCP Server

Zarejestruj dwa serwery, których potrzebuje większość pracy z IaC:

Okno terminala
# Terminal, root repozytorium. Serwer Terraform tylko z registry, przypięty obraz
claude mcp add terraform -s project -- docker run -i --rm hashicorp/terraform-mcp-server:1.3.0
# Walidacja CloudFormation i CDK; poświadczenia z profilu tylko do odczytu
claude mcp add aws-iac -s project -e AWS_PROFILE=agent-readonly -- uvx awslabs.aws-iac-mcp-server@latest
claude mcp list

Skille HashiCorp dodasz w Claude Code poleceniem claude plugin marketplace add hashicorp/agent-skills, a potem claude plugin install terraform@hashicorp; w pozostałych narzędziach instaluj je pojedynczo, na przykład npx skills add hashicorp/agent-skills/plugins/terraform/skills/terraform-style-guide. Konfigurację tokena HCP Terraform, listy dozwolonych narzędzi i koszt kontekstu każdego serwera opisuje strona MCP dla infrastruktury: Docker, Kubernetes i Terraform.

„Utwórz klaster EKS z trzema węzłami” daje generyczny klaster. Opisz ograniczenia biznesowe i poproś agenta, żeby przed napisaniem kodu wymienił swoje założenia. Ten prompt działa tak samo we wszystkich trzech narzędziach.

Punkt 4 jest tu najważniejszy. Wyciąga miejsca, w których agent zgaduje (czy baza źródłowa jest szyfrowana kluczem, który da się współdzielić między regionami? czy budżet jest miesięczny, czy na środowisko?), dopóki korekta kursu kosztuje jedną wiadomość. Punkt 5 zmusza agenta do przemyślenia zasięgu skutków, zanim czegokolwiek dotknie.

Niech agent napisze zmianę i uruchamia każde deterministyczne sprawdzenie, dopóki wszystkie nie przejdą. Decydują kody wyjścia, a nie relacja agenta o nich.

StosBramki, które uruchamia agent i powtarza CI
Terraformterraform fmt -check -recursive · terraform validate · tflint --recursive · trivy config . lub checkov -d . · terraform test
OpenTofuTo samo z tofu zamiast terraform
CloudFormationcfn-lint template.yaml · cfn-guard validate -d template.yaml -r rules/
CDKcdk synth z zarejestrowanym cdk-nag, tak aby problemy bezpieczeństwa przerywały synth
Pulumipulumi preview --policy-pack ./policy z pakietem polityk CrossGuard

W CDK cdk-nag 3.x rejestruje się jako plugin walidacji: Validations.of(app).addPlugins(new AwsSolutionsChecks(app)); w punkcie wejścia aplikacji.

Moduł główny (root module) z aktualnymi wersjami przypina to, co modele najczęściej psują:

terraform {
required_version = ">= 1.11"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
backend "s3" {
bucket = "acme-tf-state-prod"
key = "platform/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true # natywne blokowanie w S3; nowy projekt nie potrzebuje tabeli blokad w DynamoDB
}
}

Skanery bezpieczeństwa zgłaszają za dużo (WAF wymagany na wewnętrznym load balancerze), a agent za mało (akcja IAM z wildcardem, którą sam napisał). Skaner zostaw jako bramkę, a każde wyciszenie traktuj jako przejrzaną linię w konfiguracji skanera z uzasadnieniem, nigdy jako ciche pominięcie, które agent dodaje, żeby build zrobił się zielony.

Recenzent nie czyta HCL linia po linii. Czyta plan, który mówi, co stanie się w chmurze, a CI pilnuje, żeby w planie nie było niespodzianki, której recenzent nie zatwierdził.

  1. Zapisz plan jako JSON w CI. Job działa z rolą, która może tylko planować i nie sięga dalej niż odczyt stanu i zasobów oraz zapis obiektu blokady:

    Okno terminala
    terraform plan -out tfplan
    terraform show -json tfplan > plan.json

    Plan wykonuje kod z pull requesta: binaria dostawców, programy data "external" i źródła modułów. Dlatego job planu z poświadczeniami uruchamiaj tylko dla gałęzi z tego samego repozytorium, na wyzwalaczu pull_request, który nie przekazuje sekretów forkom. Nigdy nie używaj pull_request_target do checkoutu głowy pull requesta. Fork kontrybutora planuj dopiero wtedy, gdy maintainer przeczyta zmianę i wypchnie ją na gałąź w tym repozytorium, albo wcale: etykieta, która uruchamia plan z poświadczeniami na głowie forka, wykonuje kod forka z rolą planu.

  2. Przerwij build przy każdym niezadeklarowanym usunięciu lub zastąpieniu. Zastąpienie pojawia się w resource_changes jako delete plus create:

    Okno terminala
    jq -r '.resource_changes[] | select(any(.change.actions[]; . == "delete")) | .address' plan.json \
    > deletes.txt
    if [ -s deletes.txt ] && ! grep -q '^allow-delete:' pr-body.txt; then
    echo "Plan deletes or replaces:"; cat deletes.txt; exit 1
    fi

    pr-body.txt to opis pull requesta zapisany do pliku we wcześniejszym kroku. Autor wyraża zgodę linią allow-delete:, w której podaje adresy i powód. Jeśli pull request otworzył agent, to on napisał też opis, więc ta linia jest deklaracją, a nie zabezpieczeniem: sprawdzenie tylko uwidacznia usunięcie, a zatrzymuje je dopiero wymagana akceptacja planu przez właściciela workspace’u. Przed akceptacją właściciel porównuje każdy adres z deletes.txt z linią allow-delete:. Bogatsze reguły (tagi, rozmiary instancji, regiony) sprawdzisz silnikiem polityk, takim jak Conftest, na tym samym plan.json.

  3. Poproś agenta o podsumowanie planu dla recenzenta. Podsumowanie jest mapą, nie dowodem: recenzent porównuje je z wyjściem planu.

  4. Właściciel workspace’u akceptuje, CI aplikuje zapisany plan. CI uruchamia terraform apply tfplan z tego samego pliku planu, więc wykonuje się dokładnie to, co zaakceptowano. Rollback to revert pull requesta i ten sam pipeline; operacje na stanie zostają przy właścicielu.

To infrastrukturalna wersja pakietu dowodów, który musi nieść pull request agenta: kody wyjścia bramek, zapisany plan, kontrola usunięć i podsumowanie. Jak recenzent przechodzi przez ten pakiet bez czytania każdej linii, opisuje strona o code review PR-a agenta, a podłączenie jobów do pipeline’u — strona o automatyzacji pipeline’ów z AI.

Dryf (poprawka wyklikana w konsoli, ręcznie dodana reguła security group) to miejsce, w którym kod infrastruktury po cichu przestaje być prawdą. Wykrywaj go samym narzędziem IaC według harmonogramu, a potem daj wynik agentowi do triażu. Wykrywanie jest deterministyczne; agent tylko porządkuje i wyjaśnia.

Okno terminala
# Kod wyjścia 2 oznacza, że prawdziwa infrastruktura różni się od stanu
terraform plan -refresh-only -detailed-exitcode -out drift.tfplan
terraform show -json drift.tfplan > drift.json

Zanim zadziałasz na podstawie znaleziska, potwierdź dwie rzeczy, których agent nie wie: że wartość „oczekiwana” odpowiada kodowi na domyślnej gałęzi, a nie staremu planowi, i że ręczna zmiana nie była nieudokumentowaną poprawką zrobioną podczas incydentu. Zapytaj właściciela stacka; wybrana naprawa przechodzi potem przez ten sam pull request i przegląd planu co każda inna zmiana.

terraform apply w CI wisi na „Acquiring state lock”. Dwa uruchomienia nałożyły się na siebie albo wcześniejsze padło w trakcie apply. Najpierw odczytaj z komunikatu, kto trzyma blokadę i od kiedy. terraform force-unlock LOCK_ID uruchom dopiero wtedy, gdy potwierdzisz, że tamten proces nie żyje; odblokowanie trwającego apply może uszkodzić stan. Nakładanie się zatrzymasz grupą współbieżności (concurrency group) na jobie apply.

Plan zastępuje zasób, którego nikt nie chciał ruszać. Agent zmienił nazwę zasobu albo przeniósł go do modułu, więc Terraform widzi usunięcie i utworzenie. Kontrola usunięć w CI to łapie. Poproś agenta o blok moved ze starego adresu na nowy i planuj ponownie, aż zastąpienie zniknie.

terraform init pada po tym, jak agent zmienił wersję dostawcy. Plik blokady wciąż przypina starą wersję główną. Nie pozwalaj agentowi podnosić wersji głównej dostawcy w tej samej zmianie co funkcję; zrób to w osobnym pull requeście po lekturze przewodnika aktualizacji dostawcy. Uruchom terraform init -upgrade, żeby zaktualizować .terraform.lock.hcl, a potem terraform providers lock -platform=linux_amd64 -platform=darwin_arm64, żeby CI i laptopy miały te same skróty.

terraform validate odrzuca argument napisany przez agenta. Agent pominął sprawdzenie w registry albo czytał najnowszą dokumentację wobec starszego przypiętego dostawcy. Zrób ze sprawdzenia osobną turę i podaj w prompcie przypiętą wersję, jak w briefie z ograniczeniami powyżej.

Bramki przechodzą, ale zmiana jest zbyt liberalna. Generowane polityki IAM dryfują w stronę akcji z wildcardem i szerokich principali, na które wiele skanerów tylko ostrzega. Dodaj regułę polityki, która przerywa plan przy "Action": "*" i przy ruchu przychodzącym z 0.0.0.0/0, a ścieżki wrażliwe (IAM, sieć, KMS) trzymaj na liście, która zawsze wymaga akceptacji właściciela.

Serwer MCP nic nie zwraca albo zwraca stare dane. Najpierw sprawdź pakiet (zobacz ramkę z ostrzeżeniem powyżej: npm terraform-mcp-server i wycofane serwery AWS Labs to częste przyczyny), potem poświadczenia: AWS_PROFILE i region w env serwera oraz uprawnienia odczytu profilu. claude mcp list albo codex mcp list pokaże, czy serwer się połączył. Więcej w problemach z połączeniem MCP.

Hurtowy revert dryfu usuwa prawdziwą poprawkę. Ktoś otworzył port w trakcie incydentu, a revert znowu go zamyka. Nigdy nie cofaj dryfu z harmonogramu bez triażu; świeże zmiany kieruj ścieżką (c) z promptu o dryfie.

Agent wykonuje instrukcję ukrytą w wyjściu planu lub w tagu zasobu. Wyjście planu, tagi i opisy to dane, które trafiają do modelu. Trzymaj agenta w trybie tylko do odczytu, gdy je czyta, i nie łącz w tej samej sesji serwerów z prawem zapisu. Zobacz bezpieczeństwo MCP.