Blog

Kateri naročniki dejansko potrebujejo svoj VM? Načrt izolacije Docker po nivojih

VM za vsakega naročnika je pretiravanje. Pojasnimo, kako se odločiti, koliko izolacije vsak najemnik potrebuje—in avtomatizirati odločitev.

Povzetek

Agencije pogosto paničarjo, ko naročnik vpraša, kako resnično izolirani so njihovi podatki od drugih najemnikov. Dockerjevi imenski prostori in cgroups zagotavljajo resnično izolacijo, vendar to ni enako kot strojna meja. Namesto da bi vsakega naročnika pognali na VM—ali še huje, vse naročnike obravnavali enako—zgradite majhen nabor izolacijskih nivojev in vsakega naročnika uvrstite v enega glede na občutljivost podatkov, zaupanje in skladnost. Zaklenjen vsebnik (non-root, odvzete zmogljivosti, seccomp, samo za branje korenskega sistema) pokriva večino spletnih mest; regulirane ali sovražne obremenitve dobijo VM ali hibrid vsebnik-v-VM. Ta objava podaja ponovljiv postopek odločanja, primerjalno tabelo in iskren pogled na to, kdaj je več izolacije pretiravanje.

Ali ste na prodajnem klicu, ko novi naročnik reče „smo zdravstvo, pokažite mi, da so naši podatki izolirani od vaših drugih naročnikov" in bi raje govorili o čem drugem?

To je problem agencij: ne ena popolna namestitev, ampak ista zanesljiva namestitev, ponovljena pri ducatu naročnikov z različnimi proračuni, profili tveganja in zahtevami glede skladnosti. Tukaj je iskrena različica. Docker izolacija je resnična, vendar je specifična. Imenski prostori vsakemu vsebniku dajo svoj pogled na procese, omrežje in datotečni sistem; cgroups omejijo CPU, pomnilnik in disk I/O, tako da najemniki ne morejo drug drugega izstradati. Toda to vam ne kupi strojne stene med vsebnikom in gostiteljskim jedrom. Če napadalec pobegne iz vsebnika, je znotraj edinega jedra, ki ga imate. Preostanek tega članka to neprijetno dejstvo spremeni v ponovljivo odločitev: razvrstite vsakega naročnika glede na občutljivost podatkov in zaupanje, uporabite osnovni profil utrjevanja in se za VM odločite le, ko so stroški vdora višji od stroškov VM.

Počakaj, ali vsebniki niso že izolirani?

Docker deluje na Linux imenskih prostorih in cgroups, in te besede opravljajo pravo delo. Imenski prostori ločujejo ID-je procesov, omrežne sklade, priklopne točke in uporabnike, tako da proces v enem vsebniku ne more videti procesne tabele drugega. Cgroups postavijo omejitve: dajte vsebniku 0,5 CPU, 512 MB pomnilnika in fiksno težo blokovnega I/O, in točno to dobi. Ubežna zanka pri enem najemniku se omeji, namesto da bi podrla soseda. Če niste konfigurirali omejitev, ste preskočili najosnovnejšo stvar, za katero so cgroups namenjeni.

Vzemite preprosto PHP aplikacijo v vsebniku A. Ta vidi svoj datotečni sistem, svoj omrežni vmesnik, svoj PID 1. Vsebnik B ima enako, vendar drugačen pogled. To so imenski prostori. Zdaj se oddaljite in preskočite omejitev pomnilnika: vsebnik A lahko napolni RAM gostitelja in povzroči, da vsebnik B leze. To je tisto, kar cgroups preprečujejo. Toda dva vsebnika sta lahko izolirana drug od drugega z imenskimi prostori in si še vedno delita jedro gostitelja, kar je del, o katerem govori vsaka zgodba o pobegu iz vsebnika. Izkoriščanje, ki doseže jedro, lahko potencialno doseže vsakega najemnika na tem gostitelju.

„Docker je izoliran" je polresničen stavek. Natančna različica je „Docker izolira z imenskimi prostori in cgroups, ranljivost jedra pa je eksplozijski radij." Preden zaupate najemniku, da bo izvajal nezaupanja vredno kodo, pomislite na to za minuto. Odgovor ni „nikoli ne uporabljajte vsebnikov"—to je enostavna panika. Odgovor je sistem nivojev.

Zakaj nekateri naročniki potrebujejo več kot imenske prostore?

Iskren odgovor je, da izolacija ni stikalo, ampak spekter. Na enem koncu imate popolnoma deljen vsebnik, kjer so vsi dejansko v eni aplikaciji. Na drugem koncu imate ločen VM za vsakega najemnika z lastnim jedrom. Večina agencijskega dela živi v neudobni sredini in sredina ni binarna izbira med „Docker je v redu" in „pognati VM za vsakogar."

Kar potisne naročnika v desno, ni njihova velikost. To so štiri vprašanja:

  • Ali hranijo regulirane podatke? Zdravstvene kartoteke, podatki o plačilnih karticah, karkoli, kar bi regulator označil za občutljivo.
  • Ali ima vdor v njihov najemniški prostor realno pot do drugega najemnika? Če lahko izvajajo poljubno kodo, ja.
  • Ali zaupate kodi in ljudem, ki jo nameščajo? Naročnik, ki najame najcenejšega freelancerja, ni enaka raven zaupanja kot naročnik, čigar razvojno ekipo poznate.
  • Ali njihova pogodba pravi „namensko," „izolirano" ali „zasebno"? Če ja, ste že obljubili nivo; zdaj je edina naloga izbrati pravega.

Če na ta vprašanja še ne morete odgovoriti, dajte naročnika v osnovni nivo in zapišite predpostavke. To ni varnostni pregled; je preverjanje razuma, ki ga ponovite ob vsakem uvajanju.

Kako se odločim za vsakega naročnika, ne da bi vsakič izvedel varnostni pregled?

Naredite majhno tabelo in se je držite. Ne potrebujete matrike s štiridesetimi celicami. Štirje nivoji pokrijejo skoraj vsakega naročnika, ki ga agencija vidi.

Položaj naročnikaKaj jih dejansko ločujeUporabi, ko
Nivo 1: Deljena aplikacija/vsebnikSamo aplikacijska logikaInterne pripomočke, podatki z nizkim tveganjem, projekti, kjer so vsi izrecno v enem prijavnem sistemu
Nivo 2: Isti gostitelj, ločeni vsebnikiImenski prostori in cgroupsVečina marketinških spletnih mest, kontaktni obrazci, brez občutljivih podatkov
Nivo 3: Zaklenjen vsebnikNivo 2 + non-root, odvzete zmogljivosti, seccomp, samo za branje korenskega sistema, omrežna segmentacijaE-trgovina, PII, po meri napisana koda, ki ji ne zaupate popolnoma
Nivo 4: VM na najemnikaHipervizor in ločeno jedroZdravstvo, finance, dokumentacija skladnosti, nezaupanja vredna koda, hrupni sosedje

Takole se to odvija v praksi. Naročnik pekarne s kontaktnim obrazcem in Instagram povezavo gre v Nivo 2: en vsebnik na deljenem gostitelju, privzeto Docker omrežje, omejitve virov, delo opravljeno. Spletna trgovina, ki shranjuje imena strank, naslove in preusmeritve plačil, gre v Nivo 3: isti deljeni gostitelj, vendar vsebnik teče kot non-root uporabnik, nima dodatnih zmogljivosti jedra, uporablja seccomp profil in izpostavlja samo vrata 443. Medicinski portal za sprejem bolnikov, ki shranjuje zaščitene zdravstvene podatke, gre v Nivo 4: VM na najemnika, ker strošek vdora ni „bomo to počistili", ampak „naročniku ne moremo pokazati, da smo ga vzeli resno."

Celoten trik je v tem, da ne razmišljate znova o arhitekturi za vsakega naročnika. Izberete vrstico iz tabele, o kateri ste se že dogovorili. Tako lahko petčlanska agencija poganja sto spletnih mest brez sto ločenih obsedenosti z varnostjo. To tudi pomeni, da naslednji naročnik ne dobi odgovora, ki je odvisen od tega, kateri član ekipe je odgovoril na telefon. Za globljo arhitekturno razpravo o teh odločitvah ta vodnik o oblikovanju ravni izolacije za več najemnikov podrobneje pokriva kompromise.

Kako dejansko izgleda zaklenjen vsebnik?

Nehajmo govoriti „zaklenjen" in postanimo konkretni. To pomeni Nivo 3 za tipičnega WordPress ali PHP naročnika.

Najprej spremenite uporabnika. Večina uradnih slik privzeto še vedno teče kot root; v svoji Dockerfile datoteki ustvarite non-root uporabnika in zaženite aplikacijo kot ta uporabnik. To takoj odstrani najpogostejši način, kako kompromitacija vsebnika postane kompromitacija gostitelja. Drugič, odvrzite zmogljivosti, ki jih ne potrebujete. Zaženite z --cap-drop ALL in dodajte nazaj samo eno, običajno NET_BIND_SERVICE, da lahko aplikacija posluša na vratih 80. Že to je večja sprememba, kot jo večina ljudi pričakuje. Tretjič, naredite korenski datotečni sistem samo za branje z --read-only in pripnite zapisljive imenike (prenose, podatkovni imenik baze) kot nosilce ali tmpfs. Četrtič, uporabite seccomp profil in, če vaš gostitelj to podpira, AppArmor ali SELinux. Nazadnje dajte vsebnik na namensko Docker omrežje in izpostavite samo tista vrata, ki morajo biti dejansko dosegljiva.

Poglejmo primer WordPress. Osnovna slika verjetno teče kot root, zato dodate korak useradd in direktivo USER. Zaženite vsebnik z omejitvijo pomnilnika in CPU, tako da izbruh prometa vtičnikov ne škoduje sosedu. Pripnete /var/www/html/wp-content/uploads kot zapisljiv nosilec. Nastavite --read-only. Pripnete ga na omrežje, ki nima zastavice --privileged nikjer v bližini. Rezultat je vsebnik, ki je bil nekoč „spletno mesto WordPress" in je zdaj „spletno mesto WordPress, ki je bolj zaklenjeno kot večina virtualnih zasebnih strežnikov."

Če se vam ročno ustvarjanje vsega tega zdi krhko, obstaja lažja srednja pot: Dockerjevo naprednejše vsebniška izolacija (Enhanced Container Isolation), ki uporablja izolacijo uporabniških imenskih prostorov in varen vsebniški runtime. To je legitimna bližnjica, vendar to ni prost prehod, da preskočite non-root ali odvzem zmogljivosti. Najemnik še vedno potrebuje smiselno sliko. Razlika je v tem, da se napadalna površina, obrnjena proti jedru, zmanjša, ne da bi čez noč postali seccomp strokovnjak. Če želite točno zaporedje za enega najemnika, vodnik za utrjevanje izolacije po korakih spremeni ta razdelek v ukaze kopiraj-prilepi.

Kdaj preneham dodajati plasti in jim preprosto dam VM?

Tukaj je kontradiktorni del: več izolacije ni samodejno bolje. VM-ji zagotavljajo izolacijo na ravni strojne opreme, ločeno jedro in veliko manjšo napadalno površino, če pade gostujoče jedro. Točno to zdravstveni in finančni naročniki pričakujejo, ko rečejo „želimo biti izolirani." Toda vsak VM doda stroške popravkov, varnostnih kopij in računske moči ter pomnoži delo vzdrževanja flote. Če naredite VM za vsakega naročnika, ker vam je en naročnik nekoč rekel, da ga Docker straši, ste kupili varnostno gledališče z pravim denarjem.

VM je pravi odgovor, ko je tveganje na najemnika višje od operativnih stroškov VM na najemnika. To pomeni regulirane podatke, pisne zahteve glede skladnosti, nezaupanja vredno kodo tretjih oseb ali naročnika, ki potrebuje odstranjenega hrupnega soseda. Prav tako je pravi odgovor, ko naročnikova pogodba dobesedno obljublja namensko okolje, ker „vsebnik" ni tisto, kar si predstavljajo, ko podpišejo „namensko."

Toda VM ne opravičuje površnega vsebnika. Pogosta past je, da naročnika daste v VM in nato preskočite utrjevanje, ker „jih VM varuje." VM varuje gostitelja pred najemnikom, ne pa najemnika pred njegovo lastno slabo sliko. Še vedno želite non-root, odvzete zmogljivosti in seccomp znotraj tega VM. Hibridni pristop—vsebniki znotraj VM—je pogosto najboljša točka: VM zagotavlja mejo za pogovore o skladnosti, vsebnik pa vam daje način uvajanja, ki ga že poznate. Daljša različica te razprave je v Ali bi moral vsak najemnik dobiti svoj VM?, vendar je kratek odgovor ta, da je VM za pogodbo, ne za strah.

Kako to naredim ponovljivo pri vsakem naročniku?

To naredite ponovljivo tako, da nivojski sistem postane predloga, ne spomin. Hranite imenik datotek Compose, enega za vsak nivo: tier2-baseline, tier3-locked, tier4-vm-hybrid. Ko se pojavi nov naročnik, kopirajte predlogo, spremenite okoljske spremenljivke in že veste obliko izolacije, preden napišete vrstico nove infrastrukture.

Nato zapišite odločitev. Ne 400-stransko varnostno poročilo, ampak kratek odstavek v naročnikovem repozitoriju: katere podatke hranijo, na katerem nivoju so, zakaj in kaj bi jih premaknilo na višji nivo. Ta odstavek je vreden več kot sto požarnih pravil, ker je to stvar, ki jo lahko pokažete naslednjemu revizorju ali naslednjemu prestrašenemu naročniku. Prav tako vam preprečuje, da bi se morali spomniti, zakaj je pekarna dobila Nivo 2 in e-trgovina Nivo 3, ko je prvotni prodajni klic že zbledel.

Avtomatizirajte dolgočasne preglede. Vaš CI naj pregleda vsako naročniško sliko in zavrne gradnjo, če teče kot root, če ima vse zmogljivosti ali če poskuša objaviti vrata, ki niso tista, ki jih nivo dovoljuje. Nič od tega ni eksotično; gre samo za to, da predloga ni pomotoma zlomil dobrohotni razvijalec. Če že gradite okoliški gostiteljski potek dela, članek o produkcijsko pripravljenih strategijah gostovanja Docker pokriva del, ki pride po definiranih vsebnikih.

Nič od tega ni glamurozno. Nobena objava na blogu ne bo naredila „izolacije najemnikov" tako vznemirljive kot diagram arhitekture za projekt iz nič. Toda to je razlika med agencijo, ki na vprašanje „kako izolirani smo?" odgovori s prekrižanimi prsti „popolnoma", in tisto, ki lahko pokaže nivo, konfiguracijo in razlog. Vsebniki niso čarobna stena. VM-ji niso čarobna krogla. Nivojski sistem je samo odločitev, ki jo zapišete in ponovno uporabite—in za agencijo je ponovljivost celotna igra.

Sources (5)