Znasz to: w firmowej wiki leży „standard”, którego nikt nie czyta, a na review i tak przechodzi PR łamiący zasadę — bo recenzent akurat jej nie pamiętał. Sam nieraz byłem tym recenzentem. Polityka, której nie da się uruchomić, to nie polityka, tylko dokument. Policy-as-code (PaC) zamienia ją w coś przeciwnego: regułę zapisaną jako kod, którą maszyna sprawdza przy każdej zmianie — deterministycznie, w tym samym miejscu co reszta pipeline’u, z wynikiem, który albo przepuszcza, albo zatrzymuje.
W wprowadzeniu do serii postawiliśmy tezę, że platform engineering to normalizacja pracy — kodowanie osądu raz i stosowanie go wszędzie. Policy-as-code jest tej tezy najczystszym wcieleniem: zamiast debatować każdy przypadek z osobna, zespół platformowy zapisuje regułę i pozwala jej działać w kółko. Ten artykuł rozwija PaC od pojedynczej bramki w CI do warstwowej płaszczyzny kontroli całej platformy — i pokazuje, dlaczego to ona staje się fundamentem zarówno zgodności regulacyjnej, jak i bezpiecznej autonomii agentów.
Policy-as-code to nie pojedynczy skan w CI, lecz warstwa kontroli rozłożona wzdłuż całego cyklu — od IDE i PR, przez build i plan IaC, po admission w klastrze. Egzekwowana automatycznie i blisko miejsca, gdzie pracuje inżynier, zamienia bezpieczeństwo i zgodność z bramkarza, który blokuje, w guardrail, który prowadzi — i daje gotowy ślad audytowy jako produkt uboczny.
Co właściwie znaczy „as code”
Sednem PaC jest oddzielenie decyzji od egzekwowania. Zamiast zaszywać logikę „czy wolno?” w każdej aplikacji i każdym skrypcie, opisujesz ją deklaratywnie w jednym miejscu, a silnik polityk odpowiada na pytania w czasie, gdy decyzja jest potrzebna. To daje trzy własności, których dokument nigdy nie miał:
- Wersjonowanie — polityka żyje w repo, ma historię zmian, autora i przegląd jak każdy inny kod.
- Testowalność — regułę można pokryć testami i uruchomić lokalnie, zanim trafi na produkcję.
- Audytowalność — każde uruchomienie zostawia ślad: co sprawdzono, na jakich danych i z jakim wynikiem.
To ta sama zmiana nośnika, którą opisaliśmy przy tokenach designu: gdy reguła staje się danymi, przestaje zależeć od ludzkiej pamięci, a zaczyna od pipeline’u.
OPA i Rego: uniwersalny silnik
Open Policy Agent (OPA) to ogólnego przeznaczenia silnik polityk i projekt CNCF na poziomie „graduated” — czyli najwyższym poziomie dojrzałości. Jego siła to uniwersalność: jednym językiem opiszesz reguły dla Kubernetes, planu Terraform/OpenTofu, API mikroserwisu czy pipeline’u CI. OPA nie wie nic o domenie — dostaje dane wejściowe (JSON) i zwraca decyzję.
Reguły pisze się w Rego — deklaratywnym języku wywodzącym się z Datalog, zaprojektowanym do odpytywania złożonych, zagnieżdżonych struktur danych. Prosty przykład bramki w CI, która odrzuca obraz z tagiem latest:
package ci.images
# odrzuć każdy kontener używający :latest
deny contains msg if {
some c in input.spec.containers
endswith(c.image, ":latest")
msg := sprintf("obraz %v używa :latest — przypnij wersję", [c.image])
}
# ta sama reguła jako bramka w pipeline (bez klastra)
$ conftest test deployment.yaml
FAIL - deployment.yaml - ci.images - obraz app:latest używa :latest — przypnij wersję
1 test, 0 passed, 1 failure # exit 1 → PR nie przechodzi
Tu rolę uruchamiacza w CI pełni Conftest (Rego poza klastrem), a tę samą politykę w klastrze egzekwuje jako admission webhook OPA Gatekeeper. Uczciwa uwaga: Rego bywa stromy — opanowanie go to realnie kilkadziesiąt godzin nauki, a w 2026 r. ekosystem OPA przeszedł zmiany właścicielskie (część twórców i inżynierów Styra dołączyła do Apple). To nie podważa dojrzałości projektu, ale warto znać krajobraz alternatyw.
Nie tylko OPA: krajobraz silników
„Policy-as-code” to kategoria, nie jedno narzędzie. Wybór zależy od tego, co egzekwujesz i kto ma pisać reguły.
| Silnik | Język / format | Najlepszy do | Cena wyboru |
|---|---|---|---|
| OPA + Conftest | Rego | Spójne reguły w całym stacku (K8s, IaC, API, CI) | Stroma krzywa Rego |
| Kyverno | YAML (zasoby K8s) | Governance Kubernetes bez nowego języka | Mocno związany z K8s |
| Gatekeeper | Rego (CRD) | Admission control w klastrze na bazie OPA | Tylko klaster |
| Cedar | Cedar | Autoryzacja aplikacyjna (czytelna, szybka, analizowalna) | Węższy zakres, ekosystem AWS |
| Checkov / Terrascan | wbudowane reguły | Skan IaC out-of-the-box | Mniej elastyczne niż własne reguły |
| Casbin | modele (ACL/RBAC/ABAC) | Autoryzacja wewnątrz aplikacji | To biblioteka, nie bramka CI |
Dwie osie pomagają wybrać. Pierwsza: uniwersalność vs prostota — OPA daje jeden język na wszystko kosztem nauki Rego; Kyverno zostaje w YAML, ale tylko dla Kubernetes. Druga: kto czyta regułę — Cedar jest celowo czytelny i ściśle typowany (łatwiejszy do przejrzenia także dla nie-programisty oraz do automatycznej analizy), Rego bywa gęsty. W EIAC nie stawiamy na konkretne narzędzie, lecz na zasadę: reguła jest kodem, bramką i śladem — niezależnie od silnika.
Warstwowa płaszczyzna kontroli
Najczęstszy błąd to potraktowanie PaC jak pojedynczego skanu w CI. Dojrzała platforma rozkłada polityki warstwowo, tak by każda bramka działała tam, gdzie ma najwięcej kontekstu i najmniej przeszkadza:
- Źródło i projekt (IDE, PR) — linty, szablony, walidacja konwencji; najtańsze i najszybsze sprzężenie zwrotne.
- Build — polityki nad Dockerfile i obrazami (brak
latest, brak roota, dozwolone bazowe obrazy), skan zależności (Trivy). - Plan / provisioning — reguły nad planem IaC (zanim cokolwiek powstanie: brak otwartych portów, wymagane szyfrowanie, tagi właściciela).
- Deploy / runtime — admission controller (Gatekeeper/Kyverno) odrzuca niezgodne zasoby przy
kubectl apply/helm.
Kluczowe jest, by ta sama intencja była egzekwowana na wielu warstwach: „brak latest” sprawdzasz w CI (szybkie sprzężenie dla dewelopera) i w admission (twarda gwarancja, że nic nie obejdzie pipeline’u). Warstwy się nie wykluczają — uzupełniają.
Guardrails, nie bramkarze
Najważniejsza zmiana myślenia: PaC ma być guardrailem, nie bramkarzem. Bramkarz blokuje i zmusza do proszenia o zgodę; guardrail wyznacza bezpieczny tor, po którym jedzie się samoobsługowo. Google Cloud opisuje cztery mechanizmy kontroli platformy: złote ścieżki (domyślne, wspierane drogi), guardrails (automatyczne granice), siatki bezpieczeństwa (wykrywanie po fakcie) i ręczne punkty kontrolne (gdy naprawdę trzeba człowieka). PaC realizuje przede wszystkim guardrails — i to one skalują się najlepiej, bo „kodują osąd raz i stosują go nieustannie”.
Z tego wynika praktyczna reguła doboru: shift-left to nie tylko „wcześniej”, ale „wcześniej i automatycznie” — walidacja tam, gdzie inżynier już pracuje (IDE, PR, CI, deploy), ze sprzężeniem, które jest szybkie, konkretne i naprawialne. Polityka, która zwraca „odmowa” bez wskazania, co poprawić, jest bramkarzem. Polityka, która mówi „użyj var(--space-2) zamiast 12px” albo „przypnij wersję obrazu” — jest guardrailem. Różnica decyduje o tym, czy zespoły platformę pokochają, czy zaczną ją obchodzić.
Policy-as-code w platformie agentowej
Tu PaC przestaje być wygodą, a staje się warunkiem koniecznym. Gdy część pracy w pętli wykonuje agent AI, a nie człowiek, znika naturalny punkt kontroli, jakim był recenzent przy klawiaturze. Pętla narzędziowa agenta sama z siebie nie ma punktu decyzyjnego „czy wolno?” — i to policy-as-code go dostarcza: deklaratywną bramkę, przez którą musi przejść każde działanie, niezależnie od tego, czy zainicjował je człowiek, czy model.
To jest dokładnie rdzeń deterministycznego szkieletu ADP: nie ufamy modelowi „że zrobi dobrze”, tylko zamykamy go w polityce egzekwowanej maszynowo. Im wyżej w czterech poziomach autonomii, tym mocniejsze muszą być te bramki — bo tym mniej człowieka zostaje w pętli. PaC łączy się tu wprost z Security Plane: tożsamość mówi kto/co działa (także tożsamość nie-ludzka agenta), a polityka — co temu komuś wolno.
# Kyverno: w klastrze nic nie wystartuje jako root — dotyczy tak samo
# wdrożeń człowieka, jak i tych zainicjowanych przez agenta
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: { name: require-non-root }
spec:
validationFailureAction: Enforce
rules:
- name: check-runAsNonRoot
match: { any: [{ resources: { kinds: ["Pod"] } }] }
validate:
message: "kontener musi działać jako non-root"
pattern:
spec:
securityContext: { runAsNonRoot: true }
Zgodność jako produkt uboczny
Ponieważ każde uruchomienie polityki zostawia ślad — co sprawdzono, z jakim wynikiem — PaC daje za darmo to, co regulacje wymagają osobno: dowód. Zamiast ręcznych audytów raz na kwartał masz ciągły, maszynowy zapis zgodności. To wprost odpowiada na wymóg DORA, by zgodność dało się wykazać, oraz na oczekiwania AI Act co do śladu i nadzoru. „Compliance by design” nie jest hasłem — to konsekwencja tego, że reguła jest kodem, który się wykonuje i loguje.
Granica uczciwości: PaC pokrywa techniczną część zgodności. Procesy organizacyjne — rejestr ryzyka, raportowanie incydentów, role i odpowiedzialności — to wciąż praca ludzi. Platforma jest warunkiem koniecznym zgodności, nie wystarczającym.
Wybierz ścieżkę
Nie ma jednej słusznej drogi wdrożenia — jest sekwencja, którą warto przejść etapami:
- Zacznij od jednej bramki w CI — np. Conftest lub Checkov na PR. Niski koszt, szybka wartość, uczy zespół myślenia regułami.
- Dołóż admission w klastrze — Kyverno (gdy zespół woli YAML) lub Gatekeeper (gdy już używasz Rego). Domyka lukę „co z tym, co omija CI”.
- Ujednolić język, jeśli rośnie zakres — gdy reguły mnożą się w wielu miejscach (K8s, IaC, API), rozważ OPA/Rego jako wspólny silnik; do czystej autoryzacji aplikacyjnej — Cedar lub Casbin.
- Traktuj polityki jak produkt — wersjonuj, testuj, dawaj czytelne komunikaty naprawcze. Guardrail bez dobrego UX zamienia się w bramkarza, którego zespoły obchodzą.
Reguła kciuka: najpierw jedna warstwa, potem szerokość, na końcu unifikacja języka. Budowanie od razu uniwersalnej platformy polityk dla problemu, którego jeszcze nie masz, to ten sam over-engineering, przed którym ostrzegaliśmy przy samej platformie.
Podsumowanie
Policy-as-code zamienia zasady bezpieczeństwa i zgodności z dokumentów, które nikt nie egzekwuje, w testowalne bramki, które działają same. Jego dojrzała forma to nie skan w CI, lecz warstwowa płaszczyzna kontroli — od IDE po admission — egzekwowana jako guardrail blisko miejsca pracy inżyniera, a nie jako bramkarz na końcu. W platformie agentowej PaC jest tym punktem decyzyjnym, którego pętla agenta sama nie ma, a przy okazji dostarcza ciągły ślad audytowy spełniający wymogi DORA i AI Act. Wybór silnika należy do Ciebie — OPA, Kyverno, Cedar czy inny — bo w EIAC liczy się zasada, nie narzędzie: reguła jest kodem, bramką i śladem. A od strony praktycznej: zacznij od jednej reguły w CI. Zobaczysz, ile spokoju daje świadomość, że standard egzekwuje się sam, a nie zależy od tego, czy ktoś go akurat pamiętał na review.