Policy as Code (OPA)
Il gate costAlertThresholdUsd nel config è un confronto totale-vs-budget. Per regole più espressive — per tag, per tipo di risorsa, per conteggio — cloudrift supporta Open Policy Agent (OPA).
Come funziona
cloudrift non esegue mai OPA da sé — produce solo JSON. Tu (o la tua pipeline CI) esegui conftest/opa contro l’output JSON:
node apps/cli/dist/main.js analyze --format json > report.json
conftest test --policy policy report.json
conftest esce con codice 1 se una regola è violata, 0 se il report è pulito — esattamente il segnale che serve a uno step CI.
Prerequisiti
Installa conftest:
# macOS
brew install conftest
# Altre piattaforme: https://www.conftest.dev/install/
Provalo in 30 secondi (senza account AWS)
Il repo include un report di esempio in policy/testdata/sample-report.json. Puoi vedere le policy in azione subito:
conftest test --policy policy policy/testdata/sample-report.json
Output atteso — tutte e tre le policy di esempio negano qualcosa:
FAIL - policy/testdata/sample-report.json - main - 3 unattached EBS volumes found, more than the 2 allowed
FAIL - policy/testdata/sample-report.json - main - ebs-volume (vol-0abc123def456) in production is wasting $40/month
FAIL - policy/testdata/sample-report.json - main - total monthly waste $63.6 exceeds budget $50
Policy di esempio incluse
| File | Regola |
|---|---|
policy/waste-budget.rego |
Totale mensile spreco sopra un budget fisso |
policy/production-tag.rego |
Qualsiasi waste con tag Environment: production |
policy/idle-resource-count.rego |
Più di N volumi EBS non attaccati |
Ogni file ha un _test.rego associato. Test delle policy:
opa test policy/ -v
Scrivere una regola personalizzata
Le policy condividono package main. Rego unisce i blocchi deny contains msg if {...} dello stesso package, quindi un quarto file ha bisogno solo dello stesso header e della sua condizione. Esempio — negare ogni finding sopra $100/mese:
# policy/high-cost-finding.rego
package main
import rego.v1
deny contains msg if {
some finding in input.findings
finding.category == "waste"
finding.monthlyCostUsd > 100
msg := sprintf("%s (%s) is wasting $%v/month", [finding.kind, finding.id, finding.monthlyCostUsd])
}
input è il JSON del report — i campi disponibili per ogni finding: kind, category, tags, monthlyCostUsd, region, id, wasteReason. Top-level: totalWasteMonthlyUsd, wasteCount, findings[].
Gotcha Rego: cloudrift serializza cifre intere senza decimale (es.
$40diventa40, non40.00). Il verbo%.2fdi Rego crasha su interi. Usa%vnelle tue regole.
Integrare in CI
Aggiungi uno step dopo lo scan:
- run: node cloudrift-cli/apps/cli/dist/main.js analyze -r us-east-1 --format json > report.json
working-directory: cloudrift-cli
- uses: openpolicyagent/conftest-action@v1
with:
policy: cloudrift-cli/policy
files: cloudrift-cli/report.json
Oppure installa conftest direttamente e lancia conftest test --policy policy report.json.
Perché esterno alla CLI
Incorporare un runtime OPA (binario shelled-out o build WASM) dentro il pacchetto npm aggiungerebbe una dipendenza pesante e platform-specific per un risultato che — per la maggior parte degli utenti — un confronto numerico già fornisce. Il valore di un vero policy engine emerge solo con regole espressive e multi-segnale, o se vuoi riusare un bundle OPA/Rego che già mantieni per Terraform o Kubernetes. Tenendo OPA fuori dal pacchetto, cloudrift resta una CLI leggera e chi vuole questo livello lo attiva esplicitamente.