Skip to content

Kubernetes Pod Security: Hardening dei Container e Verifiche Manuali

Il pod hardening riduce i privilegi effettivi dei container e limita cio che un workload puo fare a runtime. L'obiettivo e' eseguire applicazioni con permessi minimi, senza token Kubernetes non necessari, senza escalation di privilegi e con filesystem il piu possibile immutabile.

Panoramica

In Kubernetes la sicurezza del Pod si definisce soprattutto tramite securityContext, configurazione del ServiceAccount, mount, capabilities Linux e policy di rete. La configurazione dichiarativa deve sempre essere affiancata da verifiche manuali dentro il container, per controllare che il comportamento reale corrisponda a quello atteso.

Parametri Pod

Applicare le impostazioni di sicurezza direttamente nel Pod template del Deployment, StatefulSet o DaemonSet.

spec:
  enableServiceLinks: false # (1)!
  automountServiceAccountToken: false # (2)!
  securityContext:
    runAsNonRoot: true # (3)!
    seccompProfile:
      type: RuntimeDefault # (4)!
  containers:
    - name: app
      securityContext:
        allowPrivilegeEscalation: false # (5)!
        readOnlyRootFilesystem: true # (6)!
        runAsUser: 10001 # (7)!
        runAsGroup: 10001 # (8)!
        capabilities:
          drop:
            - ALL # (9)!
  1. Evita l'iniezione automatica delle variabili ambiente dei Service Kubernetes nel Pod.
  2. Non monta automaticamente il token del ServiceAccount quando il workload non deve chiamare l'API Kubernetes.
  3. Impedisce l'esecuzione del Pod come utente root.
  4. Applica il profilo seccomp predefinito del runtime container.
  5. Blocca l'acquisizione di privilegi aggiuntivi da parte del processo.
  6. Monta il filesystem root del container in sola lettura.
  7. Imposta UID esplicito non root per il processo.
  8. Imposta GID esplicito non root per il processo.
  9. Rimuove tutte le Linux capabilities non necessarie.

Verifica identita nel Pod

Entrare nel container e controllare utente, gruppi e privilegi effettivi:

kubectl exec -it <pod> -n <namespace> -- sh
whoami
id
groups

Il risultato atteso e' un utente non root, con UID/GID coerenti con runAsUser e runAsGroup.

Verifica token ServiceAccount

Controllare che il token Kubernetes non sia montato quando non serve:

kubectl exec -it <pod> -n <namespace> -- sh
ls -la /var/run/secrets/kubernetes.io/serviceaccount

Se automountServiceAccountToken: false e' applicato correttamente, il path non dovrebbe contenere token utilizzabili per chiamare l'API Kubernetes.

Verifica filesystem read-only

Validare che il filesystem root non sia scrivibile:

kubectl exec -it <pod> -n <namespace> -- sh
touch /test-write

Il risultato atteso e' un errore di scrittura. Se l'applicazione necessita path scrivibili, usare mount dedicati come emptyDir su directory specifiche, ad esempio /tmp o /var/cache/app.

Verifica capabilities e privilege escalation

Controllare capabilities e privilegi del processo:

kubectl exec -it <pod> -n <namespace> -- sh
grep Cap /proc/1/status
grep NoNewPrivs /proc/1/status

NoNewPrivs dovrebbe indicare che non e' permessa escalation. Le capabilities effettive devono essere minime o assenti, in linea con capabilities.drop: [ALL].

Verifica processi e porte

Controllare processi attivi e porte in ascolto dentro il container:

kubectl exec -it <pod> -n <namespace> -- sh
ps aux
ss -tulpn

Il container dovrebbe eseguire solo i processi necessari e ascoltare esclusivamente sulle porte previste dall'applicazione.

Verifica mount e variabili ambiente

Controllare mount, filesystem e variabili iniettate:

kubectl exec -it <pod> -n <namespace> -- sh
mount
df -h
env | sort

Con enableServiceLinks: false, il container non dovrebbe ricevere variabili automatiche legate ai Service Kubernetes non necessari.

Risultato atteso

Un Pod hardened deve rispettare queste condizioni:

  • processo non root;
  • nessuna privilege escalation;
  • capabilities Linux ridotte al minimo;
  • token ServiceAccount assente se non necessario;
  • filesystem root read-only;
  • mount scrivibili solo dove servono;
  • porte esposte limitate;
  • processi attivi coerenti con il workload;
  • configurazione verificabile sia dal manifest sia dall'interno del container.