Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Bem. overs.: Artiklen er skrevet af Reuven Harrison, som har over 20 års erfaring med softwareudvikling og i dag er teknisk direktør og medstifter af Tufin, der udvikler løsninger til håndtering af sikkerhedspolitikker. Selvom han betragter netværkspolitikker i Kubernetes som et kraftfuldt redskab til netværkssegmentering i klynger, mener han samtidig, at de ikke er så nemme at anvende i praksis. Dette materiale (som er ret omfattende) har til formål at øge bevidstheden hos fagfolk om emnet og hjælpe dem med at skabe de nødvendige konfigurationer.

I dag vælger mange virksomheder i stigende grad Kubernetes til at køre deres applikationer. Interessen for denne software er så stor, at nogle kalder Kubernetes "det nye operativsystem for datacentre". Langsomt men sikkert begynder Kubernetes (eller k8s) at blive opfattet som en kritisk vigtig del af forretningen, der kræver etablering af modne forretningsprocesser, herunder sikring af netværkssikkerhed.

For sikkerhedsspecialister, der er foruroliget over arbejdet med Kubernetes, kan standardpolitikken for denne platform være en øjenåbner: tillad alt.

Denne vejledning vil hjælpe med at forstå det indre arbejde af netværkspolitikker; forstå forskellene fra regler for almindelige firewall. Der vil også blive diskuteret nogle faldgruber, og der gives anbefalinger, som kan hjælpe med at beskytte applikationer i Kubernetes.

Kubernetes-netværkspolitikker

Mechanismen for Kubernetes-netværkspolitikker gør det muligt at styre interaktionen mellem applikationer implementeret på platformen på netværksniveau (det tredje niveau i OSI-modellen). Netværkspolitikker mangler nogle af de avancerede funktioner fra moderne firewalls, såsom kontrol på niveau 7 i OSI og trusselsopdagelse, men de leverer et grundlæggende niveau af netværkssikkerhed, som er en god start.

Netværkspolitikker kontrollerer kommunikationen mellem pod'ene

Arbejdsbelastninger i Kubernetes fordeles mellem pods, der består af en eller flere containere, som kører sammen. Kubernetes tildeler hver pod en IP-adresse, der er tilgængelig fra andre pods. Kubernetes-netværkspolitikker definerer adgangsrettigheder for grupper af pods på samme måde, som sikkerhedsgrupper i skyen bruges til at styre adgangen til virtuelle maskiner.

Definition af netværkspolitikker

Som andre Kubernetes-ressourcer defineres netværkspolitikker i YAML-sprog. I det følgende eksempel får anvendelsen balance adgang til 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

(Bem. overs.: dette screenshot, ligesom alle følgende lignende, er skabt ved hjælp af værktøjet Tufin Orca, som er udviklet af forfatteren til den oprindelige artikel og nævnes i slutningen af materialet.)

For at definere en egen netværkspolitik kræves grundlæggende kendskab til YAML. Dette sprog er baseret på indrykning (som skal angives med mellemrum, ikke tabulatorer). Et element med indrykning tilhører det nærmeste overliggende element med indrykning. Et nyt listeelement starter med en bindestreg, og alle andre elementer fremstår som nøgle-værdi.

Når du har beskrevet politikken i YAML, skal du bruge kubectl, for at oprette den i klyngen:

kubectl create -f policy.yaml

Specifikation af netværkspolitik

Specifikationen af Kubernetes-netværkspolitikken består af fire elementer:

  1. podSelector: definerer de pods, der omfattes af denne politik (mål) - obligatorisk;
  2. policyTypes: angiver, hvilke typer politikker der er inkluderet: ingress og/eller egress - valgfrit, men jeg anbefaler at skrive det klart i alle tilfælde;
  3. ingress: definerer den tilladte indgående trafik til de målrettede pods - valgfrit;
  4. egress: definerer den tilladte udgående trafik fra de målrettede pods - valgfrit.

Et eksempel hentet fra Kubernetes' hjemmeside (jeg har ændret rolle og få en fungerende kommando. app), viser hvordan alle fire elementer anvendes:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister
Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Bemærk, at det ikke er obligatorisk at inkludere alle fire elementer. Kun podSelectorer nødvendigt, mens de øvrige parametre kan bruges valgfrit.

Hvis du udelader policyTypes, vil politikken blive fortolket som følger:

  • Som standard antages det, at den definerer ingress-siden. Hvis der ikke er eksplicitte angivelser i politikken, vil systemet betragte al trafik som forbudt.
  • Adfærden på egress-siden bestemmes af tilstedeværelsen eller fraværet af den tilsvarende egress-parameter.

For at undgå fejl anbefaler jeg altid at angive eksplicit policyTypes.

I overensstemmelse med den ovenstående logik, hvis parametrene ingress og/eller egress udelades, vil politikken forbyde al trafik (se "Rydningsregel" nedenfor).

Standardpolitikken er at tillade

Hvis der ikke er defineret politikker, tillader Kubernetes som standard al trafik. Alle pods kan frit kommunikere indbyrdes. Set fra et sikkerhedsperspektiv kan det synes illogisk, men husk at Kubernetes oprindeligt blev skabt af udviklerne med det formål at muliggøre interaktion mellem applikationer. Netværkspolitikker blev tilføjet senere.

Navnerum

Navnerum (Namespaces) er et mekanisme til kollektivt arbejde i Kubernetes. De er beregnet til at isolere logiske miljøer fra hinanden, mens dataudveksling mellem navnerum som standard er tilladt.

Som med de fleste Kubernetes-komponenter lever netværkspolitikker i et bestemt navnerum. I blokken metadata kan du angive, hvilket navnerum politikken tilhører:

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

Hvis navnerummet i metadata ikke er angivet eksplicit, vil systemet bruge det navnerum, der er angivet i kubectl (som standard namespace=default):

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

Jeg anbefaler eksplicit at angive navnerummet, medmindre du skriver en politik, der er beregnet til flere navnerum på én gang.

Primær element podSelector i politikken vil vælge pods fra det navnerum, som politikken tilhører (den har ikke adgang til pods fra andre navnerum).

Tilsvarende kan podSelectors i ingress- og egress-blokke kun vælge pods fra deres eget navnerum, medmindre du sammenkæder dem ved hjælp af namespaceSelector (dette vil blive diskuteret i sektionen “Filtrering efter navnerum og pods”).

Navngivningsregler for politikker

Politiknavnene er unikke inden for et enkelt navnerum. Der kan ikke være to politikker med samme navn i ét navnerum, men der kan være politikker med samme navne i forskellige navnerum. Dette er praktisk, når du vil genbruge den samme politik på flere navnerum.

Jeg kan især godt lide en af måderne at navngive på. Den går ud på at kombinere navnet på navnerummet med de målrettede pods. For eksempel:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Labels

Brugerdefinerede labels kan knyttes til Kubernetes-objekter såsom pods og navnerum. Labels (labels — etiketter) svarer til tags i skyen. Kubernetes netværkspolitikker bruger labels til at vælge pods, som de anvendes på:

podSelector:
  matchLabels:
    role: db

… eller navnerum, som de anvendes på. I dette eksempel vælges alle pods i navnerum med de tilsvarende labels:

namespaceSelector:
  matchLabels:
    project: myproject

Én advarsel: når du bruger namespaceSelector skal du sikre dig, at de valgte navnerum indeholder den ønskede label. Vær opmærksom på, at indbyggede navnerum, såsom default og kube-system, som standard ikke indeholder labels.

For at tilføje en label til et navnerum kan du gøre følgende:

kubectl label namespace default namespace=default

Her skal namespace i sektionen metadata henvise til det faktiske navn på navnerummet og ikke til labelen:

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

Kilde og modtager

Firewall-politikker består af regler med kilder og modtagere. Netværkspolitikker i Kubernetes defineres for et mål - et sæt pod'er, som de anvendes på, og etablerer derefter regler for indgående (ingress) og/eller udgående (egress) trafik. I vores eksempel vil målet for politikken være alle pod'er i navnerummet default med et label med nøgle app og værdi 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister
Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Underafsnit ingress i denne politik åbner indgående trafik til mål-pod'erne. Med andre ord fungerer ingress som kilde, og målet er den tilsvarende modtager. Tilsvarende er egress modtageren, og målet er dens kilde.

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Dette svarer til to firewall-regler: Ingress → Mål; Mål → Egress.

Egress og DNS (vigtigt!)

Når du begrænser udgående trafik, særligt vær opmærksom på DNS — Kubernetes bruger denne tjeneste til at kortlægge tjenester til IP-adresser. For eksempel vil følgende politik ikke fungere, da du ikke har tilladt applikationen balance at få adgang til 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Du kan rette det ved at åbne for adgangen til DNS-tjenesten:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Det sidste element til — er tomt, og derfor vælger det indirekte alle pod'er i alle navnerum, hvilket tillader balance at sende DNS-forespørgsler til den relevante Kubernetes-tjeneste (den kører typisk i navnerummet kube-system).

Denne tilgang fungerer, men den er alt for tilladende og usikker, da den tillader at sende DNS-forespørgsler udenfor klyngen.

Det kan forbedres i tre trin.

1. Tillad DNS-forespørgsler kun indenfor klyngen ved at tilføje 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

2. Tillad DNS-forespørgsler kun inden for navnerummet kube-system.

For dette skal du tilføje et label til navnerummet kube-system: kubectl label namespace kube-system namespace=kube-system — og angive det i politikken ved hjælp af 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

3. Paranoide kan gå endnu længere og begrænse DNS-forespørgsler til en bestemt DNS-tjeneste i kube-system. I sektionen "Filtrer efter navnerum og pods" vil det blive forklaret, hvordan dette kan gøres.

En anden mulighed er at tillade DNS på navnerumsniveau. I så fald behøver det ikke at åbnes for hver tjeneste:

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

Tom podSelector vælger alle pods i navnerummet.

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Den første overensstemmelse og rækkefølge for regler

I almindelige firewalls bestemmes handlingen ("Tillad" eller "Forbyd") for en pakke af den første regel, den opfylder. I Kubernetes har rækkefølgen af politikker ingen betydning.

Som standard, når der ikke er nogen politikker defineret, er kommunikation mellem pods tilladt, og de kan frit udveksle oplysninger. Så snart du begynder at formulere politikker, bliver hver pod, der berøres af mindst en af dem, isoleret i henhold til disjunktion (logisk ELLER) af alle politikker, der vælger den. Pods, der ikke påvirkes af nogen politik, forbliver åbne.

Denne adfærd kan ændres med et rydderegulativ.

Rydde-regulativet ("Forbyd")

Firewall-politikker forbyder normalt enhver trafik, der ikke er eksplicit tilladt.

I Kubernetes findes der ikke nogen handling "forbyd" (deny),, men en tilsvarende effekt kan opnås med en almindelig (tilladende) politik ved at vælge en tom gruppe af pod-kilder (ingress):

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Denne politik vælger alle pods i navnerummet og lader ingress være udefineret, hvilket forbyder al indgående trafik.

På samme måde kan man begrænse al udgående trafik fra navnerummet:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Bemærk, at enhver yderligere politik, der tillader trafik til pods i navnerummet, vil have prioritet over denne regel (svarende til at tilføje en tilladende regel før en forbudt i firewall-konfigurationen).

Tillad alt (Any-Any-Any-Allow)

For at oprette en "Tillad alt" politik, skal du supplere ovenstående forbudspolitik med et tomt element ingress:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Den åbner adgang fra alle pods i alle navnerum (og alle IP-adresser) til enhver pod i navnerummet default. Denne adfærd er aktiveret som standard, så normalt behøver den ikke at blive defineret yderligere. Dog kan det nogle gange være nødvendigt midlertidigt at deaktivere nogle specifikke tilladelser for at diagnosticere et problem.

Reglen kan indsnævres og tillade adgang kun til et bestemt sæt pods (app:balance) i navnerummet default:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Den følgende politik tillader al indgående (ingress) og udgående (egress) trafik, inklusive adgang til enhver IP uden for klyngen:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister
Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Kombinering af flere politikker

Politikker kombineres ved hjælp af logisk ELLER på tre niveauer; tilladelserne for hver pod er baseret på disjunktion af alle politikker, der påvirker dem:

1. I felterne fra og til kan du definere tre typer elementer (alle kombineres med ELLER):

  • namespaceSelector — vælger navnerummet som helhed;
  • podSelector — vælger pods;
  • ipBlock — vælger subnet.

Der er ingen grænse for antallet af elementer (selv de samme) i underafsnit fra/til Alle vil blive kombineret logisk ELLER.

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

2. Inden for politikafsnittet ingress kan der være mange elementer fra (kombineres med logisk ELLER). Tilsvarende kan afsnittet egress omfatte mange elementer til (også kombineres med disjunktion):

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

3. Forskellige politikker kombineres også med logisk ELLER

Men når de kombineres, er der en begrænsning, som at Chris Cooney: Kubernetes kan kun kombinere politikker med forskellige policyTypes (Ingress eller Egress). Politikker, der definerer ingress (eller egress), vil overskrive hinanden.

Forbindelse mellem navnerum

Som standard er informationsudveksling mellem navnerum tilladt. Dette kan ændres med en restriktiv politik, som begrænser udgående og/eller indgående trafik i et navnerum (se "Cleansing rule" ovenfor).

Ved at blokere adgangen til et navnerum (se "Cleansing rule" ovenfor) kan du lave undtagelser i den restriktive politik ved at tillade forbindelser fra et bestemt navnerum ved hjælp af 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Som et resultat vil alle pod’ene i navnerummet default få adgang til pod’ene postgres i navnerummet database. Men hvad nu, hvis du vil åbne adgangen til postgres kun specifikke pod’ere i navnerummet default?

Filtrering efter navnerum og pod’ere

Kubernetes version 1.11 og højere tillader kombination af operatorer namespaceSelector og podSelector ved hjælp af logisk OG. Det ser således ud:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Hvorfor tolkes dette som OG i stedet for det sædvanlige ELLER?

Bemærk venligst, at podSelector starter ikke med et bindestreg. I YAML betyder det, at podSelector og det, der står før det namespaceSelector tilhører det samme listeelement. Derfor kombineres de med logisk OG.

Tilføjelse af et bindestreg foran podSelector vil føre til oprettelsen af et nyt listeelement, der kombineres med det forrige namespaceSelector ved hjælp af en logisk ELLER.

For at vælge pods med et bestemt label i alle navnerum, indtast et tomt 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Flere labels kombineres med OG

Firewall-regler med flere objekter (hosts, netværk, grupper) kombineres ved hjælp af logisk ELLER. Den følgende regel gælder, hvis kildepakken matcher Host_1 . Host_2:

| Kilde | Destination | Tjeneste | Handling |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Tillad  |
| Host_2 |             |         |        |
| ----------------------------------------|

Omvendt i Kubernetes kombineres forskellige labels med podSelector eller namespaceSelector logisk OG. For eksempel vil den følgende regel vælge pods med begge labels, role=db Og version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

Den samme logik gælder for alle typer operatører: målpolitikkere, pod-selektorer og navnerums-selektorer.

Subnet og IP-adresser (IPBlocks)

For at segmentere netværket bruger firewalls VLAN, IP-adresser og subnets.

I Kubernetes tildeles IP-adresser automatisk til pods og kan ofte ændre sig, så labels bruges til at vælge pods og navnerum i netværkspolitikker.

Subnets (ipBlocks) bruges til at håndtere indgående (ingress) eller udgående (egress) eksterne (North-South) forbindelser. For eksempel åbner denne politik for alle pods i navnerummet default adgang til Googles DNS-tjeneste:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

En tom pod-selektor i dette eksempel betyder "vælg alle pods i navnerummet".

Denne politik åbner kun adgang til 8.8.8.8; adgang til enhver anden IP er forbudt. Dermed har du i praksis blokeret adgangen til Kubernetes interne DNS-tjeneste. Hvis du alligevel vil åbne det, skal du angive det eksplicit.

Normalt ipBlocks og podSelectors er gensidigt udelukkende, da interne IP-adresser for pods ikke bruges i ipBlocks. Ved at angive interne pod IP-adresser, vil du faktisk tillade forbindelser til/fra pod’ere med disse adresser. I praksis vil du ikke vide, hvilken IP-adresse du skal bruge, derfor skal de ikke anvendes til at vælge pod’ere.

Som et modbevis inkluderer følgende politik alle IP’er og tillader derfor adgang til alle andre pod’ere:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Adgang kan kun åbnes til eksterne IP’er, mens interne IP-adresser fra pod’erne udelukkes. For eksempel, hvis din pod’s subnet er 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Porter og protokoller

Normalt lytter pod’ere på én port. Det betyder, at man simpelthen kan undlade at angive portnumre i politikkerne og lade alt være som standard. Dog anbefales det, at politikkerne gøres så begrænsende som muligt, så i nogle tilfælde kan det være nødvendigt at angive 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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Bemærk, at selektor ports anvendes på alle elementer i blokken til eller fra, hvori den er indeholdt. For at angive forskellige porte for forskellige sætbredder, del ingress eller egress op i flere underafsnit med til eller fra og angiv de nødvendige porte for hver:

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

Introduktion til Kubernetes-netværkspolitikker for sikkerhedsspecialister

Standard portdrift:

  • Hvis du helt udelader portdefinitioner (ports), betyder det alle protokoller og alle porte;
  • Hvis du udelader protokoldefinitionen (protocol), betyder det TCP;
  • Hvis du udelader portdefinitionen (port), betyder det alle porte.

Bedste praksis: stol ikke på standardværdier, angiv det, du har brug for, eksplicit.

Bemærk, at du skal bruge pod's porte i stedet for tjenester (læs mere om dette i næste afsnit).

Er politikkerne defineret for pod's eller tjenester?

Normalt kommunikerer pod's i Kubernetes med hinanden via en service — en virtuel belastningsfordeler, der omdirigerer trafik til de pod's, der implementerer servicen. Man kunne tro, at netværkspolitikker kontrollerer adgangen til tjenester, men det er ikke tilfældet. Netværkspolitikker i Kubernetes arbejder med pod's porte og ikke tjenester.

For eksempel, hvis en service lytter på port 80, men videresender trafik til port 8080 på sine pod's, skal den netværkspolitik angive præcist 8080.

En sådan mekanisme anses for suboptimal: ved ændringer af den interne struktur af servicen (hvis portene bliver lyttet på af pod's) skal netværkspolitikkerne opdateres.

En ny arkitektonisk tilgang ved brug af Service Mesh (for eksempel se om Istio nedenfor — bem. overs.) løser dette problem.

Skal både Ingress og Egress angives?

Det korte svar er ja, for at pod A kan kommunikere med pod B, skal det tillades at oprette en udgående forbindelse (for dette skal der konfigureres en egress-politik), og pod B skal kunne modtage en indgående forbindelse (for dette kræves en ingress-politik).

Men i praksis kan man stole på standardpolitikken, som tillader forbindelser i en eller begge retninger.

Hvis en pod-kilde bliver valgt af en eller flere egress-politikker, vil de begrænsninger, der pålægges den, blive bestemt af deres disjunktion. I dette tilfælde vil det være nødvendigt at tillade forbindelse til pod-modtageren. Hvis pod'en ikke er valgt af nogen politik, er dens udgående (egress) trafik tilladt som standard.

På samme måde vil skæbnen for pod-modtageren, valgt af en eller flere ingress-politikker, blive bestemt af deres disjunktion. I dette tilfælde skal det tillades, at den kan modtage trafik fra pod-kilden. Hvis en pod ikke er valgt af nogen politik, er al indgående (ingress) trafik for den tilladt som standard.

Se punktet 'Stateful eller Stateless' nedenfor.

Logs

Netværkspolitikker i Kubernetes har ikke mulighed for at registrere trafik. Det gør det svært at afgøre, om politikken fungerer korrekt og komplicerer analysen inden for sikkerhed.

Kontrol over trafikken til eksterne tjenester

Kubernetes-netværkspolitikker tillader ikke at angive et fuldt domænenavn (DNS) i egress-sektionerne. Denne situation skaber betydelige udfordringer ved forsøg på at begrænse trafik til eksterne adresser, der ikke har en fast IP-adresse (såsom aws.com).

Politik kontrol

Firewalls vil advare dig eller endda nægte at acceptere en fejlagtig politik. Kubernetes udfører også en vis validering. Når du angiver netværkspolitikken via kubectl, kan Kubernetes erklære, at den er ugyldig og nægte at acceptere den. I andre tilfælde vil Kubernetes acceptere politikken og supplere den med manglende detaljer. Disse kan ses med følgende kommando:

kubernetes get networkpolicy  -o yaml

Vær opmærksom på, at Kubernetes' valideringssystem ikke er ufejlbarligt og kan overse nogle typer fejl.

Udførelse

Kubernetes implementerer ikke netværkspolitikker selv, men fungerer blot som en API-gateway, der pålægger kontrollen til et underliggende system kaldet Container Networking Interface (CNI). At angive politikker i et Kubernetes-kluster uden at tildele den relevante CNI svarer til at oprette politikker på en firewall-administrationsserver uden at installere dem i firewalls. Du skal selv sikre, at der er en passende CNI tilgængelig, eller i tilfælde af Kubernetes-platforme i skyen (se listen over udbydere her — red.), aktivere netværkspolitikker, der vil etablere CNI for dig.

Bemærk, at Kubernetes ikke vil advare dig, hvis du angiver en netværkspolitik uden den relevante CNI.

Stateful eller Stateless?

Alle Kubernetes CNI'er, jeg har stiftet bekendtskab med, er stateful (for eksempel bruger Calico Linux conntrack). Dette gør det muligt for en pod at modtage svar på en TCP-forbindelse, den har initieret, uden at skulle etablere den igen. Jeg kender dog ikke til nogen Kubernetes-standard, der garanterer statefulness.

Avanceret sikkerhedspolitikstyring

Her er nogle måder at øge effektiviteten af sikkerhedspolitikudførelse i Kubernetes:

  1. Arkitekturmønsteret Service Mesh bruger sidecar-containere til at levere detaljeret telemetri og trafikstyring på serviceniveau. Et eksempel kunne være Istio.
  2. Nogle af CNI-leverandørerne har forbedret deres værktøjer, så de går udover netværkspolitikkerne i Kubernetes.
  3. Tufin Orca giver gennemsigtighed og automatisering af netværkspolitikkerne i Kubernetes.

Tufin Orca-pakken administrerer netværkspolitikkerne i Kubernetes (og fungerer som kilde til de ovenfor nævnte skærmbilleder).

Yderligere oplysninger

Konklusion

Netværkspolitikkerne i Kubernetes tilbyder et godt sæt værktøjer til segmentering af klynger, men de er ikke intuitive og har mange nuancer. Jeg mener, at på grund af denne kompleksitet indeholder mange eksisterende klynger fejl. Mulige løsninger på dette problem er automatisering af politikdefinitioner eller brug af andre segmenteringsværktøjer.

Jeg håber, at denne guide vil hjælpe med at klarlægge nogle spørgsmål og løse de problemer, du måtte støde på.

P.S. fra oversætteren

Læs også på vores blog:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster