O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Notă. transl.: Autorul articolului, Reuven Harrison, are peste 20 de ani de experiență în dezvoltarea de software, iar astăzi este CTO și co-fondator al Tufin, o companie care creează soluții de management al politicilor de securitate. În timp ce el vede politicile de rețea Kubernetes ca un instrument destul de puternic pentru segmentarea rețelei într-un cluster, el crede, de asemenea, că acestea nu sunt atât de ușor de implementat în practică. Acest material (destul de voluminos) are scopul de a îmbunătăți gradul de conștientizare a specialiștilor cu privire la această problemă și de a-i ajuta să creeze configurațiile necesare.

Astăzi, multe companii aleg din ce în ce mai mult Kubernetes pentru a-și rula aplicațiile. Interesul pentru acest software este atât de mare încât unii numesc Kubernetes „noul sistem de operare pentru centrul de date”. Treptat, Kubernetes (sau k8s) începe să fie perceput ca o parte critică a afacerii, ceea ce necesită organizarea proceselor de afaceri mature, inclusiv securitatea rețelei.

Pentru profesioniștii în securitate care sunt nedumeriți să lucreze cu Kubernetes, adevărata revelație poate fi politica implicită a platformei: permite totul.

Acest ghid vă va ajuta să înțelegeți structura internă a politicilor de rețea; înțelegeți cum diferă de regulile pentru firewall-urile obișnuite. De asemenea, va acoperi unele capcane și va oferi recomandări pentru a ajuta la securizarea aplicațiilor pe Kubernetes.

Politicile de rețea Kubernetes

Mecanismul de politică de rețea Kubernetes vă permite să gestionați interacțiunea aplicațiilor implementate pe platformă la nivelul rețelei (al treilea în modelul OSI). Politicile de rețea nu au unele dintre caracteristicile avansate ale firewall-urilor moderne, cum ar fi aplicarea OSI Layer 7 și detectarea amenințărilor, dar oferă un nivel de bază de securitate a rețelei care este un bun punct de plecare.

Politicile de rețea controlează comunicațiile dintre poduri

Sarcinile de lucru din Kubernetes sunt distribuite pe poduri, care constau din unul sau mai multe containere implementate împreună. Kubernetes atribuie fiecărui pod o adresă IP care este accesibilă din alte poduri. Politicile de rețea Kubernetes stabilesc drepturi de acces pentru grupuri de pod-uri în același mod în care grupurile de securitate din cloud sunt folosite pentru a controla accesul la instanțele mașinilor virtuale.

Definirea politicilor de rețea

Ca și alte resurse Kubernetes, politicile de rețea sunt specificate în YAML. În exemplul de mai jos, aplicația balance acces la 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

(Notă. transl.: această captură de ecran, ca toate celelalte similare ulterioare, a fost creată nu folosind instrumente native Kubernetes, ci folosind instrumentul Tufin Orca, care a fost dezvoltat de compania autorului articolului original și care este menționat la sfârșitul materialului.)

Pentru a vă defini propria politică de rețea, veți avea nevoie de cunoștințe de bază despre YAML. Acest limbaj se bazează pe indentare (specificată mai degrabă de spații decât de file). Un element indentat aparține celui mai apropiat element indentat de deasupra acestuia. Un nou element de listă începe cu o cratimă, toate celelalte elemente au forma valoare cheie.

După ce a descris politica în YAML, utilizați kubectlpentru a-l crea în cluster:

kubectl create -f policy.yaml

Specificația politicii de rețea

Specificația politicii de rețea Kubernetes include patru elemente:

  1. podSelector: definește podurile afectate de această politică (ținte) - obligatoriu;
  2. policyTypes: indică ce tipuri de politici sunt incluse în aceasta: intrare și/sau ieșire - opțional, dar recomand să le specificați în mod explicit în toate cazurile;
  3. ingress: definește permis de intrare traficul către podurile țintă este opțional;
  4. egress: definește permis de ieșire traficul de la podurile țintă este opțional.

Exemplu preluat de pe site-ul Kubernetes (am înlocuit role pe app), arată cum sunt utilizate toate cele patru elemente:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate
O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Vă rugăm să rețineți că toate cele patru elemente nu trebuie incluse. Este doar obligatoriu podSelector, alți parametri pot fi utilizați după cum doriți.

Dacă omiteți policyTypes, politica va fi interpretată după cum urmează:

  • În mod implicit, se presupune că definește partea de intrare. Dacă politica nu prevede acest lucru în mod explicit, sistemul va presupune că tot traficul este interzis.
  • Comportamentul pe partea de ieșire va fi determinat de prezența sau absența parametrului de ieșire corespunzător.

Pentru a evita greșelile recomand fă-l întotdeauna explicit policyTypes.

Conform logicii de mai sus, dacă parametrii ingress și / sau egress omisă, politica va refuza tot traficul (consultați „Regula de eliminare” de mai jos).

Politica implicită este Permite

Dacă nu sunt definite politici, Kubernetes permite întregul trafic în mod implicit. Toate podurile pot schimba liber informații între ele. Acest lucru poate părea contraintuitiv din perspectiva securității, dar rețineți că Kubernetes a fost conceput inițial de dezvoltatori pentru a permite interoperabilitatea aplicațiilor. Politicile de rețea au fost adăugate ulterior.

Spații de nume

Spațiile de nume sunt mecanismul de colaborare Kubernetes. Sunt concepute pentru a izola mediile logice unele de altele, în timp ce comunicarea între spații este permisă în mod implicit.

La fel ca majoritatea componentelor Kubernetes, politicile de rețea trăiesc într-un anumit spațiu de nume. În bloc metadata puteți specifica ce spațiu îi aparține politica:

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

Dacă spațiul de nume nu este specificat în mod explicit în metadate, sistemul va folosi spațiul de nume specificat în kubectl (în mod implicit namespace=default):

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

Vă recomand specificați în mod explicit spațiul de nume, cu excepția cazului în care scrieți o politică care vizează mai multe spații de nume simultan.

Primar element podSelector în politică va selecta pod-uri din spațiul de nume căruia îi aparține politica (i se interzice accesul la pod-uri dintr-un alt spațiu de nume).

În mod similar, podSelectors în blocurile de intrare și ieșire pot selecta poduri numai din propriul spațiu de nume, cu excepția cazului în care, desigur, le combinați namespaceSelector (acest lucru va fi discutat în secțiunea „Filtrare după spații de nume și poduri”).

Reguli de denumire a politicilor

Numele politicilor sunt unice în același spațiu de nume. Nu pot exista două politici cu același nume în același spațiu, dar pot exista politici cu același nume în spații diferite. Acest lucru este util atunci când doriți să aplicați din nou aceeași politică în mai multe spații.

Îmi place în special una dintre metodele de numire. Constă în combinarea numelui spațiului de nume cu podurile țintă. De exemplu:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Etichete

Puteți atașa etichete personalizate obiectelor Kubernetes, cum ar fi pod-uri și spații de nume. Etichete (etichete - etichete) sunt echivalentul etichetelor din cloud. Politicile de rețea Kubernetes folosesc etichete pentru a selecta păstăila care se aplica:

podSelector:
  matchLabels:
    role: db

… sau spații de numela care se aplică. Acest exemplu selectează toate podurile din spațiile de nume cu etichetele corespunzătoare:

namespaceSelector:
  matchLabels:
    project: myproject

O atenție: atunci când utilizați namespaceSelector asigurați-vă că spațiile de nume pe care le selectați conțin eticheta corectă. Rețineți că spațiile de nume încorporate, cum ar fi default и kube-system, în mod implicit nu conțin etichete.

Puteți adăuga o etichetă unui spațiu ca acesta:

kubectl label namespace default namespace=default

În același timp, spațiu de nume în secțiune metadata ar trebui să se refere la numele spațiului real, nu la etichetă:

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

Sursa si destinatia

Politicile firewall constau în reguli cu surse și destinații. Politicile de rețea Kubernetes sunt definite pentru o țintă - un set de pod-uri la care se aplică - și apoi stabilesc reguli pentru traficul de intrare și/sau de ieșire. În exemplul nostru, ținta politicii vor fi toate podurile din spațiul de nume default cu eticheta cu cheie app și sens 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate
O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Subsecțiunea ingress în această politică, deschide traficul de intrare către podurile țintă. Cu alte cuvinte, intrarea este sursa și ținta este destinația corespunzătoare. De asemenea, ieșirea este destinația și ținta este sursa acesteia.

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Acest lucru este echivalent cu două reguli de firewall: Intrare → Țintă; Obiectiv → Ieșire.

Ieșire și DNS (important!)

Prin limitarea traficului de ieșire, acordați o atenție deosebită DNS-ului - Kubernetes folosește acest serviciu pentru a mapa serviciile la adrese IP. De exemplu, următoarea politică nu va funcționa deoarece nu ați permis aplicația balance acces 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Puteți remedia problema deschizând accesul la serviciul 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Ultimul element to este gol și, prin urmare, selectează indirect toate podurile din toate spațiile de nume, permițând balance trimiteți interogări DNS către serviciul Kubernetes corespunzător (care rulează de obicei în spațiu kube-system).

Această abordare funcționează, totuși prea permisiv și nesigur, deoarece permite interogărilor DNS să fie direcționate în afara clusterului.

Îl poți îmbunătăți în trei pași succesivi.

1. Permiteți numai interogări DNS în cluster prin adăugare 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

2. Permite interogări DNS numai în spațiul de nume kube-system.

Pentru a face acest lucru, trebuie să adăugați o etichetă la spațiul de nume kube-system: kubectl label namespace kube-system namespace=kube-system - și scrieți-l în politica de utilizare 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

3. Oamenii paranoici pot merge și mai departe și pot limita interogările DNS la un anumit serviciu DNS în kube-system. Secțiunea „Filtrați după spații de nume și poduri” vă va spune cum să realizați acest lucru.

O altă opțiune este de a rezolva DNS la nivel de spațiu de nume. În acest caz, nu va fi necesar să fie deschis pentru fiecare serviciu:

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

Gol podSelector selectează toate podurile din spațiul de nume.

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Primul meci și ordinea regulilor

În firewall-urile convenționale, acțiunea (Allow sau Deny) asupra unui pachet este determinată de prima regulă pe care o îndeplinește. În Kubernetes, ordinea politicilor nu contează.

În mod implicit, atunci când nu sunt setate politici, sunt permise comunicațiile între poduri și pot face schimb de informații liber. Odată ce începeți să formulați politici, fiecare pod afectat de cel puțin unul dintre ele devine izolat în funcție de disjuncția (SAU logic) a tuturor politicilor care l-au selectat. Podurile care nu sunt afectate de nicio politică rămân deschise.

Puteți modifica acest comportament folosind o regulă de dezlipire.

Regula de eliminare („Refuză”)

Politicile firewall de obicei interzice orice trafic care nu este permis în mod explicit.

Nu există nicio acțiune de respingere în Kubernetes, totuși, un efect similar poate fi obținut cu o politică obișnuită (permisivă), selectând un grup gol de pod-uri sursă (ingress):

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Această politică selectează toate podurile din spațiul de nume și lasă intrarea nedefinită, interzicând tot traficul de intrare.

Într-un mod similar, puteți restricționa tot traficul de ieșire dintr-un spațiu de nume:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Vă rugăm să rețineți că orice politici suplimentare care permit traficul către poduri din spațiul de nume vor avea prioritate față de această regulă (similar cu adăugarea unei reguli de permis înaintea unei reguli de refuzare într-o configurație de firewall).

Permite totul (Orice-Orice-Orice-Permite)

Pentru a crea o politică Allow All, trebuie să completați politica Deny de mai sus cu un element gol ingress:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Permite accesul de la toate podurile din toate spațiile de nume (și toate IP-urile) către orice pod din spațiul de nume default. Acest comportament este activat în mod implicit, deci de obicei nu trebuie să fie definit în continuare. Cu toate acestea, uneori poate fi necesar să dezactivați temporar anumite permisiuni pentru a diagnostica problema.

Regula poate fi restrânsă pentru a permite accesul numai la un set specific de păstăi (app:balance) în spațiul de nume default:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Următoarea politică permite întregul trafic de intrare și ieșire, inclusiv accesul la orice IP din afara clusterului:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate
O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Combinarea mai multor politici

Politicile sunt combinate folosind SAU logic la trei niveluri; Permisiunile fiecărui pod sunt setate în conformitate cu disjuncția tuturor politicilor care îl afectează:

1. În câmpuri from и to Pot fi definite trei tipuri de elemente (toate combinate folosind OR):

  • namespaceSelector — selectează întregul spațiu de nume;
  • podSelector — selectează păstăile;
  • ipBlock — selectează o subrețea.

Mai mult, numărul de elemente (chiar identice) din subsecțiuni from/to nu este limitat. Toate vor fi combinate prin OR logic.

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

2. În interiorul secțiunii de politici ingress poate avea multe elemente from (combinat prin OR logic). La fel, secțiunea egress poate include multe elemente to (combinat și prin disjuncție):

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

3. Politici diferite sunt, de asemenea, combinate cu SAU logic

Dar atunci când le combinăm, există o limitare a subliniat Chris Cooney: Kubernetes poate combina doar politici cu diferite policyTypes (Ingress sau Egress). Politicile care definesc intrarea (sau ieșirea) se vor suprascrie reciproc.

Relația dintre spațiile de nume

În mod implicit, partajarea informațiilor între spațiile de nume este permisă. Acest lucru poate fi modificat prin utilizarea unei politici de refuzare care va restricționa traficul care iese și/sau intrarea în spațiul de nume (consultați „Regula de eliminare” de mai sus).

După ce ați blocat accesul la un spațiu de nume (consultați „Regula de eliminare” de mai sus), puteți face excepții de la politica de refuzare permițând conexiuni dintr-un anumit spațiu de nume folosind 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Ca rezultat, toate podurile din spațiul de nume default va avea acces la poduri postgres în spațiul de nume database. Dar ce se întâmplă dacă doriți să deschideți accesul la postgres numai poduri specifice în spațiul de nume default?

Filtrați după spații de nume și poduri

Kubernetes versiunea 1.11 și o versiune ulterioară vă permite să combinați operatori namespaceSelector и podSelector folosind AND logic. Arată astfel:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

De ce este interpretat acest lucru ca ȘI în loc de SAU obișnuit?

Vă rugăm să rețineți faptul că podSelector nu începe cu o cratimă. În YAML asta înseamnă că podSelector și stând în fața lui namespaceSelector se referă la același element de listă. Prin urmare, ele sunt combinate cu ȘI logic.

Adăugarea unei cratime înainte podSelector va avea ca rezultat apariția unui nou element de listă, care va fi combinat cu cel anterior namespaceSelector folosind SAU logic.

Pentru a selecta poduri cu o anumită etichetă în toate spațiile de nume, introduceți gol 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Mai multe etichete fac echipă cu I

Regulile pentru un firewall cu mai multe obiecte (gazde, rețele, grupuri) sunt combinate folosind SAU logic. Următoarea regulă va funcționa dacă sursa pachetului se potrivește Host_1 SAU Host_2:

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

Dimpotrivă, în Kubernetes diferitele etichete în podSelector sau namespaceSelector sunt combinate cu ȘI logic. De exemplu, următoarea regulă va selecta podurile care au ambele etichete, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

Aceeași logică se aplică tuturor tipurilor de operatori: selectoare de țintă de politică, selectoare de pod și selectoare de spații de nume.

Subrețele și adrese IP (IPBlocks)

Firewall-urile folosesc VLAN-uri, adrese IP și subrețele pentru a segmenta o rețea.

În Kubernetes, adresele IP sunt atribuite automat pod-urilor și se pot schimba frecvent, astfel încât etichetele sunt folosite pentru a selecta pod-urile și spațiile de nume din politicile de rețea.

Subrețele (ipBlocks) sunt utilizate la gestionarea conexiunilor externe (nord-sud) de intrare (intrare) sau de ieșire (ieșire). De exemplu, această politică se deschide pentru toate podurile din spațiul de nume default acces la serviciul DNS 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Selectorul de pod gol din acest exemplu înseamnă „selectați toate podurile din spațiul de nume”.

Această politică permite accesul numai la 8.8.8.8; accesul la orice alt IP este interzis. Deci, în esență, ați blocat accesul la serviciul intern Kubernetes DNS. Dacă tot doriți să îl deschideți, indicați acest lucru în mod explicit.

Obișnuit ipBlocks и podSelectors se exclud reciproc, deoarece adresele IP interne ale podurilor nu sunt utilizate în ipBlocks. Prin indicarea pod-uri IP interne, veți permite de fapt conexiuni către/de la poduri cu aceste adrese. În practică, nu veți ști ce adresă IP să utilizați, motiv pentru care nu ar trebui folosite pentru a selecta pod-uri.

Ca contra-exemplu, următoarea politică include toate IP-urile și, prin urmare, permite accesul la toate celelalte pod-uri:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Puteți deschide accesul numai la IP-uri externe, excluzând adresele IP interne ale pod-urilor. De exemplu, dacă subrețeaua podului este 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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Porturi și protocoale

De obicei, podurile ascultă un singur port. Aceasta înseamnă că pur și simplu nu puteți specifica numerele de port în politici și lăsați totul ca implicit. Cu toate acestea, este recomandat să faceți politicile cât mai restrictive posibil, astfel încât în ​​unele cazuri puteți încă specifica porturi:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Rețineți că selectorul ports se aplică tuturor elementelor din bloc to sau from, care contine. Pentru a specifica diferite porturi pentru diferite seturi de elemente, împărțiți ingress sau egress în mai multe subsecţiuni cu to sau from și în fiecare înregistrare porturile dvs.:

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

O introducere în politicile de rețea Kubernetes pentru profesioniștii în securitate

Operare implicită a portului:

  • Dacă omiteți complet definiția portului (ports), aceasta înseamnă toate protocoalele și toate porturile;
  • Dacă omiteți definiția protocolului (protocol), aceasta înseamnă TCP;
  • Dacă omiteți definiția portului (port), aceasta înseamnă toate porturile.

Cea mai bună practică: nu vă bazați pe valorile implicite, specificați în mod explicit ceea ce aveți nevoie.

Vă rugăm să rețineți că trebuie să utilizați porturi pod, nu porturi de serviciu (mai multe despre asta în paragraful următor).

Sunt definite politici pentru poduri sau servicii?

De obicei, podurile din Kubernetes se accesează reciproc printr-un serviciu - un echilibrator de încărcare virtual care redirecționează traficul către podurile care implementează serviciul. S-ar putea să credeți că politicile de rețea controlează accesul la servicii, dar nu este cazul. Politicile de rețea Kubernetes funcționează pe porturile pod, nu pe porturile de serviciu.

De exemplu, dacă un serviciu ascultă portul 80, dar redirecționează traficul către portul 8080 al pod-urilor sale, exact 8080 trebuie specificat în politica de rețea.

Un astfel de mecanism ar trebui considerat suboptim: dacă structura internă a serviciului (ale căror porturi le ascultă podurile) se modifică, politicile de rețea vor trebui actualizate.

Nouă abordare arhitecturală folosind Service Mesh (de exemplu, vezi despre Istio mai jos - aprox. traducere) vă permite să faceți față acestei probleme.

Este necesar să se înregistreze atât Ingress, cât și Egress?

Răspunsul scurt este da, pentru ca podul A să comunice cu podul B, trebuie să i se permită crearea unei conexiuni de ieșire (pentru aceasta trebuie să configurați o politică de ieșire), iar podul B trebuie să poată accepta o conexiune de intrare ( pentru aceasta, în consecință, aveți nevoie de o politică de intrare).politică).

Cu toate acestea, în practică, vă puteți baza pe politica implicită pentru a permite conexiuni în una sau ambele direcții.

Dacă vreo pod-sursă va fi selectat de unul sau mai multe ieşire-politicieni, restrictiile impuse acestuia vor fi determinate de disjungerea acestora. În acest caz, va trebui să permiteți în mod explicit conexiunea la pod -către destinatar. Dacă un pod nu este selectat de nicio politică, traficul său de ieșire (ieșire) este permis în mod implicit.

În mod similar, soarta păstăii esteadresa, selectat de unul sau mai multe pătrundere-politicienii, vor fi determinate de disjuncția lor. În acest caz, trebuie să îi permiteți în mod explicit să primească trafic de la podul sursă. Dacă un pod nu este selectat de nicio politică, tot traficul de intrare pentru acesta este permis în mod implicit.

Vezi mai jos Stateful sau Stateless.

Bușteni

Politicile de rețea Kubernetes nu pot înregistra traficul. Acest lucru face dificilă determinarea dacă o politică funcționează conform intenției și complică foarte mult analiza securității.

Controlul traficului către serviciile externe

Politicile de rețea Kubernetes nu vă permit să specificați un nume de domeniu complet (DNS) în secțiunile de ieșire. Acest fapt duce la inconveniente semnificative atunci când se încearcă limitarea traficului către destinații externe care nu au o adresă IP fixă ​​(cum ar fi aws.com).

Verificarea politicii

Firewall-urile vă vor avertiza sau chiar vor refuza să acceptați politica greșită. Kubernetes face, de asemenea, unele verificări. Când setați o politică de rețea prin kubectl, Kubernetes poate declara că este incorectă și poate refuza să o accepte. În alte cazuri, Kubernetes va prelua politica și o va completa cu detaliile lipsă. Ele pot fi văzute folosind comanda:

kubernetes get networkpolicy <policy-name> -o yaml

Rețineți că sistemul de validare Kubernetes nu este infailibil și poate rata anumite tipuri de erori.

Execuție

Kubernetes nu implementează politicile de rețea în sine, ci este doar un gateway API care deleagă sarcina controlului unui sistem subiacent numit Container Networking Interface (CNI). Setarea politicilor pe un cluster Kubernetes fără alocarea CNI-ului adecvat este aceeași cu crearea politicilor pe un server de gestionare a firewall-ului fără a le instala apoi pe firewall-uri. Depinde de tine să te asiguri că ai un CNI decent sau, în cazul platformelor Kubernetes, găzduit în cloud (puteți vedea lista furnizorilor aici — aprox. traducere), activați politicile de rețea care vor seta CNI pentru dvs.

Rețineți că Kubernetes nu vă va avertiza dacă setați o politică de rețea fără ajutorul CNI adecvat.

Cu stat sau apatrid?

Toate CNI-urile Kubernetes pe care le-am întâlnit sunt cu stare (de exemplu, Calico utilizează Linux conntrack). Acest lucru permite podului să primească răspunsuri pe conexiunea TCP pe care a inițiat-o fără a fi nevoie să o restabilize. Cu toate acestea, nu cunosc un standard Kubernetes care să garanteze starea.

Management avansat al politicii de securitate

Iată câteva modalități de a îmbunătăți aplicarea politicii de securitate în Kubernetes:

  1. Modelul arhitectural Service Mesh folosește containere sidecar pentru a oferi telemetrie detaliată și control al traficului la nivel de serviciu. Ca exemplu putem lua Istio.
  2. Unii dintre furnizorii CNI și-au extins instrumentele pentru a depăși politicile de rețea Kubernetes.
  3. Tufin Orca Oferă vizibilitate și automatizare a politicilor de rețea Kubernetes.

Pachetul Tufin Orca gestionează politicile de rețea Kubernetes (și este sursa capturilor de ecran de mai sus).

informaţii suplimentare

Concluzie

Politicile de rețea Kubernetes oferă un set bun de instrumente pentru segmentarea clusterelor, dar nu sunt intuitive și au multe subtilități. Din cauza acestei complexități, cred că multe politici existente de cluster sunt greșite. Soluțiile posibile la această problemă includ automatizarea definițiilor politicilor sau utilizarea altor instrumente de segmentare.

Sper că acest ghid vă ajută la clarificarea unor întrebări și la rezolvarea problemelor pe care le puteți întâlni.

PS de la traducator

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu