Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Nota del traduttore.: L'autore dell'articolo, Reuven Harrison, ha oltre 20 anni di esperienza nello sviluppo software ed è attualmente il CTO e cofondatore di Tufin, un'azienda specializzata in soluzioni per la gestione delle politiche di sicurezza. Considerando le politiche di rete di Kubernetes come uno strumento potente per la segmentazione della rete all'interno di un cluster, ritiene però che non siano così semplici da applicare nella pratica. Questo materiale (abbastanza corposo) è destinato a migliorare la consapevolezza dei professionisti su questo argomento e ad aiutarli nella creazione delle configurazioni necessarie.

Oggi molte aziende scelgono sempre più spesso Kubernetes per eseguire le proprie applicazioni. L'interesse per questo software è così elevato che alcuni lo definiscono 'il nuovo sistema operativo per i data center'. Gradualmente, Kubernetes (o k8s) viene percepito come una parte fondamentale del business, richiedendo l'organizzazione di processi aziendali maturi, compresa la sicurezza di rete.

Per i professionisti della sicurezza che sono stati sfidati dalla gestione di Kubernetes, una vera scoperta può essere la politica di default di questa piattaforma: consentire tutto.

Questa guida aiuterà a comprendere il funzionamento delle politiche di rete; a capire come si differenziano dalle regole dei normali firewall. Saranno inoltre evidenziate alcune insidie e fornite raccomandazioni per proteggere le applicazioni in Kubernetes.

Politiche di rete Kubernetes

Il meccanismo delle politiche di rete Kubernetes consente di gestire le interazioni delle applicazioni distribuite sulla piattaforma a livello di rete (terzo livello nel modello OSI). Le politiche di rete non dispongono di alcune delle funzionalità avanzate dei moderni firewall, come il controllo al settimo livello OSI e la rilevazione delle minacce, ma forniscono un livello base di sicurezza di rete, che rappresenta un buon punto di partenza.

Le politiche di rete controllano le comunicazioni tra i pod.

I carichi di lavoro in Kubernetes sono distribuiti tra i pod, che consistono in uno o più contenitori distribuiti insieme. Kubernetes assegna a ogni pod un indirizzo IP accessibile da altri pod. Le politiche di rete di Kubernetes definiscono i diritti di accesso per gruppi di pod in modo simile a come i gruppi di sicurezza nel cloud vengono utilizzati per gestire l'accesso alle istanze di macchine virtuali.

Definizione delle politiche di rete

Come le altre risorse di Kubernetes, le politiche di rete sono definite nel linguaggio YAML. Nell'esempio seguente, all'applicazione balance viene concesso accesso a postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

(Nota del traduttore.: questo screenshot, come tutti i successivi analoghi, è stato creato non con i mezzi nativi di Kubernetes, ma utilizzando lo strumento Tufin Orca, sviluppato dall'azienda dell'autore dell'articolo originale e menzionato alla fine del materiale.)

Per definire una propria politica di rete, è necessaria una conoscenza di base di YAML. Questo linguaggio si basa su rientri (definiti da spazi, non da tabulazioni). Un elemento con rientro appartiene all'elemento con rientro più vicino sopra di esso. Un nuovo elemento della lista inizia con un trattino, mentre tutti gli altri elementi hanno la forma chiave-valore.

Dopo aver descritto la politica in YAML, utilizza kubectl, per crearla nel cluster:

kubectl create -f policy.yaml

Specifiche della politica di rete

Le specifiche della politica di rete Kubernetes comprendono quattro elementi:

  1. podSelector: definisce i pod coinvolti da questa politica (obiettivo) — obbligatorio;
  2. policyTypes: indica quali tipi di politiche sono inclusi: ingress e/o egress — facoltativo, ma raccomando di specificarlo esplicitamente in tutti i casi;
  3. ingress: definisce il traffico in entrata consentito ai pod obiettivo — facoltativo;
  4. egress: definisce il traffico traffico in uscita dai pod obiettivo — facoltativo.

Un esempio preso dal sito di Kubernetes (ho sostituito role con app), mostra come vengono utilizzati tutti e quattro gli elementi:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<<
    matchLabels:
      app: db
  policyTypes:    # <<<<
  - Ingress
  - Egress
  ingress:        # <<<<
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:         # <<<<
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza
Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Si prega di notare che non è necessario includere tutti e quattro gli elementi. Solo podSelectorè obbligatorio, gli altri parametri possono essere utilizzati a piacere.

Se si omette policyTypes, la politica sarà interpretata nel seguente modo:

  • Per impostazione predefinita, si presume che definisca il lato ingress. Se non ci sono indicazioni esplicite in merito nella politica, il sistema considererà che tutto il traffico è vietato.
  • Il comportamento sul lato egress sarà determinato dalla presenza o assenza del corrispondente parametro egress.

Per evitare errori, consiglio di specificare sempre in modo esplicito policyTypes.

In conformità con la logica sopra riportata, se i parametri ingress e/o egress sono omessi, la politica vieterà tutto il traffico (vedere "Regola di pulizia" qui sotto).

Politica predefinita — consentire

Se non sono definite politiche, Kubernetes consente per impostazione predefinita tutto il traffico. Tutti i pod possono comunicare liberamente tra loro. Dal punto di vista della sicurezza, questo può sembrare illogico, ma ricorda che Kubernetes è stato originariamente sviluppato da ingegneri con l'obiettivo di garantire l'interoperabilità delle applicazioni. Le politiche di rete sono state aggiunte successivamente.

Spazi dei nomi

Gli spazi dei nomi (Namespaces) sono un meccanismo di collaborazione in Kubernetes. Sono progettati per isolare ambienti logici tra loro, consentendo per impostazione predefinita lo scambio di dati tra gli spazi.

Come la maggior parte dei componenti di Kubernetes, le politiche di rete risiedono in uno specifico spazio dei nomi. Nel blocco metadata è possibile specificare a quale spazio appartiene la politica:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

Se lo spazio dei nomi nei metadati non è esplicitamente definito, il sistema utilizzerà lo namespace specificato in kubectl (per impostazione predefinita namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

Ti consiglio di specificare esplicitamente lo namespace, a meno che tu non stia scrivendo una policy destinata a più spazi dei nomi.

Principale elemento podSelector nella policy sarà quello di selezionare i pod appartenenti allo spazio dei nomi di cui fa parte la policy (non ha accesso ai pod di altri spazi dei nomi).

Analogamente, i podSelector nei blocchi ingress e egress possono selezionare i pod solo dal proprio spazio dei nomi, a meno che tu non li combini tramite namespaceSelector (di questo si parlerà nella sezione 'Filtrare per spazi dei nomi e pod').

Regole di denominazione delle policy

I nomi delle policy devono essere unici all'interno di uno spazio dei nomi. Non possono esserci due policy con lo stesso nome all'interno di uno spazio, ma possono esserci policy con nomi identici in spazi diversi. Questo è utile quando desideri riutilizzare la stessa policy in più spazi.

Mi piace particolarmente uno dei modi di denominare. Consiste nell'unire il nome dello spazio dei nomi ai pod destinati. Ad esempio:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Etichette

È possibile allegare etichette personalizzate a oggetti Kubernetes come pod e spazi dei nomi. Le etichette (etichette — sono l'equivalente dei tag nel cloud. Le politiche di rete di Kubernetes utilizzano le etichette per selezionare pod, a cui si applicano:

podSelector:
  matchLabels:
    role: db

… oppure spazi dei nomi, a cui si applicano. In questo esempio, vengono selezionati tutti i pod negli spazi dei nomi con etichette corrispondenti:

namespaceSelector:
  matchLabels:
    project: myproject

Una avvertenza: quando si utilizza namespaceSelector assicurati che gli spazi dei nomi selezionati contengano l'etichetta desiderata. Tieni presente che gli spazi dei nomi incorporati, come default e kubectl -n kube-system edit cm kubelet-config-1.16, di default non contengono etichette.

Puoi aggiungere un'etichetta a uno spazio dei nomi nel seguente modo:

kubectl label namespace default namespace=default

In questo caso, lo spazio dei nomi nella sezione metadata deve far riferimento al nome reale dello spazio e non all'etichetta:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

Fonte e destinatario

Le politiche per i firewall consistono in regole con fonti e destinatari. Le politiche di rete Kubernetes sono definite per un obiettivo — un insieme di pod a cui si applicano, e poi stabiliscono regole per il traffico in ingresso (ingress) e/o in uscita (egress). Nel nostro esempio, l'obiettivo della politica saranno tutti i pod nello spazio dei nomi default con etichetta con chiave app e valore db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db   # <<<
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza
Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Sezione ingress in questa politica apre il traffico in ingresso ai pod target. In altre parole, ingress funge da fonte, mentre l'obiettivo è il corrispondente destinatario. Allo stesso modo, egress è il destinatario, mentre l'obiettivo è la sua fonte.

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Questo è equivalente a due regole per il firewall: Ingress → Obiettivo; Obiettivo → Egress.

Egress e DNS (importante!)

Limitando il traffico in uscita, fai particolare attenzione a DNS — Kubernetes utilizza questo servizio per associare i servizi agli indirizzi IP. Ad esempio, la seguente policy non funzionerà poiché non hai consentito all'applicazione balance di accedere al DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Puoi correggerlo consentendo l'accesso al servizio DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Ultimo elemento to — vuoto, e quindi seleziona indirettamente tutti i pod in tutti gli spazi dei nomi, consentendo balance di inviare richieste DNS al corrispondente servizio Kubernetes (di solito funziona nello spazio kubectl -n kube-system edit cm kubelet-config-1.16).

Questo approccio funziona, ma è eccessivamente permissivo e insicuro, poiché consente di indirizzare le richieste DNS al di fuori del cluster.

Può essere migliorato in tre passaggi consecutivi.

1. Consentire le richieste DNS solo all'interno al cluster, aggiungendo namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

2. Consentire le richieste DNS solo nello spazio dei nomi kubectl -n kube-system edit cm kubelet-config-1.16.

Per questo è necessario aggiungere un'etichetta allo spazio dei nomi kubectl -n kube-system edit cm kubelet-config-1.16: kubectl label namespace kube-system namespace=kube-system — e specificarla nella policy usando namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

3. I paranoici possono andare oltre e limitare le richieste DNS a un determinato servizio DNS in kubectl -n kube-system edit cm kubelet-config-1.16. Nella sezione "Filtra per spazi dei nomi e pod" verrà spiegato come ottenere ciò.

Un'altra opzione è consentire DNS a livello di spazio dei nomi. In questo caso, non sarà necessario aprirlo per ogni servizio:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Vuoto podSelector seleziona tutti i pod nel namespace.

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Primo corrispondenza e ordine delle regole

Nei normali firewall, l'azione («Consenti» o «Nega») riguardante un pacchetto è determinata dalla prima regola che soddisfa. In Kubernetes, l'ordine delle politiche non ha alcun significato.

Per impostazione predefinita, quando non ci sono politiche definite, le comunicazioni tra i pod sono consentite e possono scambiarsi informazioni liberamente. Una volta che inizi a formulare politiche, ogni pod colpito da almeno una di esse diventa isolato in base alla disgiunzione (logico O) di tutte le politiche che lo selezionano. I pod non colpiti da alcuna politica rimangono aperti.

È possibile modificare questo comportamento tramite una regola di pulizia.

Regola di pulizia («Nega»)

Le politiche firewall normalmente negano qualsiasi traffico esplicitamente non consentito.

In Kubernetes non c'è un'azione di «negare» (deny), tuttavia, un effetto simile può essere raggiunto con una politica ordinaria (di consentimento), selezionando un gruppo vuoto di pod sorgente (ingress):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Questa politica seleziona tutti i pod nello spazio dei nomi e lascia l'ingresso non definito, bloccando tutto il traffico in entrata.

Allo stesso modo, è possibile limitare tutto il traffico in uscita dallo spazio dei nomi:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Si noti che qualsiasi politica aggiuntiva che consente il traffico ai pod nello spazio dei nomi avrà la precedenza su questa regola (similmente all'aggiunta di una regola di autorizzazione prima di una di blocco nella configurazione del firewall).

Consenti tutto (Any-Any-Any-Allow)

Per creare una politica di "Consenti tutto", è necessario complementare la politica di blocco sopra con un elemento vuoto ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Essa consente l'accesso da tutti i pod in tutti gli spazi dei nomi (e tutti gli IP) a qualsiasi pod nello spazio dei nomi default. Questo comportamento è abilitato per impostazione predefinita, quindi generalmente non è necessario definirlo ulteriormente. Tuttavia, a volte potrebbe essere necessario disabilitare temporaneamente alcune autorizzazioni specifiche per diagnosticare un problema.

La regola può essere ristretta e l'accesso consentito solo a un set specifico di pod (app:balance) nello spazio dei nomi default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

La seguente policy consente tutto il traffico in ingresso (ingress) e in uscita (egress), incluso l'accesso a qualsiasi IP al di fuori del cluster:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza
Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Combinazione di più politiche

Le politiche si combinano utilizzando un'operazione logica OR a tre livelli; i permessi di ciascun pod sono stabiliti in base alla disgiunzione di tutte le politiche che lo riguardano:

1. Nei campi from e to possono essere definiti tre tipi di elementi (tutti combinati tramite OR):

  • namespaceSelector — seleziona interamente lo spazio dei nomi;
  • podSelector — seleziona i pod;
  • ipBlock — seleziona una sottorete.

Inoltre, il numero di elementi (anche identici) nei sottogruppi from/to non è limitato. Tutti saranno combinati logico OR.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

2. All'interno della policy, ingress può avere molti elementi from (uniti da un'operazione logica OR). Analogamente, la sezione egress può includere molti elementi to (anch'essi uniti tramite disgiunzione):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

3. Diverse policies sono unite anche tramite un'operazione logica OR

Ma nella loro combinazione c'è una restrizione da considerare, su cui ha indicato Chris Cooney: Kubernetes può combinare solo policies con diversi policyTypes (Ingress o Egress). Le policies che definiscono l'ingress (o egress) si sovrascriveranno.

Relazione tra i namespace

Per impostazione predefinita, la comunicazione tra i namespace è consentita. Questo può essere modificato tramite una policy restrittiva, che limiterà il traffico in uscita e/o in entrata verso il namespace (vedi "Regola di pulizia" sopra).

Bloccando l'accesso allo spazio dei nomi (vedi «Regola di pulizia» sopra), puoi apportare delle eccezioni alla politica restrittiva, consentendo le connessioni da uno specifico spazio dei nomi con namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Di conseguenza, tutti i pod nello spazio dei nomi default avranno accesso ai pod postgres nello spazio dei nomi database. Ma cosa succede se vuoi aprire l'accesso a postgres solo a specifici pod nello spazio dei nomi default?

Filtrare per spazi dei nomi E pod

Kubernetes versione 1.11 e superiori consente di combinare operatori namespaceSelector e podSelector utilizzando l'operatore logico E. Questo appare nel seguente modo:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Perché questo viene interpretato come E invece del consueto O?

Nota che podSelector non inizia con un trattino. In YAML questo significa che podSelector e quello che lo precede namespaceSelector appartengono allo stesso elemento della lista. Quindi vengono uniti logicamente con E.

Aggiungere un trattino prima di podSelector porterà alla creazione di un nuovo elemento della lista, che sarà combinato con il precedente namespaceSelector utilizzando l'operatore logico O.

Per selezionare i pod con un determinato etichetta in tutti gli spazi dei nomi, digita vuoto namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Le etichette multiple vengono unite con E

Le regole del firewall con più oggetti (host, reti, gruppi) sono combinate usando l'operatore logico O. La seguente regola si attiverà se la fonte del pacchetto corrisponde a Host_1 OPPURE Host_2:

| Fonte | Destinazione | Servizio | Azione |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Consenti  |
| Host_2 |             |         |        |
| ----------------------------------------|

Al contrario, in Kubernetes le diverse etichette in podSelector o namespaceSelector sono unite logicamente con E. Ad esempio, la seguente regola selezionerà i pod che hanno entrambe le etichette, role=db E version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

La stessa logica si applica a tutti i tipi di operatori: selettori di obiettivi delle politiche, selettori di pod e selettori di spazi dei nomi.

Sottogruppi e indirizzi IP (IPBlocks)

Per segmentare la rete, i firewall utilizzano VLAN, indirizzi IP e sottogruppi.

In Kubernetes, gli indirizzi IP vengono assegnati automaticamente ai pod e possono cambiare frequentemente, quindi vengono utilizzati i label per la selezione di pod e spazi dei nomi nelle politiche di rete.

Sottogruppi (ipBlocks) sono utilizzati per gestire le connessioni esterne in entrata (ingress) o in uscita (egress) (North-South). Ad esempio, questa politica consente a tutti i pod nel namespace default di accedere al servizio DNS di Google:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Un selettore di pod vuoto in questo esempio significa "selezionare tutti i pod nel namespace".

Questa politica consente l'accesso solo a 8.8.8.8; l'accesso a qualsiasi altro IP è vietato. Quindi, fondamentalmente, hai bloccato l'accesso al servizio DNS interno di Kubernetes. Se desideri comunque aprirlo, specifica esplicitamente.

Di solito ipBlocks e podSelectors sono mutuamente esclusivi, poiché gli indirizzi IP interni dei pod non vengono utilizzati in ipBlocks. Specificando gli IP interni dei pod, si consentono effettivamente connessioni da/a pod con questi indirizzi. In pratica, non saprai quale indirizzo IP utilizzare, ecco perché non dovrebbero essere utilizzati per selezionare i pod.

Come controesempio, la seguente policy include tutti gli IP e, di conseguenza, consente l'accesso a tutti gli altri pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

È possibile concedere accesso solo agli IP esterni, escludendo gli indirizzi IP interni dei pod. Ad esempio, se la subnet del tuo pod è 10.16.0.0/14:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Porte e protocolli

Di solito, i pod ascoltano una porta. Ciò significa che è possibile omettere i numeri di porta nelle politiche e lasciare tutto impostato sui valori predefiniti. Tuttavia, si consiglia di rendere le politiche il più restrittive possibile, quindi in alcuni casi è comunque possibile specificare le porte:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:
      - port: 443
        protocol: TCP
      - port: 80
        protocol: TCP
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Si noti che il selettore ports si applica a tutti gli elementi nel blocco to o from, in cui è contenuto. Per specificare porte diverse per diversi set di elementi, suddividi ingress o egress in più sezioni con to o from e in ciascuna specifica le tue porte:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:
     - port: 443
       protocol: TCP
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:
     - port: 80
       protocol: TCP
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Introduzione alle politiche di rete di Kubernetes per esperti di sicurezza

Funzionamento delle porte predefinite:

  • Se salti completamente la definizione delle porte (ports), ciò significa tutti i protocolli e tutte le porte;
  • Se salti la definizione del protocollo (protocol), ciò significa TCP;
  • Se salti la definizione della porta (port), ciò significa tutte le porte.

Pratica migliore: non fare affidamento sui valori predefiniti, specifica chiaramente ciò di cui hai bisogno.

Nota che è necessario utilizzare le porte dei pod e non dei servizi (maggiori dettagli nel paragrafo successivo).

Le politiche sono definite per i pod o per i servizi?

Di solito, i pod in Kubernetes comunicano tra loro tramite un servizio — un bilanciatore di carico virtuale che reindirizza il traffico ai pod che implementano il servizio. Si potrebbe pensare che le politiche di rete controllino l'accesso ai servizi, ma non è così. Le politiche di rete di Kubernetes funzionano con le porte dei pod, non con quelle dei servizi.

Ad esempio, se un servizio ascolta sulla porta 80, ma reindirizza il traffico alla porta 8080 dei suoi pod, nella politica di rete deve essere specificata proprio la 8080.

Un meccanismo del genere dovrebbe essere considerato subottimale: quando si modifica la configurazione interna del servizio (le cui porte sono ascoltate dai pod), sarà necessario aggiornare le politiche di rete.

Un nuovo approccio architetturale utilizzando il Service Mesh (ad esempio, vedi Istio qui sotto — nota del traduttore) può affrontare questo problema.

È necessario specificare sia Ingress che Egress?

La risposta breve è sì: affinché il pod A possa comunicare con il pod B, è necessario consentirgli di stabilire una connessione in uscita (per questo bisogna configurare la policy di egress), e il pod B deve poter accettare una connessione in entrata (per questo è necessaria una policy di ingress).

Tuttavia, nella pratica si può fare affidamento sulla policy predefinita che consente connessioni in una o entrambe le direzioni.

Se un certo podfonte viene selezionato da una o più egress-policy, i vincoli applicabili saranno definiti dalla loro disgiunzione. In questo caso, sarà necessario autorizzare esplicitamente la connessione al poddestinatario. Se un pod non è selezionato da alcuna policy, il suo traffico in uscita (egress) è autorizzato per impostazione predefinita.

Analogamente, il destino del poddestinatario, selezionato da una o più ingress-policy, sarà determinato dalla loro disgiunzione. In questo caso, è necessario autorizzargli esplicitamente di ricevere traffico dal pod sorgente. Se un pod non è selezionato da alcuna policy, tutto il traffico in ingresso (ingress) per esso è autorizzato per impostazione predefinita.

Vedi la sezione "Stateful o Stateless" qui sotto.

Log

Le policy di rete di Kubernetes non registrano il traffico. Ciò rende difficile determinare se la policy funzioni correttamente e complica notevolmente l'analisi della sicurezza.

Monitoraggio del traffico verso i servizi esterni

Le policy di rete di Kubernetes non consentono di specificare un nome di dominio completo (DNS) nelle sezioni egress. Questo comporta notevoli disagi nel tentativo di limitare il traffico verso indirizzi esterni privi di un IP fisso (come aws.com).

Verifica della policy

I firewall ti avviseranno o potrebbero persino rifiutarsi di accettare una policy errata. Anche Kubernetes compie alcune verifiche. Quando si imposta una policy di rete tramite kubectl, Kubernetes può dichiarare che è errata e rifiutarsi di accettarla. In altri casi, Kubernetes accetterà la policy e la completerà con dettagli mancanti. Questi possono essere visualizzati con il comando:

kubernetes get networkpolicy  -o yaml

Tieni presente che il sistema di verifica di Kubernetes non è infallibile e potrebbe trascurare alcuni tipi di errori.

Esecuzione

Kubernetes non gestisce autonomamente l'implementazione delle politiche di rete, fungendo invece da gateway API, trasferendo il compito oneroso di controllo al sistema sottostante noto come Container Networking Interface (CNI). Impostare politiche all'interno di un cluster Kubernetes senza assegnare il corrispondente CNI è paragonabile a creare politiche su un server di gestione del firewall senza successivamente applicarle ai firewall. Devi assicurarti di avere un CNI adeguato o, nel caso delle piattaforme Kubernetes ospitate nel cloud (puoi trovare l'elenco dei fornitori qui — nota del traduttore), implementare politiche di rete che installeranno il CNI per te.

Si prega di notare che Kubernetes non ti avviserà se imposti una politica di rete senza un adeguato CNI ausiliario.

Stateful o Stateless?

Tutti i CNI di Kubernetes che ho incontrato gestiscono stati (ad esempio, Calico utilizza Linux conntrack). Questo consente al pod di ricevere risposte per una connessione TCP che ha avviato senza doverla stabilire nuovamente. Tuttavia, non sono a conoscenza di uno standard Kubernetes che garantisca la gestione dello stato (statefulness).

Gestione avanzata della sicurezza

Ecco alcuni modi per migliorare l'efficacia della politica di sicurezza in Kubernetes:

  1. Il pattern architettonico Service Mesh utilizza contenitori sidecar per garantire telemetria dettagliata e controllo del traffico a livello di servizi. Un esempio è Istio.
  2. Alcuni fornitori di CNI hanno ampliato i loro strumenti per andare oltre le politiche di rete di Kubernetes.
  3. Tufin Orca fornisce trasparenza e automazione delle politiche di rete di Kubernetes.

Il pacchetto Tufin Orca gestisce le politiche di rete di Kubernetes (e funge da fonte per gli screenshot sopra).

Informazioni aggiuntive

Conclusione

Le politiche di rete di Kubernetes offrono una buona gamma di strumenti per la segmentazione dei cluster, ma risultano spesso poco intuitive e presentano molte complessità. Credo che a causa di questa difficoltà, molte politiche dei cluster esistenti siano errate. Le possibili soluzioni a questo problema includono l'automazione delle definizioni delle politiche o l'uso di altri strumenti di segmentazione.

Spero che questa guida possa chiarire alcuni dubbi e risolvere i problemi che potresti incontrare.

P.S. dal traduttore

Leggete anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster