Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Nota. trad.: L'autore dell'articolo, Reuven Harrison, ha oltre 20 anni di esperienza nello sviluppo di software e oggi è CTO e cofondatore di Tufin, un'azienda che crea soluzioni di gestione delle policy di sicurezza. Sebbene consideri le policy di rete Kubernetes come uno strumento abbastanza potente per la segmentazione della rete in un cluster, ritiene anche che non siano così facili da implementare nella pratica. Questo materiale (abbastanza voluminoso) ha lo scopo di migliorare la consapevolezza degli specialisti su questo problema e aiutarli a creare le configurazioni necessarie.

Oggi molte aziende scelgono sempre più Kubernetes per eseguire le proprie applicazioni. L’interesse per questo software è così alto che alcuni chiamano Kubernetes “il nuovo sistema operativo per il data center”. A poco a poco, Kubernetes (o k8s) comincia a essere percepito come una parte critica del business, che richiede l'organizzazione di processi aziendali maturi, inclusa la sicurezza della rete.

Per i professionisti della sicurezza che sono perplessi lavorando con Kubernetes, la vera rivelazione potrebbe essere la politica predefinita della piattaforma: consentire tutto.

Questa guida ti aiuterà a comprendere la struttura interna delle politiche di rete; capire come differiscono dalle regole per i normali firewall. Coprirà inoltre alcune insidie ​​​​e fornirà consigli per aiutare a proteggere le applicazioni su Kubernetes.

Politiche di rete Kubernetes

Il meccanismo delle policy di rete Kubernetes consente di gestire l'interazione delle applicazioni distribuite sulla piattaforma a livello di rete (il terzo nel modello OSI). Le policy di rete non dispongono di alcune delle funzionalità avanzate dei firewall moderni, come l'applicazione di OSI Layer 7 e il rilevamento 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 pod, costituiti da uno o più contenitori distribuiti insieme. Kubernetes assegna a ciascun pod un indirizzo IP accessibile da altri pod. Le policy di rete Kubernetes impostano i diritti di accesso per i gruppi di pod nello stesso modo in cui i gruppi di sicurezza nel cloud vengono utilizzati per controllare l'accesso alle istanze della macchina virtuale.

Definizione delle politiche di rete

Come altre risorse Kubernetes, le policy di rete sono specificate in YAML. Nell'esempio seguente, l'applicazione balance 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

(Nota. trad.: questo screenshot, come tutti i successivi simili, è stato creato non utilizzando gli strumenti nativi di Kubernetes, ma utilizzando lo strumento Tufin Orca, sviluppato dalla società dell'autore dell'articolo originale e menzionato alla fine del materiale.)

Per definire la tua politica di rete, avrai bisogno di una conoscenza di base di YAML. Questo linguaggio è basato sul rientro (specificato da spazi anziché da tabulazioni). Un elemento rientrato appartiene all'elemento rientrato più vicino sopra di esso. Un nuovo elemento della lista inizia con un trattino, tutti gli altri elementi hanno la forma valore-chiave.

Dopo aver descritto la policy in YAML, utilizzare kubectlper crearlo nel cluster:

kubectl create -f policy.yaml

Specifica della politica di rete

La specifica della politica di rete Kubernetes include quattro elementi:

  1. podSelector: definisce i pod interessati da questa politica (obiettivi) - obbligatorio;
  2. policyTypes: indica quali tipi di policy sono incluse in questo: ingresso e/o uscita - facoltativo, ma consiglio di specificarlo esplicitamente in tutti i casi;
  3. ingress: definisce consentito arrivo traffico verso i pod target - facoltativo;
  4. egress: definisce consentito in uscita il traffico dai pod di destinazione è facoltativo.

Esempio tratto dal sito Kubernetes (ho sostituito role su 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza
Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Tieni presente che non è necessario includere tutti e quattro gli elementi. È solo obbligatorio podSelector, altri parametri possono essere utilizzati a piacere.

Se ometti policyTypes, la politica sarà interpretata come segue:

  • Per impostazione predefinita, si presuppone che definisca il lato di ingresso. Se la policy non lo afferma esplicitamente, il sistema presumerà che tutto il traffico sia vietato.
  • Il comportamento sul lato di uscita sarà determinato dalla presenza o dall'assenza del parametro di uscita corrispondente.

Per evitare errori lo consiglio renderlo sempre esplicito policyTypes.

Secondo la logica di cui sopra, se i parametri ingress e / o egress omessa, la policy negherà tutto il traffico (vedi "Regola di stripping" di seguito).

La policy predefinita è Consenti

Se non vengono definite policy, Kubernetes consente tutto il traffico per impostazione predefinita. Tutti i pod possono scambiarsi liberamente informazioni tra loro. Ciò può sembrare controintuitivo dal punto di vista della sicurezza, ma ricorda che Kubernetes è stato originariamente progettato dagli sviluppatori per consentire l'interoperabilità delle applicazioni. Le politiche di rete sono state aggiunte successivamente.

Spazi dei nomi

Gli spazi dei nomi sono il meccanismo di collaborazione Kubernetes. Sono progettati per isolare gli ambienti logici gli uni dagli altri, mentre la comunicazione tra gli spazi è consentita per impostazione predefinita.

Come la maggior parte dei componenti Kubernetes, le policy di rete risiedono in uno spazio dei nomi specifico. Nel blocco metadata puoi specificare a quale spazio appartiene la polizza:

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

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

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

Vi consiglio specificare lo spazio dei nomi in modo esplicito, a meno che tu non stia scrivendo una policy destinata a più spazi dei nomi contemporaneamente.

primario elemento podSelector nella policy selezionerà i pod dallo spazio dei nomi a cui appartiene la policy (gli viene negato l'accesso ai pod da un altro spazio dei nomi).

Allo stesso modo, podSelectors nei blocchi di ingresso e di uscita puoi selezionare solo i pod dal proprio spazio dei nomi, a meno che ovviamente non li combini con namespaceSelector (questo sarà discusso nella sezione "Filtro per namespace e pod").

Regole di denominazione delle policy

I nomi delle policy sono univoci all'interno dello stesso spazio dei nomi. Non possono esserci due policy con lo stesso nome nello stesso spazio, ma possono esserci policy con lo stesso nome in spazi diversi. Ciò è utile quando desideri riapplicare la stessa policy su più spazi.

Mi piace particolarmente uno dei metodi di denominazione. Consiste nel combinare il nome dello spazio dei nomi con i pod di destinazione. Per 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Etichette

Puoi allegare etichette personalizzate agli oggetti Kubernetes, come pod e spazi dei nomi. Etichette (etichette - tag) sono l'equivalente dei tag nel cloud. Le policy di rete Kubernetes utilizzano le etichette per la selezione baccellia cui si applicano:

podSelector:
  matchLabels:
    role: db

… o spazi dei nomia cui si applicano. Questo esempio seleziona tutti i pod negli spazi dei nomi con le etichette corrispondenti:

namespaceSelector:
  matchLabels:
    project: myproject

Un avvertimento: durante l'utilizzo namespaceSelector assicurati che gli spazi dei nomi selezionati contengano l'etichetta corretta. Tieni presente che gli spazi dei nomi integrati come default и kube-system, per impostazione predefinita non contengono etichette.

Puoi aggiungere un'etichetta a uno spazio come questo:

kubectl label namespace default namespace=default

Allo stesso tempo, spazio dei nomi nella sezione metadata dovrebbe fare riferimento al nome effettivo dello spazio, non all'etichetta:

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

Origine e destinazione

Le policy firewall sono costituite da regole con origini e destinazioni. Le policy di rete Kubernetes vengono definite per una destinazione, ovvero un insieme di pod a cui si applicano, e quindi impostano le regole per il traffico in entrata e/o in uscita. Nel nostro esempio, l'obiettivo della policy saranno tutti i pod nello spazio dei nomi default con etichetta con chiave app e significato 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza
Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Sottosezione ingress in questa policy, apre il traffico in entrata ai pod di destinazione. In altre parole, l'ingresso è l'origine e la destinazione è la destinazione corrispondente. Allo stesso modo, l'uscita è la destinazione e la destinazione è la sua origine.

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Ciò equivale a due regole del firewall: Ingress → Target; Obiettivo → Uscita.

Uscita e DNS (importante!)

Limitando il traffico in uscita, prestare particolare attenzione al DNS - Kubernetes utilizza questo servizio per mappare i servizi sugli indirizzi IP. Ad esempio, la seguente policy non funzionerà perché non hai consentito l'applicazione balance accedi 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Puoi risolverlo aprendo 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Ultimo elemento to è vuoto e quindi seleziona indirettamente tutti i pod in tutti gli spazi dei nomi, permettendo balance invia query DNS al servizio Kubernetes appropriato (solitamente in esecuzione nello spazio kube-system).

Questo approccio funziona, comunque eccessivamente permissivo e insicuro, poiché consente di indirizzare le query DNS all'esterno del cluster.

Puoi migliorarlo in tre passaggi successivi.

1. Consenti solo query DNS interno 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

2. Consenti query DNS solo all'interno dello spazio dei nomi kube-system.

Per fare ciò è necessario aggiungere un'etichetta al namespace kube-system: kubectl label namespace kube-system namespace=kube-system - e scriverlo nella policy utilizzando 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

3. Le persone paranoiche possono andare ancora oltre e limitare le query DNS a un servizio DNS specifico kube-system. La sezione "Filtra per spazi dei nomi E pod" ti spiegherà come ottenere questo risultato.

Un'altra opzione è risolvere il 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

nullo podSelector seleziona tutti i pod nello spazio dei nomi.

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Prima partita e ordine delle regole

Nei firewall convenzionali, l'azione (Consenti o Nega) su un pacchetto è determinata dalla prima regola che soddisfa. In Kubernetes l'ordine delle policy non ha importanza.

Per impostazione predefinita, quando non vengono impostate policy, le comunicazioni tra i pod sono consentite e possono scambiarsi liberamente informazioni. Una volta che si inizia a formulare le policy, ogni pod interessato da almeno uno di essi viene isolato in base alla disgiunzione (OR logico) di tutte le policy che lo hanno selezionato. I pod non interessati da alcuna policy rimangono aperti.

Puoi modificare questo comportamento utilizzando un filetto di estrazione.

Regola di stripping (“Nega”)

Le policy del firewall in genere negano qualsiasi traffico non esplicitamente consentito.

Non esiste alcuna azione di negazione in Kubernetes, tuttavia, un effetto simile può essere ottenuto con una policy regolare (permissiva) selezionando un gruppo vuoto di pod di origine (ingress):

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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Questa policy seleziona tutti i pod nello spazio dei nomi e lascia l'ingresso indefinito, negando tutto il traffico in entrata.

In modo simile, puoi limitare tutto il traffico in uscita da uno spazio dei nomi:

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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Si prega di notare che eventuali politiche aggiuntive che consentono il traffico ai pod nello spazio dei nomi avranno la precedenza su questa regola (simile all'aggiunta di una regola di autorizzazione prima di una regola di rifiuto in una configurazione del firewall).

Consenti tutto (Qualsiasi-Qualsiasi-Qualsiasi-Consenti)

Per creare una policy Consenti tutto, è necessario integrare la policy Deny sopra con un elemento vuoto ingress:

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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

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 in genere non è necessario definirlo ulteriormente. Tuttavia, a volte potrebbe essere necessario disabilitare temporaneamente alcune autorizzazioni specifiche per diagnosticare il problema.

La regola può essere ristretta per consentire l'accesso 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

La seguente policy consente tutto il traffico in entrata e in uscita, incluso l'accesso a qualsiasi IP esterno al cluster:

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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza
Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Combinazione di più politiche

Le policy vengono combinate utilizzando l'OR logico a tre livelli; Le autorizzazioni di ciascun pod sono impostate in conformità con la disgiunzione di tutte le politiche che lo influenzano:

1. Nei campi from и to È possibile definire tre tipi di elementi (tutti combinati utilizzando OR):

  • namespaceSelector — seleziona l'intero spazio dei nomi;
  • podSelector — seleziona i baccelli;
  • ipBlock — seleziona una sottorete.

Inoltre, il numero di elementi (anche identici) nelle sottosezioni from/to non limitato. Tutti verranno combinati tramite OR logico.

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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

2. All'interno della sezione policy ingress può avere molti elementi from (combinati da OR logico). Allo stesso modo, la sezione egress può includere molti elementi to (anche combinati per 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

3. Diverse politiche sono anche combinate con l'OR logico

Ma quando li si combinano, c'è una limitazione su cui ho Chris Cooney: Kubernetes può combinare solo policy diverse policyTypes (Ingress o Egress). Le policy che definiscono l'ingresso (o l'uscita) si sovrascriveranno a vicenda.

Relazione tra spazi dei nomi

Per impostazione predefinita, è consentita la condivisione delle informazioni tra spazi dei nomi. Questo può essere modificato utilizzando una policy di rifiuto che limiterà il traffico in uscita e/o in entrata nello spazio dei nomi (vedere "Regola di stripping" sopra).

Una volta bloccato l'accesso a uno spazio dei nomi (vedi la "Regola di stripping" sopra), puoi fare eccezioni alla politica di negazione consentendo le connessioni da uno spazio dei nomi specifico utilizzando 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della 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 pod specifici nello spazio dei nomi default?

Filtra per spazi dei nomi e pod

Kubernetes versione 1.11 e successive consentono di combinare gli operatori namespaceSelector и podSelector utilizzando l'operatore logico AND. Il risultato è questo:

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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Perché viene interpretato come AND invece del solito OR?

Si noti che podSelector non inizia con un trattino. In YAML questo significa questo podSelector e stare di fronte a lui namespaceSelector fare riferimento allo stesso elemento della lista. Pertanto, sono combinati con AND logico.

Aggiunta di un trattino prima podSelector comporterà l'emergere di un nuovo elemento della lista, che verrà combinato con quello precedente namespaceSelector utilizzando l'OR logico.

Per selezionare i pod con un'etichetta specifica in tutti gli spazi dei nomi, inserisci 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Molteplici etichette si uniscono a I

Le regole per un firewall con più oggetti (host, reti, gruppi) vengono combinate utilizzando l'OR logico. La seguente regola funzionerà se l'origine del pacchetto corrisponde Host_1 OR Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

Al contrario, in Kubernetes le varie etichette in podSelector o namespaceSelector sono combinati con AND logico. Ad esempio, la seguente regola selezionerà i pod che hanno entrambe le etichette, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

La stessa logica si applica a tutti i tipi di operatori: selettori di target della policy, selettori pod e selettori dello spazio dei nomi.

Sottoreti e indirizzi IP (IPBlock)

I firewall utilizzano VLAN, indirizzi IP e sottoreti per segmentare una rete.

In Kubernetes, gli indirizzi IP vengono assegnati automaticamente ai pod e possono cambiare frequentemente, quindi le etichette vengono utilizzate per selezionare pod e spazi dei nomi nelle policy di rete.

Sottoreti (ipBlocks) vengono utilizzati quando si gestiscono le connessioni esterne (Nord-Sud) in entrata (ingress) o in uscita (egress). Ad esempio, questa policy si apre a tutti i pod dello spazio dei nomi default accesso 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Il selettore pod vuoto in questo esempio significa "seleziona tutti i pod nello spazio dei nomi".

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

Solitamente ipBlocks и podSelectors si escludono a vicenda, poiché gli indirizzi IP interni dei pod non vengono utilizzati ipBlocks. Indicando pod IP interni, consentirai effettivamente le connessioni da/verso i pod con questi indirizzi. In pratica non saprai quale indirizzo IP utilizzare, motivo per cui non dovrebbero essere utilizzati per selezionare i pod.

Come controesempio, la seguente policy include tutti gli IP e pertanto 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Puoi aprire l'accesso solo agli IP esterni, escludendo gli indirizzi IP interni dei pod. Ad esempio, se la sottorete 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Porte e protocolli

In genere i pod ascoltano una porta. Ciò significa che non puoi semplicemente specificare i numeri di porta nelle policy e lasciare tutto come predefinito. Tuttavia, si consiglia di rendere le policy quanto 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Tieni presente che il selettore ports si applica a tutti gli elementi del blocco to o from, che contiene. Per specificare porte diverse per insiemi di elementi diversi, dividere ingress o egress in diverse sottosezioni con to o from e in ogni registro 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

Un'introduzione alle policy di rete Kubernetes per i professionisti della sicurezza

Operazione porta predefinita:

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

Procedura consigliata: non fare affidamento sui valori predefiniti, specifica ciò di cui hai bisogno in modo esplicito.

Tieni presente che devi utilizzare le porte pod, non le porte di servizio (maggiori informazioni su questo nel paragrafo successivo).

Sono definite policy per pod o servizi?

In genere, i pod in Kubernetes si accedono tra loro tramite un servizio, un bilanciatore del carico virtuale che reindirizza il traffico ai pod che implementano il servizio. Potresti pensare che le politiche di rete controllino l'accesso ai servizi, ma non è così. Le policy di rete Kubernetes funzionano sulle porte pod, non sulle porte di servizio.

Ad esempio, se un servizio è in ascolto sulla porta 80, ma reindirizza il traffico alla porta 8080 dei suoi pod, devi specificare esattamente 8080 nella politica di rete.

Un tale meccanismo dovrebbe essere considerato non ottimale: se la struttura interna del servizio (le porte su cui i pod ascoltano) cambia, le politiche di rete dovranno essere aggiornate.

Nuovo approccio architetturale utilizzando Service Mesh (ad esempio, vedi sotto su Istio - trad. ca.) ti permette di affrontare questo problema.

È necessario registrare sia Ingress che Egress?

La risposta breve è sì, affinché il pod A possa comunicare con il pod B, deve essere consentito creare una connessione in uscita (per questo è necessario configurare una policy di uscita) e il pod B deve essere in grado di accettare una connessione in entrata ( per questo, di conseguenza, è necessaria una politica di ingresso).

Tuttavia, in pratica, puoi fare affidamento sulla policy predefinita per consentire le connessioni in una o entrambe le direzioni.

Se qualche pod-fonte sarà selezionato da uno o più uscita-politici, le restrizioni imposte saranno determinate dalla loro disgiunzione. In questo caso, dovrai consentire esplicitamente la connessione al pod -al destinatario. Se un pod non è selezionato da alcuna policy, il relativo traffico in uscita (in uscita) è consentito per impostazione predefinita.

Allo stesso modo, il destino del pod èl'indirizzo, selezionato da uno o più ingresso-i politici, saranno determinati dalla loro disgiunzione. In questo caso, devi consentirlo esplicitamente di ricevere traffico dal pod di origine. Se un pod non è selezionato da alcuna policy, tutto il traffico in entrata per esso è consentito per impostazione predefinita.

Vedere Stateful o Stateless di seguito.

logs

Le policy di rete Kubernetes non possono registrare il traffico. Ciò rende difficile determinare se una policy funziona come previsto e complica notevolmente l’analisi della sicurezza.

Controllo del traffico verso servizi esterni

Le policy di rete Kubernetes non consentono di specificare un nome di dominio completo (DNS) nelle sezioni in uscita. Questo fatto porta a notevoli inconvenienti quando si cerca di limitare il traffico verso destinazioni esterne che non hanno un indirizzo IP fisso (come aws.com).

Controllo delle politiche

I firewall ti avviseranno o addirittura rifiuteranno di accettare la politica sbagliata. Kubernetes esegue anche alcune verifiche. Quando si imposta una politica di rete tramite kubectl, Kubernetes può dichiarare che non è corretta e rifiutarsi di accettarla. In altri casi, Kubernetes prenderà la policy e la completerà con i dettagli mancanti. Possono essere visualizzati utilizzando il comando:

kubernetes get networkpolicy <policy-name> -o yaml

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

Esecuzione

Kubernetes non implementa le policy di rete in sé, ma è semplicemente un gateway API che delega l'onere del controllo a un sistema sottostante chiamato Container Networking Interface (CNI). Impostare le policy su un cluster Kubernetes senza assegnare la CNI appropriata equivale a creare policy su un server di gestione del firewall senza poi installarle sui firewall. Sta a te assicurarti di avere un CNI decente o, nel caso delle piattaforme Kubernetes, ospitato nel cloud (puoi vedere l'elenco dei fornitori qui - ca. trans.), abilita i criteri di rete che imposteranno CNI per te.

Tieni presente che Kubernetes non ti avviserà se imposti una policy di rete senza l'helper CNI appropriato.

Apolide o apolide?

Tutti i CNI Kubernetes che ho incontrato sono stateful (ad esempio, Calico utilizza Linux conntrack). Ciò consente al pod di ricevere risposte sulla connessione TCP avviata senza doverla ristabilire. Tuttavia, non sono a conoscenza di uno standard Kubernetes che garantisca lo statefulness.

Gestione avanzata delle politiche di sicurezza

Ecco alcuni modi per migliorare l'applicazione delle policy di sicurezza in Kubernetes:

  1. Il modello architettonico Service Mesh utilizza contenitori sidecar per fornire telemetria dettagliata e controllo del traffico a livello di servizio. Come esempio possiamo prendere Istio.
  2. Alcuni fornitori CNI hanno esteso i propri strumenti per andare oltre le policy di rete Kubernetes.
  3. Tufin Orca Fornisce visibilità e automazione delle policy di rete Kubernetes.

Il pacchetto Tufin Orca gestisce le policy di rete Kubernetes (ed è la fonte degli screenshot sopra).

ulteriori informazioni

conclusione

Le policy di rete Kubernetes offrono un buon set di strumenti per segmentare i cluster, ma non sono intuitive e presentano molte sottigliezze. A causa di questa complessità, ritengo che molte policy di cluster esistenti siano difettose. Le possibili soluzioni a questo problema includono l'automazione delle definizioni delle politiche o l'utilizzo di altri strumenti di segmentazione.

Spero che questa guida aiuti a chiarire alcune domande e a risolvere i problemi che potresti incontrare.

PS da traduttore

Leggi anche sul nostro blog:

Fonte: habr.com

Aggiungi un commento