ProHoster > Blog > administration > En introduktion til Kubernetes netværkspolitikker for sikkerhedsprofessionelle
En introduktion til Kubernetes netværkspolitikker for sikkerhedsprofessionelle
Bemærk. overs.: Forfatteren af artiklen - Reuven Harrison - har over 20 års erfaring med softwareudvikling, og er i dag CTO og medstifter af Tufin, en virksomhed med løsninger til styring af sikkerhedspolitik. Selvom han anser Kubernetes netværkspolitikker for at være kraftfulde nok til at segmentere netværket i en klynge, mener han også, at de ikke er så nemme at implementere i praksis. Dette materiale (temmelig omfangsrigt) er beregnet til at forbedre specialisternes bevidsthed i denne sag 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 styresystem til datacentre." Efterhånden begynder Kubernetes (eller k8s) at blive opfattet som en kritisk del af virksomheden, der kræver organisering af modne forretningsprocesser, herunder netværkssikkerhed.
For sikkerhedsprofessionelle, der har været forvirrede over at arbejde med Kubernetes, kan standardpolitikken for denne platform være en reel opdagelse: tillad alt.
Denne guide vil hjælpe dig med at forstå netværkspolitikkernes indre funktion; forstå, hvordan de adskiller sig fra reglerne for almindelige firewalls. Den vil også tale om nogle af faldgruberne og give anbefalinger, der vil hjælpe med at beskytte applikationer i Kubernetes.
Kubernetes netværkspolitikker
Kubernetes-netværkspolitikmekanismen giver dig mulighed for at styre interaktionen mellem applikationer, der er implementeret på platformen på netværkslaget (det tredje i OSI-modellen). Netværkspolitikker mangler nogle af de avancerede funktioner i moderne firewalls, såsom OSI lag 7-kontrol og trusselsdetektion, men de giver et grundlæggende lag af netværkssikkerhed, der er et godt udgangspunkt.
Netværkspolitikker styrer kommunikation mellem pods
Arbejdsbelastninger i Kubernetes er fordelt på tværs af pods, som består af en eller flere containere, der er installeret sammen. Kubernetes tildeler hver pod en IP-adresse, der er tilgængelig fra andre pods. Kubernetes-netværkspolitikker angiver adgangstilladelser for grupper af pods på samme måde, som sikkerhedsgrupper i skyen bruges til at kontrollere adgangen til virtuelle maskiner.
Definition af netværkspolitikker
Ligesom andre Kubernetes-ressourcer er netværkspolitikker angivet i YAML. I eksemplet nedenfor er applikationen balance åbner adgang til postgres:
(Bemærk. overs.: dette skærmbillede, ligesom alle efterfølgende lignende skærmbilleder, blev ikke oprettet ved hjælp af native Kubernetes-værktøjer, men ved hjælp af Tufin Orca-værktøjet, som blev udviklet af firmaet til forfatteren af den originale artikel, og som er nævnt i slutningen af materialet.)
Grundlæggende viden om YAML er nødvendig for at definere din egen netværkspolitik. Dette sprog er baseret på indrykning (specificeret med mellemrum, ikke tabulatorer). Det indrykkede element hører til det nærmeste indrykkede element over det. Det nye element på listen starter med en bindestreg, alle andre elementer er af formen nøgleværdi.
Efter at have beskrevet politikken i YAML, brug kubectlfor at oprette det i klyngen:
kubectl create -f policy.yaml
Netværkspolitikspecifikation
Kubernetes netværkspolitikspecifikation omfatter fire elementer:
podSelector: definerer de pods, der er berørt af denne politik (mål) - påkrævet;
policyTypes: angiver, hvilke typer politikker der er inkluderet i denne: indgang og/eller udgang - valgfri, men jeg anbefaler, at du udtrykkeligt specificerer det i alle tilfælde;
ingress: definerer tilladt indgående trafik til målpods - valgfrit;
egress: definerer tilladt udgående trafik fra target pods er valgfrit.
Et eksempel lånt fra Kubernetes-webstedet (jeg erstattede role på app), viser, hvordan alle fire elementer bruges:
Bemærk, at det ikke er nødvendigt at inkludere alle fire elementer. Det er kun påkrævet podSelector, kan resten af parametrene bruges efter ønske.
Hvis du undlader policyTypes, vil politikken blive fortolket som følger:
Det antages som standard at definere indgangssiden. Hvis politikken ikke udtrykkeligt angiver dette, vil systemet antage, at al trafik er forbudt.
Opførslen på udgangssiden vil blive bestemt af tilstedeværelsen eller fraværet af den tilsvarende udgangsparameter.
For at undgå fejl, anbefaler jeg altid være eksplicit policyTypes.
Ifølge logikken ovenfor, i tilfælde af parametrene ingress og / eller egress udeladt, vil politikken afvise al trafik (se "Sweep Rule" nedenfor).
Standardpolitik - tillad
Hvis der ikke er defineret nogen politikker, tillader Kubernetes al trafik som standard. Alle pods kan frit udveksle information med hinanden. Fra et sikkerhedssynspunkt kan dette virke kontraintuitivt, men husk at Kubernetes oprindeligt blev skabt af udviklere med det formål at gøre applikationer interoperable. Netværkspolitikker blev tilføjet senere.
Navneområder
Navneområder er Kubernetes-samarbejdsmekanismen. De er designet til at isolere logiske miljøer fra hinanden, mens de som standard tillader kommunikation mellem rum.
Som de fleste Kubernetes-komponenter lever netværkspolitikker i et specifikt navneområde. I blokken metadata du kan angive, hvilket rum politikken tilhører:
Hvis navneområdet ikke er eksplicit angivet i metadataene, vil systemet bruge det navneområde, der er angivet i kubectl (standard namespace=default):
kubectl apply -n my-namespace -f namespace.yaml
jeg anbefaler angiv navneområde eksplicit, medmindre du skriver en politik, der er målrettet mod flere navneområder på én gang.
Primær element podSelector i politikken vil vælge pods fra det navneområde, som politikken tilhører (den har ikke adgang til pods fra et andet navneområde).
Tilsvarende podSelectors i ind- og udgangsblokke kan kun vælge pods fra deres eget navneområde, medmindre du selvfølgelig kombinerer dem med namespaceSelector (Dette vil blive diskuteret i afsnittet "Filtrer efter navnerum og pods").
Regler for navngivning af politik
Politiknavne er unikke inden for det samme navneområde. Der kan ikke være to politikker med samme navn i samme rum, men der kan være politikker med samme navn i forskellige rum. Dette er nyttigt, når du vil genanvende den samme politik på tværs af flere områder.
Jeg kan især godt lide en af navngivningsmetoderne. Det består af at sammenkæde navnerummets navn med målpods. For eksempel:
Brugerdefinerede etiketter kan knyttes til Kubernetes-objekter såsom pods og navnerum. Etiketter (etiketter tags) svarer til tags i skyen. Kubernetes netværkspolitikker bruger etiketter til at vælge bælgsom de gælder for:
podSelector:
matchLabels:
role: db
… eller navnerumsom de gælder for. Dette eksempel vælger alle pods i navneområder med matchende etiketter:
En advarsel: ved brug namespaceSelectorsørg for, at de navneområder, du vælger, indeholder den korrekte etiket. Vær opmærksom på, at indbyggede navnerum som f.eks default и kube-system, indeholder ikke etiketter som standard.
Du kan tilføje en etiket til et mellemrum som dette:
kubectl label namespace default namespace=default
I dette tilfælde navnerummet i sektionen metadata skal referere til det faktiske navn på rummet, ikke etiketten:
Firewall-politikker består af kilde- og destinationsregler. Kubernetes netværkspolitikker defineres pr. mål, det sæt af pods, de gælder for, og sætter derefter regler for indgående og/eller udgående trafik. I vores eksempel vil politikmålet være alle pods i navneområdet default med nøglelabel app og mening db:
Underafsnit ingress i denne politik åbner indgående trafik til målpods. Med andre ord er indgangen kilden, og målet er den tilsvarende destination. Tilsvarende er udgang destinationen, og målet er dets kilde.
Dette svarer til to firewall-regler: Ingress → Target; Mål → Udgang.
Egress og DNS (vigtigt!)
Begrænsning af udgående trafik være særlig opmærksom på DNS - Kubernetes bruger denne service til at kortlægge tjenester til IP-adresser. For eksempel vil følgende politik ikke fungere, fordi du ikke har tilladt applikationen balance få adgang til DNS:
Sidste element to er tom, og så vælger den indirekte alle pods i alle navneområder, tillader balance send DNS-forespørgsler til den relevante Kubernetes-tjeneste (normalt kører den i rummet kube-system).
Denne tilgang virker dog alt for eftergivende og usikker, fordi det giver dig mulighed for at dirigere DNS-forespørgsler uden for klyngen.
Du kan forbedre det i tre på hinanden følgende trin.
1. Tillad kun DNS-forespørgsler inden klynge ved at tilføje namespaceSelector:
2. Tillad kun DNS-forespørgsler i navneområdet kube-system.
For at gøre dette skal du tilføje en etiket til navneområdet kube-system: kubectl label namespace kube-system namespace=kube-system - og registrere det i politikken vha namespaceSelector:
3. Paranoider kan gå endnu længere og begrænse DNS-anmodninger til en specifik DNS-tjeneste i kube-system. Afsnittet "Filtrer efter navnerum OG Pods" viser dig, hvordan du opnår dette.
En anden mulighed er at løse DNS på navnerumsniveau. I dette tilfælde behøver det ikke at blive åbnet for hver tjeneste:
I konventionelle firewalls bestemmes handlingen (Allow or Deny) på en pakke af den første regel, den opfylder. I Kubernetes er rækkefølgen af politikker ligegyldig.
Som standard, når der ikke er angivet nogen politikker, er kommunikation mellem pods tilladt, og de kan frit udveksle oplysninger. Så snart du begynder at formulere politikker, bliver hver pod, der er påvirket af mindst én af dem, isoleret i henhold til adskillelsen (logisk ELLER) af alle de politikker, der har valgt den. Pods, der ikke er påvirket af nogen politik, forbliver åbne.
Du kan ændre denne adfærd med en sweep-regel.
Oprydningsregel ("Forbyd")
Firewallpolitikker afviser normalt enhver trafik, der ikke udtrykkeligt er tilladt.
Kubernetes har ikke en "afvis"-handling, men den samme effekt kan opnås med en normal (tilladende) politik ved at vælge en tom gruppe af kildepods (indgang):
Bemærk venligst eventuelle yderligere politikker, der tillader trafik til pods i navneområdet, har forrang over denne regel (svarende til at tilføje en tillad-regel før en afvisningsregel i firewall-konfigurationen).
Tillad alle (Any-Any-Any-Allow)
For at oprette en "Tillad alle"-politik skal du supplere ovenstående afvisningspolitik med et tomt element ingress:
Det giver adgang til alle pods i alle navneområder (og alle IP'er) til enhver pod i navneområdet default. Denne adfærd er aktiveret som standard, så den behøver normalt ikke at blive defineret yderligere. Nogle gange kan det dog være nødvendigt midlertidigt at deaktivere visse specifikke tilladelser for at diagnosticere problemet.
Reglen kan indsnævres til kun at tillade adgang til et bestemt sæt bælg (app:balance) i navnerummet default:
2. Inside politik afsnit ingress kan have mange elementer from (kombineret med logisk ELLER). Tilsvarende afsnit egress kan indeholde mange elementer to (også kombineret med disjunktion):
3. Forskellige politikker kombineres også med en logisk OR
Men når de kombineres, er der én begrænsning for hvilken påpegedeChris Cooney: Kubernetes kan kun kombinere politikker med forskellige policyTypes (Ingress eller Egress). Politikker, der definerer indgang (eller udgang), vil overskrive hinanden.
Relation mellem navnerum
Som standard er udveksling af information mellem navneområder tilladt. Dette kan ændres med en restriktiv politik, der begrænser udgående og/eller indgående trafik til navneområdet (se "Sweep-regel" ovenfor).
Ved at blokere adgangen til et navneområde (se "Sweep Rule" ovenfor), kan du gøre undtagelser fra afvisningspolitikken ved at tillade forbindelser fra et specifikt navneområde med namespaceSelector:
Som et resultat, alle pods i navneområdet default få adgang til pods postgres i navnerummet database. Men hvad nu hvis du vil åbne adgang til postgres kun specifikke pods i navnerummet default?
Filtrer efter navnerum OG pods
Kubernetes version 1.11 og nyere giver dig mulighed for at kombinere operatører namespaceSelector и podSelector bruger logisk OG. Det ser sådan ud:
Hvorfor tolkes det som OG i stedet for det sædvanlige ELLER?
Bemærk, at podSelector starter ikke med en bindestreg. I YAML betyder det det podSelector og står foran ham namespaceSelector henvise til det samme listeelement. Derfor er de kombineret med et logisk OG.
Tilføjelse af en tankestreg før podSelector vil resultere i et nyt listeelement, der vil blive kombineret med det forrige namespaceSelector ved hjælp af logisk ELLER.
For at vælge pods med en bestemt etiket i alle navneområder, indtast tom namespaceSelector:
Firewall-regler med flere enheder (værter, netværk, grupper) kombineres ved hjælp af en logisk OR. Følgende regel udløses, hvis pakkekilden matcher Host_1 OR Host_2:
Tværtimod, i Kubernetes forskellige etiketter i podSelector eller namespaceSelector kombineres med et logisk OG. For eksempel vil følgende regel vælge pods, der har begge etiketter, role=db И version=v2:
podSelector:
matchLabels:
role: db
version: v2
Den samme logik gælder for alle typer udsagn: politikmålvælgere, podvælgere og navneområdevælgere.
Undernet og IP-adresser (IPBlocks)
Firewalls bruger VLAN'er, IP-adresser og undernet til at segmentere et netværk.
I Kubernetes tildeles IP-adresser automatisk til pods og kan ændres ofte, så etiketter bruges til at vælge pods og navneområder i netværkspolitikker.
Undernet (ipBlocks) bruges til håndtering af indgående (indgående) eller udgående (udgående) eksterne (nord-syd) forbindelser. For eksempel åbner denne politik alle pods fra navneområdet default adgang til Google DNS-tjeneste:
Den tomme pod-vælger i dette eksempel betyder "vælg alle pods i navneområdet".
Denne politik tillader kun adgang til 8.8.8.8; adgang til enhver anden IP er forbudt. Så i det væsentlige har du blokeret adgangen til den interne Kubernetes DNS-tjeneste. Hvis du stadig vil åbne det, skal du angive det eksplicit.
Normalt ipBlocks и podSelectors udelukker hinanden, da de interne IP-adresser på pod'erne ikke bruges i ipBlocks. Påpege interne IP-pods, vil du faktisk tillade forbindelser til/fra pods med disse adresser. I praksis vil du ikke vide, hvilken IP-adresse du skal bruge, hvorfor du ikke bør bruge dem til at vælge pods.
Som et modeksempel inkluderer følgende politik alle IP'er og giver derfor adgang til alle andre pods:
Normalt lytter pods på én port. Det betyder, at du blot kan udelade portnumrene i dine politikker og lade alt stå som standard. Det anbefales dog at gøre politikker så restriktive som muligt, så i nogle tilfælde kan du stadig angive porte:
Bemærk, at vælgeren ports gælder for alle elementer i blokken to eller from, som indeholder. For at angive forskellige porte for forskellige varesæt, skal du bryde ingress eller egress i flere underafsnit to eller from og i hver skriv dine porte ned:
Hvis du helt udelader definitionen af porte (ports), hvilket betyder alle protokoller og alle porte;
Hvis du udelader protokoldefinitionen (protocol), hvilket betyder TCP;
Hvis du udelader portdefinitionen (port), hvilket betyder alle porte.
Bedste praksis: Stol ikke på standardværdier, angiv eksplicit, hvad du har brug for.
Bemærk, at du skal bruge pod-porte, ikke tjenester (mere om dette i næste afsnit).
Politikker defineret for pods eller tjenester?
Normalt kommunikerer pods i Kubernetes med hinanden gennem en tjeneste – en virtuel load balancer, der omdirigerer trafik til de pods, der implementerer tjenesten. Du tror måske, at netværkspolitikker styrer adgangen til tjenester, men det er ikke tilfældet. Kubernetes netværkspolitikker fungerer med pod-porte, ikke tjenester.
For eksempel, hvis en tjeneste lytter på port 80, men omdirigerer trafik til port 8080 af dens pods, skal du angive 8080 i netværkspolitikken.
En sådan mekanisme bør anerkendes som suboptimal: Hvis tjenestens interne enhed (hvis portene lytter til pods) ændres, skal netværkspolitikker opdateres.
Ny arkitektonisk tilgang ved hjælp af Service Mesh (se f.eks. om Istio nedenfor - ca. oversættelse) giver dig mulighed for at håndtere dette problem.
Er det nødvendigt at skrive både Ingress og Egress?
Det korte svar er ja, for at pod A kan kommunikere med pod B, skal du give den mulighed for at oprette en udgående forbindelse (for dette skal du konfigurere udgående politik), og pod B skal kunne acceptere en indgående forbindelse (til dette har du derfor brug for indgangspolitik).
I praksis kan du dog stole på, at standardpolitikken tillader forbindelser i en eller begge retninger.
Hvis nogle pod-kilde vil blive valgt af en eller flere egress-politikere, de begrænsninger, der pålægges det, vil blive bestemt af deres disjunktion. I dette tilfælde skal du udtrykkeligt tillade forbindelsen til podenadressat. Hvis en pod ikke er valgt af nogen politik, er dens udgående (udgående) trafik tilladt som standard.
På samme måde, skæbnen for pod'a-adressatvalgt af en eller flere indtrængen-politikker vil blive bestemt af deres adskillelse. I dette tilfælde skal du udtrykkeligt tillade, at den modtager trafik fra kildepoden. Hvis en pod ikke er valgt af nogen politik, er al indgående trafik til den som standard tilladt.
Se "Statsfuld eller statsløs" nedenfor.
Logs
Kubernetes netværkspolitikker ved ikke, hvordan man logger trafik. Dette gør det svært at afgøre, om en politik fungerer som forventet, og gør sikkerhedsanalyse meget vanskelig.
Trafikkontrol til eksterne tjenester
Kubernetes netværkspolitikker tillader ikke, at du angiver et fuldt kvalificeret domænenavn (DNS) i udgående sektioner. Denne kendsgerning fører til en betydelig ulempe, når man forsøger at begrænse trafik til eksterne destinationer, der ikke har en fast IP-adresse (såsom aws.com).
Politikcheck
Firewalls vil advare dig eller endda nægte at acceptere en fejlagtig politik. Kubernetes udfører også en vis kontrol. Når du sætter en netværkspolitik via kubectl, kan Kubernetes erklære, at politikken er forkert og nægte at acceptere den. I andre tilfælde vil Kubernetes tage politikken og udfylde den med de manglende detaljer. Du kan se dem med kommandoen:
kubernetes get networkpolicy <policy-name> -o yaml
Husk, at Kubernetes-valideringssystemet ikke er ufejlbarligt og kan gå glip af nogle typer fejl.
Udførelse
Kubernetes håndhæver ikke netværkspolitikker alene, men er blot en API-gateway, der placerer kontrolbyrden på et underliggende system kaldet Container Networking Interface (CNI). At indstille politikker på en Kubernetes-klynge uden at tildele en passende CNI svarer til at indstille politikker på en firewall-administrationsserver uden efterfølgende at indstille dem på firewalls. Det er op til dig at sikre dig, at du har en anstændig CNI eller, i tilfælde af Kubernetes-platforme, hostet i skyen (Se en liste over udbydere her - ca. oversættelse), aktiver netværkspolitikker, der indstiller CNI for dig.
Bemærk, at Kubernetes ikke vil advare dig, hvis du indstiller en netværkspolitik uden den relevante hjælpe-CNI.
Statsfuld eller statsløs?
Alle Kubernetes CNI'er, jeg er stødt på, er stateful (f.eks. bruger Calico Linux conntrack). Dette gør det muligt for poden at modtage svar på den TCP-forbindelse, den startede, uden at skulle genetablere den. Jeg er dog ikke bekendt med en Kubernetes-standard, der ville garantere statefulness.
Avanceret sikkerhedspolitikstyring
Her er nogle måder at forbedre effektiviteten af håndhævelsen af sikkerhedspolitik i Kubernetes:
Service Mesh arkitektoniske mønster bruger sidevogne til at levere detaljeret telemetri og trafikkontrol på serviceniveau. Som eksempel kan man tage Samme.
Nogle af CNI-leverandørerne har udvidet deres værktøjer til at gå ud over Kubernetes netværkspolitikker.
Tufin spækhugger giver gennemsigtighed og automatisering af Kubernetes netværkspolitikker.
Tufin Orca-pakken administrerer Kubernetes netværkspolitikker (og er kilden til skærmbillederne ovenfor).
Kubernetes netværkspolitikker tilbyder et godt sæt værktøjer til at segmentere klynger, men de er ikke intuitive og har mange finesser. Jeg mener, at på grund af denne kompleksitet er politikkerne for mange eksisterende klynger uklare. Mulige løsninger på dette problem er at automatisere politikdefinitioner eller bruge andre segmenteringsværktøjer.
Jeg håber, at denne vejledning vil hjælpe med at afklare nogle spørgsmål og løse problemer, du måtte støde på.