Salta al contenuto principale

08 - Policy as Code - Enforcement di Security Policies nel Deployment

OPA/Rego, Kyverno (Kubernetes), Sentinel (Terraform), policy examples (image registries, resource limits), testing policies, organizational rollout.

Cosa ne pensi di questo articolo?

08 - Policy as Code - Enforcement di Security Policies nel Deployment
DevSecOpsFoto:Danny MenesesPexels

In Breve

OPA/Rego, Kyverno (Kubernetes), Sentinel (Terraform), policy examples (image registries, resource limits), testing policies, organizational rollout.

Policy as Code: Automatizzare le Regole di Sicurezza

Policy as Code (PaC) e la pratica di definire le regole di sicurezza e compliance come codice versionabile, testabile e applicabile automaticamente. Invece di documentare le policy in PDF che nessuno legge, PaC le trasforma in codice eseguibile che viene applicato automaticamente nella pipeline e nell'infrastruttura.

Con PaC, le regole come "ogni container deve girare come non-root" o "i bucket S3 non devono essere pubblici" diventano controlli automatici che bloccano i deploy non conformi. Questo elimina l'errore umano e garantisce conformità continua.

Cosa Imparerai

  • I principi di Policy as Code e i vantaggi rispetto alle policy tradizionali
  • OPA (Open Policy Agent) e il linguaggio Rego
  • Kyverno per Kubernetes policy enforcement
  • Sentinel di HashiCorp per Terraform
  • Conftest per validare configurazioni
  • Testing e deployment delle policy

OPA: Open Policy Agent

OPA (Open Policy Agent) e il motore di policy più diffuso nell'ecosistema cloud-native. Sviluppato dalla CNCF, OPA utilizza il linguaggio dichiarativo Rego per definire policy che possono essere applicate a qualsiasi tipo di dato strutturato: richieste API, configurazioni Kubernetes, configurazioni Terraform, pipeline CI/CD.

Scrivere Policy in Rego


# policy/kubernetes/pod-security.rego
package kubernetes.admission

# Nega i container che girano come root
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  not container.securityContext.runAsNonRoot
  msg := sprintf(
    "Container '%s' deve avere runAsNonRoot: true",
    [container.name]
  )
}

# Nega immagini con tag :latest
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  endswith(container.image, ":latest")
  msg := sprintf(
    "Container '%s' usa :latest. Specificare un tag esplicito.",
    [container.name]
  )
}

# Richiedi resource limits
deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  not container.resources.limits
  msg := sprintf(
    "Container '%s' deve definire resource limits (CPU e memory)",
    [container.name]
  )
}
      

Testare le Policy OPA


# policy/kubernetes/pod-security_test.rego
package kubernetes.admission

test_deny_root_container {
  count(deny) > 0 with input as {
    "request": {
      "kind": {"kind": "Pod"},
      "object": {
        "spec": {
          "containers": [{
            "name": "app",
            "image": "myapp:v1",
            "securityContext": {}
          }]
        }
      }
    }
  }
}

test_allow_nonroot_container {
  count(deny) == 0 with input as {
    "request": {
      "kind": {"kind": "Pod"},
      "object": {
        "spec": {
          "containers": [{
            "name": "app",
            "image": "myapp:v1",
            "securityContext": {"runAsNonRoot": true},
            "resources": {"limits": {"cpu": "500m", "memory": "256Mi"}}
          }]
        }
      }
    }
  }
}
      

Kyverno: Policy Nativo Kubernetes

Kyverno e un policy engine progettato specificamente per Kubernetes. A differenza di OPA che usa Rego, Kyverno definisce le policy come risorse Kubernetes native in YAML, rendendo l'adozione più semplice per i team che hanno già familiarita con Kubernetes.


# kyverno-policies/require-nonroot.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-run-as-nonroot
  annotations:
    policies.kyverno.io/title: Require runAsNonRoot
    policies.kyverno.io/category: Pod Security
    policies.kyverno.io/severity: high
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: check-containers
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: >-
          Container deve girare come non-root.
          Impostare securityContext.runAsNonRoot a true.
        pattern:
          spec:
            containers:
              - securityContext:
                  runAsNonRoot: true

---
# Richiedi registry approvati
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-image-registries
spec:
  validationFailureAction: Enforce
  rules:
    - name: validate-registries
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Immagini devono provenire da registry approvati."
        pattern:
          spec:
            containers:
              - image: "ghcr.io/myorg/* | registry.internal.company.com/*"
      

Conftest: Validare Configurazioni

Conftest utilizza OPA/Rego per validare qualsiasi tipo di file di configurazione: Dockerfile, Kubernetes manifest, Terraform files, pipeline CI/CD. E particolarmente utile come step nella pipeline CI per validare le configurazioni prima del deploy.


# Installare Conftest
brew install conftest

# Validare un Dockerfile
conftest test Dockerfile --policy policy/docker/

# Validare manifest Kubernetes
conftest test k8s/ --policy policy/kubernetes/

# Validare con output strutturato
conftest test --output json terraform/ --policy policy/terraform/
      

# policy/docker/dockerfile.rego
package docker

# Nega Dockerfile senza USER
deny[msg] {
  input[i].Cmd == "from"
  not any_user_after(i)
  msg := "Dockerfile deve includere l'istruzione USER per evitare l'esecuzione come root"
}

any_user_after(from_idx) {
  input[j].Cmd == "user"
  j > from_idx
}

# Nega immagini base :latest
deny[msg] {
  input[i].Cmd == "from"
  val := input[i].Value[0]
  endswith(val, ":latest")
  msg := sprintf("Evitare :latest nell'istruzione FROM. Usare un tag specifico: %s", [val])
}
      

Sentinel: Policy per Terraform

Sentinel e il framework di policy di HashiCorp, integrato nativamente in Terraform Cloud e Enterprise. Permette di definire policy che validano i piani Terraform prima dell'applicazione, prevenendo la creazione di risorse non conformi.

Confronto Policy Engines

Caratteristica OPA/Rego Kyverno Sentinel
Ambito Universale Kubernetes HashiCorp ecosystem
Linguaggio Rego (dichiarativo) YAML nativo K8s Sentinel (imperativo)
Curva apprendimento Media-alta Bassa Media
Licenza Open source (Apache 2.0) Open source (Apache 2.0) Commerciale (Terraform Cloud)

Policy nella Pipeline CI/CD


# .github/workflows/policy-check.yml
name: Policy Validation
on:
  pull_request:

jobs:
  validate-policies:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Conftest
        run: |
          wget -q https://github.com/open-policy-agent/conftest/releases/download/v0.46.0/conftest_0.46.0_Linux_x86_64.tar.gz
          tar xzf conftest_0.46.0_Linux_x86_64.tar.gz
          sudo mv conftest /usr/local/bin/

      - name: Test OPA policies
        run: opa test policy/ -v

      - name: Validate Dockerfiles
        run: conftest test Dockerfile --policy policy/docker/

      - name: Validate K8s manifests
        run: conftest test k8s/ --policy policy/kubernetes/

      - name: Validate Terraform
        run: conftest test terraform/ --policy policy/terraform/
      

Best Practice per Policy as Code

  1. Versionare le policy: trattare le policy come codice, con review, test e release
  2. Testare le policy: scrivere unit test per ogni policy per evitare regressioni
  3. Gradualità: iniziare in modalità audit (warning) prima di passare a enforce (bloccante)
  4. Documentare: ogni policy deve avere una descrizione chiara del perchè esiste
  5. Feedback rapido: integrare la validazione nella PR per feedback immediato
  6. Eccezioni gestite: prevedere un processo per le eccezioni temporanee con scadenza

Conclusioni

Policy as Code trasforma le regole di sicurezza da documenti statici a codice eseguibile e automatizzato. Con OPA, Kyverno e Conftest, le organizzazioni possono garantire conformità continua senza rallentare il processo di sviluppo.

Nel prossimo articolo esploreremo CI/CD Security Pipeline, analizzando come proteggere il processo di build e deploy stesso: pipeline hardening, OIDC, least privilege e signed commits.

Domande frequenti

Cos'è la Policy as Code (PaC) e come funziona?

La Policy as Code è una pratica che consiste nel definire le regole di sicurezza e compliance come codice versionabile, testabile e applicabile automaticamente. Questo significa trasformare le policy da documenti statici in codice eseguibile che viene applicato automaticamente nella pipeline e nell'infrastruttura.

Qual è il ruolo dell'Open Policy Agent (OPA) nel contesto della PaC?

L'Open Policy Agent è un motore di policy molto diffuso nell'ecosistema cloud-native, sviluppato dalla CNCF. Utilizza il linguaggio dichiarativo Rego per definire policy che possono essere applicate a qualsiasi tipo di dato strutturato.

Quali sono le differenze tra OPA e Kyverno in termini di definizione delle policy?

Mentre OPA utilizza il linguaggio Rego, Kyverno definisce le policy come risorse Kubernetes native in YAML. Ciò rende l'adozione più semplice per i team che hanno già familiarità con Kubernetes.

Qual è lo scopo di Conftest e come si integra con OPA/Rego?

Conftest utilizza OPA/Rego per validare qualsiasi tipo di file di configurazione, come Dockerfile, Kubernetes manifest o pipeline CI/CD. È particolarmente utile come step nella pipeline CI per validare le configurazioni prima del deploy.

Fonti e approfondimenti

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti