Adăugați anteturi de securitate cu Lambda@Edge și Terraform în AWS S3/CloudFront
Publicat: 2021-04-24Când vă conectați la https://app.sendgrid.com pentru a verifica detaliile contului sau vizitați https://mc.sendgrid.com pentru campanii de marketing, vizitați aplicațiile noastre web front-end găzduite în compartimentele AWS S3 cu Distribuții CloudFront peste ele.
Aplicațiile noastre web constau în esență în fișiere JavaScript și CSS, fișiere HTML și fișiere imagine, încărcate în compartimentele S3, sub formă de cache CloudFront și le furnizează utilizatorilor noștri. Fiecare dintre mediile aplicației noastre web, de la testare, punere în scenă și producție, are un compartiment S3 separat și o distribuție CloudFront.
Această infrastructură AWS S3 și CloudFront funcționează bine pentru aplicațiile noastre web la scară în găzduirea fișierelor într-o rețea de livrare de conținut, dar configurațiile noastre inițiale nu aveau protecții mai stricte sub formă de anteturi de securitate.
Adăugarea acestor anteturi de securitate ar împiedica utilizatorii de la atacuri, cum ar fi scripturi între site-uri, sniffing MIME, clickjacking, injectare de cod și atacuri man-in-the-middle legate de protocoalele nesigure. Dacă sunt lăsate nesupravegheate, acestea ar avea consecințe grave pentru datele clienților noștri și pentru încrederea companiei noastre în a putea oferi o experiență sigură pe web.
Înainte de a cerceta cum să adăugam aceste anteturi, am făcut mai întâi un pas înapoi pentru a vedea unde ne aflăm. După ce am rulat adresa URL a aplicației noastre web printr-un site web de scanare a antetelor de securitate , în mod surprinzător, am primit o notă nereușită, dar am văzut o listă utilă de anteturi pe care trebuie să le examinăm, așa cum se arată mai jos.
După cum puteți vedea, era mult loc de îmbunătățire. Am cercetat cum să configuram resursele noastre AWS S3 și CloudFront pentru a răspunde cu anteturi de securitate pentru a atenua riscurile și vulnerabilitățile menționate.
La un nivel înalt, putem realiza acest lucru prin crearea unei funcții Lambda@Edge care modifică anteturile de răspuns de origine pentru a adăuga anteturile de securitate dorite înainte ca fișierele aplicației web să revină în browserul utilizatorului.
Strategia este să testați mai întâi conectarea manuală a lucrurilor prin Consola AWS. Apoi, vom pune aceste configurații în Terraform pentru a salva această parte a infrastructurii în cod pentru referințe viitoare și partajare cu alte echipe și aplicații.
Ce fel de anteturi de securitate am dori să adăugăm?
Ca parte a recomandărilor echipei noastre de securitate a produselor, am fost însărcinați să adăugăm anteturi de securitate precum „Strict-Transport-Security” și „X-Frame-Options”. Vă recomandăm să consultați și resurse precum MDN Web Security Cheatsheet pentru a fi la curent. Iată un scurt rezumat al anteturilor de securitate pe care le puteți aplica aplicațiilor dvs. web.
Strict-Transport-Security (HSTS)
Acest lucru este pentru a oferi browserului indicii pentru a vă accesa aplicația web prin HTTPS, mai degrabă decât prin HTTP.
Politica de securitate a conținutului (CSP)
Aceasta este pentru a seta liste de permisiuni explicite cu privire la ce fel de resurse încărcați sau la care vă conectați în aplicația dvs. web, cum ar fi scripturi, imagini, stiluri, fonturi, solicitări de rețea și cadre iframe. Acesta a fost cel mai greu de configurat pentru noi, deoarece aveam scripturi, imagini, stiluri și puncte finale API terță parte de înregistrat în mod explicit în aceste politici.
Sfat: utilizați antetul Content-Security-Policy-Report-Only pentru a vă ajuta cu testarea în anumite medii. Dacă anumite resurse au încălcat politicile, am observat o ieșire utilă din consolă a resurselor pe care trebuia să le permitem în politicile noastre.
Dacă doriți să evitați o întâmplare amuzantă cu ecranele goale și aplicațiile web care nu se încarcă, vă recomandăm insistent să experimentați mai întâi cu politicile dvs. numai în modul de raportare și să faceți testare amănunțită înainte de a vă simți suficient de încrezător pentru a implementa aceste politici de securitate în producție.
X-Conținut-Tip-Opțiuni
Aceasta este pentru a menține și a încărca activele cu tipurile MIME corecte în pagina dvs. web.
X-Frame-Opțiuni
Aceasta este pentru a oferi reguli cu privire la modul în care aplicația dvs. web se încarcă potențial într-un iframe.
X-XSS-Protecție
Acest lucru oprește încărcarea paginilor dacă un atac de scripting între site-uri este detectabil în anumite browsere.
Referitor-Politica
Acesta gestionează modul în care antetul „Referitor” cu informații despre originea solicitării trece atunci când urmăresc linkuri către site-uri sau resurse externe.
Având în vedere aceste anteturi de securitate, să revenim la modul în care am configurat distribuțiile CloudFront astăzi și la modul în care funcțiile Lambda@Edge ne vor ajuta să ne atingem obiectivul.
Folosind Lambda@Edge cu distribuțiile noastre CloudFront
Pentru distribuțiile noastre CloudFront, am configurat lucruri precum:
- Certificatele SSL pentru domenii de atașat deasupra adresei URL CloudFront, cum ar fi https://app.sendgrid.com
- Originile cupei S3
- Grupuri de origine cu compartimente primare și replică pentru failover automat
- Comportamentele în cache
Aceste comportamente de cache, în special, ne permit să controlăm cât timp dorim ca răspunsurile pentru anumite tipuri de căi și fișiere să fie stocate în cache pe serverele edge din întreaga lume. În plus, comportamentele din cache ne oferă, de asemenea, o modalitate de a declanșa funcțiile AWS Lambda ca răspuns la diferitele evenimente, cum ar fi cererile de origine și răspunsurile de origine. Vă puteți gândi la funcțiile AWS Lambda ca un cod specific pe care îl definiți, care va rula ca răspuns la un anumit eveniment.
În cazul nostru, putem modifica anteturile răspunsului de origine înainte ca acestea să fie stocate în cache de serverele edge. Funcția noastră Lambda@Edge va adăuga anteturi de securitate personalizate la răspunsul de origine înainte ca acesta să revină în cele din urmă înapoi la serverul edge și înainte ca utilizatorul final să primească fișierele JavaScript, CSS și HTML cu acele anteturi.
Ne-am modelat abordarea după această postare de blog AWS și am extins-o pentru a fi mai ușor să faceți modificări la o anumită Politică de securitate a conținutului. Vă puteți modela funcția Lambda@Edge după modul în care am configurat lucrurile în generarea de liste pentru script, stil și surse de conectare. Această funcție modifică efectiv anteturile de răspuns de origine CloudFront și adaugă fiecare antet de securitate cu anumite valori la răspuns înainte de a reveni, apelând funcția de apel invers furnizată, așa cum se arată mai jos.
Cum testăm această funcție Lambda@Edge?
Înainte de a modifica oficial modul în care revin activele dvs. cu antetele de securitate, ar trebui să verificați că funcția funcționează după ce configurați totul manual prin Consola AWS. Este esențial ca aplicațiile dvs. web să se poată încărca și să funcționeze corect cu anteturile de securitate adăugate la răspunsurile rețelei. Ultimul lucru pe care doriți să îl auziți este o întrerupere neașteptată din cauza anteturilor de securitate, așa că testați-le cu atenție în mediile dvs. de dezvoltare.
De asemenea, este important să știți ce veți scrie mai târziu în codul Terraform pentru a salva această configurație în baza de cod. În cazul în care nu știți despre Terraform, acesta vă oferă o modalitate de a scrie și de a vă gestiona infrastructura cloud prin cod.
Sfat: aruncați o privire la documentele Terraform pentru a vedea dacă vă poate ajuta să vă mențineți configurațiile complexe fără a fi nevoie să vă amintiți toți pașii pe care i-ați făcut în consolele cloud.
Cum să începeți în Consola AWS
Să începem cu cum să configurați lucrurile manual prin Consola AWS.
- În primul rând, trebuie să creați funcția Lambda@Edge în regiunea „us-east-1”. Mergând la pagina de servicii Lambda, vom face clic pe „Creare Funcție” și o denumim așa cum ar fi „testSecurityHeaders1”.
2. Puteți utiliza un rol existent cu permisiuni pentru a rula funcția pe serverele edge sau puteți utiliza unul dintre șabloanele de politică a rolului acestora, cum ar fi „Permisiuni de bază Lambda@Edge…” și să îl denumiți „lambdaedgeroletest”.
3. După ce ați creat funcția și rolul Lambda de testare, ar trebui să vedeți ceva de genul acesta, unde veți observa butonul „Adăugați declanșator” pentru funcție. Aici veți asocia în cele din urmă Lambda cu comportamentul de cache al unei distribuții CloudFront declanșat la evenimentul de răspuns la origine.
4. Apoi, trebuie să editați codul funcției cu codul antetelor de securitate pe care l-am creat anterior și să apăsați „Salvare”.
5. După salvarea codului funcției, să verificăm dacă funcția Lambda funcționează chiar și derulând în partea de sus și apăsând butonul „Test”. Veți crea un eveniment de testare numit „samplecloudfrontresponse” folosind șablonul de eveniment „cloudfront-modify-response-header” pentru a bate joc de un eveniment de răspuns de origine CloudFront real și pentru a vedea cum funcția dumneavoastră rulează împotriva acestuia.
Veți observa lucruri precum obiectul antetului „cf.response” pe care codul funcției Lambda îl va modifica.
6. După ce ați creat evenimentul de testare, veți face clic din nou pe butonul „Test” și ar trebui să vedeți cum funcția Lambda a funcționat împotriva acestuia. Ar trebui să ruleze cu succes cu jurnalele care afișează răspunsul rezultat cu anteturi de securitate adăugate ca acesta.
Grozav, funcția Lambda pare să atașeze corect anteturile de securitate la răspuns!
7. Să revenim la zona „Designer” și să facem clic pe butonul „Adăugați declanșator”, astfel încât să puteți asocia funcția Lambda cu comportamentele de cache ale distribuției dvs. CloudFront la evenimentul de răspuns la origine. Asigurați-vă că selectați un declanșator „CloudFront” și faceți clic pe butonul „Deploy to Lambda@Edge”.
8. Apoi, selectați distribuția CloudFront (în exemplul nostru, am șters intrarea aici din motive de securitate) și un comportament de cache pentru a-l asocia.
Apoi alegeți comportamentul în cache „*” și selectați evenimentul „Răspuns la origine” pentru a se potrivi pe toate căile de solicitare cu distribuția dvs. CloudFront și pentru a vă asigura că funcția Lambda rulează întotdeauna pentru toate răspunsurile de origine.
Apoi bifați confirmarea înainte de a face clic pe „Implementați” pentru a vă implementa oficial funcția Lambda.
9. După ce ați asociat cu succes funcția dvs. Lambda cu toate comportamentele relevante din cache ale distribuției dvs. CloudFront, ar trebui să vedeți ceva similar cu acesta în zona „Designer” a tabloului de bord Lambda, unde puteți vedea declanșatoarele CloudFront și aveți opțiunea de a le vizualiza sau șterge.
Efectuarea modificărilor codului dvs. Lambda
Ori de câte ori este necesar să faceți modificări codului Lambda, vă recomandăm:
- Publicați o versiune nouă prin meniul drop-down butonului „Acțiuni”.
- Ștergeți declanșatoarele de pe versiunea mai veche (puteți face clic pe meniul drop-down „Calificări” pentru a vedea toate versiunile de Lambda)
- Asociați declanșatoarele cu cel mai nou număr de versiune pe care l-ați publicat recent
La implementarea dvs. Lambda pentru prima dată sau după publicarea unei noi versiuni a Lambda și asocierea declanșatorilor cu versiunea Lambda mai nouă, este posibil să nu vedeți anteturile de securitate imediat în răspunsurile dvs. pentru aplicația dvs. web. Acest lucru se datorează modului în care serverele edge din CloudFront memorează răspunsurile în cache. În funcție de cât timp ați setat timpul de viață în comportamentele dvs. de cache, poate fi necesar să așteptați un timp pentru a vedea noile anteturi de securitate, cu excepția cazului în care faceți o invalidare a memoriei cache în distribuția dvs. CloudFront afectată.
După redistribuirea modificărilor la funcția Lambda, deseori este nevoie de timp pentru ca cache-ul să se golească (în funcție de setările dvs. de cache CloudFront) înainte ca răspunsurile dvs. să aibă cele mai recente modificări ale anteturilor dvs. de securitate.
Sfat: Pentru a evita să reîmprospătați pagina mult sau să rămâneți nesigur dacă modificările dvs. au funcționat, porniți o invalidare a memoriei cache CloudFront pentru a accelera procesul de ștergere a memoriei cache, astfel încât să puteți vedea anteturile de securitate actualizate.
Accesați pagina Servicii CloudFront, așteptați ca starea distribuției CloudFront să fie implementată, ceea ce înseamnă că toate asociațiile lambda sunt complete și implementate și accesați fila „Invalidări”. Faceți clic pe „Creați o invalidare” și puneți „/*” ca cale pentru a invalida toate lucrurile din cache și apăsați pe „Invalidare”. Acest lucru nu ar trebui să dureze prea mult și, după ce este complet, reîmprospătarea aplicației dvs. web ar trebui să vadă cele mai recente modificări ale antetului de securitate.
Pe măsură ce repetați anteturile de securitate pe baza a ceea ce găsiți drept încălcări sau erori în aplicația dvs. web, puteți repeta acest proces:
- Publicarea unei noi versiuni a funcției Lambda
- Ștergerea declanșatorilor de pe vechea versiune Lambda
- Asocierea declanșatorilor pe noua versiune
- Cache-ul vă invalidează distribuția CloudFront
- Testarea aplicației dvs. web
- Repetați până când vă simțiți încrezători și în siguranță, lucrurile funcționează conform așteptărilor, fără pagini goale, solicitări API nereușite sau erori de securitate ale consolei
Odată ce lucrurile sunt stabile, puteți trece opțional la Terraforming ceea ce tocmai ați făcut manual în configurațiile de cod, presupunând că aveți Terraform integrat cu conturile dvs. AWS. Nu vom acoperi cum să configurați Terraform de la început, dar vă vom arăta fragmente din cum va arăta codul Terraform.
Terraformarea Lambda@Edge declanșată de distribuția noastră CloudFront
După ce am repetat funcția Lambda@Edge pentru anteturile de securitate din regiunea „us-east-1”, am vrut să adăugăm acest lucru la baza noastră de cod Terraform pentru menținerea codului și controlul versiunilor pe drum.
Pentru toate comportamentele de cache pe care le-am implementat deja, a trebuit să asociem comportamentul de cache cu funcția Lambda@Edge, pe care a declanșat-o evenimentul de răspuns la origine.
Următorii pași presupun că aveți deja majoritatea distribuțiilor CloudFront și a compartimentelor S3 configurate prin Terraform. Ne vom concentra asupra principalelor module și proprietăți care se referă la Lambda@Edge și vom adăuga declanșatorul comportamentelor de cache ale distribuției CloudFront. Nu vom explica cum să vă configurați compartimentele S3 și alte setări de distribuție CloudFront de la zero prin Terraform, dar sperăm că puteți vedea nivelul de efort pentru a realiza acest lucru pe cont propriu.
În prezent, împărțim resursele noastre AWS în foldere de module separate și trecem variabile în acele module pentru flexibilitate în configurația noastră. Avem un folder de apply
cu un subfolder de development
și production
și fiecare are main.tf
fișier principal.tf unde numim aceste module cu anumite variabile de intrare pentru a instanția sau modifica resursele noastre AWS.
Aceste subfoldere au, de asemenea, fiecare un folder lambdas
în care păstrăm codul nostru Lambda, cum ar fi fișierul security_headers_lambda.js
. security_headers_lambda.js
are același cod pe care l-am folosit în funcția noastră Lambda când am testat-o manual, cu excepția faptului că îl salvăm și în baza noastră de cod pentru ca noi să-l arhivăm și să îl încărcăm prin Terraform.
1. Mai întâi, avem nevoie de un modul reutilizabil pentru a arhiva fișierul nostru Lambda înainte ca acesta să fie încărcat și publicat ca o altă versiune a funcției noastre Lambda@Edge. Aceasta ia o cale către folderul nostru Lambda care conține eventuala funcție Lambda Node.js.
2. Apoi, adăugăm la modulul nostru CloudFront existent, care înglobează gălețile S3, politicile și resursele de distribuție CloudFront creând, de asemenea, o resursă Lambda construită din fișierul Lambda arhivat. Deoarece ieșirile modulului Lambda zip trec ca variabile în modulul CloudFront pentru a configura resursa Lambda, trebuie să specificăm regiunea furnizorului AWS ca „us-east-1” și cu o politică de rol de lucru ca aceasta.
3. În cadrul modulului CloudFront, asociem apoi această funcție Lambda@Edge cu comportamentele de cache ale distribuției CloudFront, așa cum este demonstrat mai jos.
4. În cele din urmă, punând totul împreună în fișierul main.tf
al folderului de apply/development
sau de apply/production
, apelăm toate aceste module și punem ieșirile corespunzătoare ca variabile în modulul nostru CloudFront, așa cum se arată aici.
Aceste modificări de configurare au grijă, în esență, de pașii manuali pe care i-am făcut în secțiunea anterioară pentru a actualiza codul Lambda și pentru a asocia versiunea mai nouă cu comportamentele de cache și declanșatoarele CloudFront pentru evenimentele de răspuns la origine. Woo hoo! Nu este nevoie să parcurgeți sau să vă amintiți pașii Consolei AWS atâta timp cât aplicăm aceste modificări resurselor noastre.
Cum implementăm acest lucru în siguranță în diferite medii?
Când am asociat prima dată funcția noastră Lambda@Edge cu distribuția noastră de testare CloudFront, am observat rapid cum aplicația noastră web nu se va mai încărca corect. Acest lucru s-a datorat în principal modului în care am implementat antetul Content-Security-Policy și că nu a acoperit toate resursele pe care le-am încărcat în aplicația noastră. Celelalte anteturi de securitate au reprezentat un risc mai mic în ceea ce privește blocarea încărcării aplicației noastre. În viitor, ne vom concentra pe lansarea antetelor de securitate având în vedere iterații ulterioare pentru a ajusta antetul Content-Security-Policy.
După cum am menționat mai devreme, am descoperit cum putem profita de antetul Content-Security-Policy-Report-Only pentru a minimiza riscul pe măsură ce adunăm mai multe domenii de resurse pentru a le adăuga în fiecare dintre politicile noastre.
În acest mod doar de raportare, politicile vor rula în continuare în browser și vor scoate mesaje de eroare din consola pentru orice încălcare a politicilor. Cu toate acestea, nu va bloca definitiv acele scripturi și surse, astfel încât aplicația noastră web poate rula în continuare ca de obicei. Depinde de noi să continuăm să parcurgem întreaga aplicație web pentru a ne asigura că nu pierdem nicio sursă importantă din politicile noastre, altfel ne va afecta negativ clienții și echipa de asistență.
Pentru fiecare mediu, puteți lansa anteturile de securitate Lambda după cum urmează:
- Publicați modificările aduse Lambda fie manual, fie printr-un plan Terraform și aplicați mai întâi pentru modificările mediului cu alte anteturi de securitate și antetul Content-Security-Policy-Report-Only.
- Așteptați ca starea distribuției dvs. CloudFront să fie implementată complet cu Lambda asociat cu comportamentele din cache.
- Efectuați o invalidare a memoriei cache pe distribuția dvs. CloudFront dacă anteturile de securitate anterioare încă apar sau este nevoie de prea mult timp pentru ca modificările dvs. curente să apară în browser.
- Vizitați și vizitați paginile aplicației dvs. web cu instrumentele pentru dezvoltatori deschise, scanând consola pentru orice mesaje de eroare ale consolei „Doar raportare...” pentru a vă îmbunătăți antetul Politica de securitate a conținutului.
- Faceți modificări codului dvs. Lambda pentru a ține cont de acele încălcări raportate.
- Repetați de la primul pas până când vă simțiți suficient de încrezător pentru a vă schimba antetul din Content-Security-Policy-Report-Only în Content-Security-Policy, ceea ce înseamnă că mediul îl va aplica.
Îmbunătățirea scorului pentru anteturile de securitate
După ce am aplicat cu succes modificările Terraform în mediile noastre și am invalidat cache-urile CloudFront, am reîmprospătat paginile din aplicația noastră web. Am ținut deschise instrumentele pentru dezvoltatori pentru a vedea anteturile de securitate, cum ar fi HSTS, CSP și altele din răspunsurile rețelei noastre, cum ar fi anteturile de securitate prezentate mai jos.
De asemenea, am rulat aplicația noastră web printr-un raport de scanare a antetelor de securitate, cum ar fi cel de pe acest site . Drept urmare, am asistat la îmbunătățiri mari (o calificare A!) de la o notă anterior nereușită și puteți obține îmbunătățiri similare după ce vă modificați setările S3/CloudFront pentru a avea anteturi de securitate.
Înaintând cu anteturile de securitate
După ce ați configurat manual anteturile de securitate prin Consola AWS sau după ce ați Terraformat cu succes soluția și ați aplicat modificările în fiecare dintre mediile dvs., aveți acum o bază excelentă pentru a continua și a îmbunătăți anteturile de securitate existente în viitor.
În funcție de evoluția aplicației dvs. web, poate fi necesar să vă faceți antetul Content-Security-Policy mai specific în ceea ce privește resursele permise pentru o securitate mai strictă. Sau, poate fi necesar să adăugați un nou antet în întregime pentru un scop separat sau pentru a completa o altă gaură de securitate.
Cu aceste modificări viitoare ale anteturilor de securitate din funcțiile Lambda@Edge, puteți urma strategii de lansare similare pentru fiecare mediu pentru a vă asigura că aplicațiile dvs. web sunt protejate de atacurile rău intenționate pe web și funcționează în continuare fără ca utilizatorii să observe vreodată diferența.
Pentru mai multe articole scrise de Alfred Lucero, accesați pagina autorului blogului său: https://sendgrid.com/blog/author/alfred/