maandag 28 januari 2019

Serverless functie in de praktijk


"Show, don't tell" is een credo die hoog op mijn favorietenlijst staat. Ik schrijf veel over cloud computing en innovatie en heb geleerd dat voorbeelden veel krachtiger zijn dan het smijten van jargon om te laten zien hoeveel je weet. Net als met goede bronnen kun je met voorbeelden overtuigend laten zien wat je bedoelt, en hier heb ik weer een prachtig voorbeeld. Eerst beschrijf ik de techniek en het probleem, daarna bied ik de stappen aan om het voorbeeld in de praktijk in te zetten. Uiteraard komt er weer een heel boeket aan concepten krachtig bij elkaar. I Love it! net als engelse uitdrukkingen gebruiken. 



Concept numero uno: HTTP Headers voor veiligheid.

Je weet wellicht dat ik artikelen schrijf voor Computable. Het heeft mij jaren geduurd om ze te overtuigen HTTPS in te zetten. Maar met HTTPS ben je er nog niet, je hebt ook zoiets als HTTPS headers en als je geen idee hebt waar ik het over heb, dan ben je in goed gezelschap. Een zeer groot deel van bedrijven die websites leveren en beheren horen dit ook voor het eerst. Om een idee te geven; ga eens naar https://observatory.mozilla.org/analyze/www.computable.nl . Je kunt in dat laatste gedeelte ook andere websites plaatsen, maar dat is even niet het punt. Als het goed is zie je dat Computable een F scoort op HTTP Headers. Wat betekent dit? Kort door de bocht dat ze hun gebruikers niet beschermen tegen boosaardige code, phishing, injectie van javascript code uit andere bronnen, etcetera. HTTP headers zijn eigenschappen die je meegeeft vanuit de server naar de gebruiker die helpen de veiligheid te verhogen. HTTP headers zijn eigen laaghangend fruit als het gaat om veiligheid. Het lost niet veel problemen op, maar het kost ook niets om in te zetten. Slecht een paar simpele instellingen. Bam! Grote kans dat je nu al iets geleerd hebt en meteen ook iets om bevriende website eigenaren mee te plagen. De F is overigens normaal, de A is uitzonderlijk. De Content Security Policy is namelijk nodig om een A te krijgen en helaas vergt deze een enorme inspanning. Dus de B zul je veel tegenkomen en is in ieder geval wat. De F zegt eigenlijk dat de website eigenaar in de regel nog geen idee heeft, jij nu wel. Echter dit is bijvangst van deze blog.


Concept twee: Serverless.

Serverless is een concept waarbij je rekenkracht en data gebruikt waarbij je niet zelf de servers hoeft te beheren waarop deze berekeningen en data verwerking worden uitgevoerd. Mits goed toegepast is serverless enorm schaalbaar, snel, goedkoop en veilig. Daarnaast kan het een enorme impact hebben op je beheerkosten, in de positieve zin welteverstaan. Serverless in de zuivere vorm betekent ook dat je afneemt van een cloud provider. Serverless betekent dat jij geen servers hebt om te beheren.

Serverless kun je inzetten voor Application Programming Interfaces (API's), micro service architectuur, maar ook voor databases, data opslag en algemene functies. Serverless hebben ook beperkingen en zijn zeker niet in alle gevallen de beste keuzes. Als je nieuwe dingen bouwt loont het wel serverless te onderzoeken. Voor bijvoorbeeld start-ups of software bouwers kan dit het concept zijn die een bedrijf succesvol maakt. Opschalen in al zijn facetten is een horde waar veel renners over struikelen en met serverless neem je misschien wel een horde weg.

Een ding waar wij serverless voor inzetten is voor websites. Technici noemen dit vaak statische websites, ofwel websites die niet snel veranderen. Door een stukje dataopslag zoals Amazon S3 bucket in te stellen als webserver kun je een snelle, veilige website opzetten die ook nog eens goedkoop is. Je koppelt zo'n bucket aan een domein en plaatst er een index.html bestand in en het draait. Het nadeel is alleen dat je niet eenvoudig HTTP headers op een duurzame manier kunt toevoegen en zeker als je een header wilt aanpassen moet je dan alle pagina's hierop aanpassen.

Concept drie: Serverless Lambda functies

Door een serverless functie te schrijven die HTTP Headers injecteert voordat ze naar de surfende gebruiker gaan kun je op eenvoudige manier al je statische websites hiervan voorzien. In dit voorbeeld gebruik ik hier Lambda @ Edge van Amazon Web Services. Lambda zag het licht in 2014 als eerste serverless functie oplossing. Met de Edge toevoeging verplaats je deze naar de rand van je infrastructuur. Dus net tussen dat stukje waar je data Amazon verlaat en via het internet naar de gebruiker vertrekt. Een andere serverless service -cloudfront- zorgt voor een https certificaat en dat de website altijd razendsnel is, hier voeg je in de instellingen de lambda functie toe. Je hoeft deze dus 1 keer te schrijven en daarna kun je hem op alle statistische websites toepassen. Fire and forget, om bij populair Engelse taalgebruik te blijven.
Zelf uitproberen? Hier is een mini tutorial met wel alle essentiƫle elementen.
Er vanuit gaande dat je een statische website hebt gemaakt in een S3 bucket en je deze via een cloudfront distributie van HTTPS voorziet zijn hier de stappen:

Ga naar Lambda functies in je AWS console. Switch naar regio N-Virginia. Dit is nodig omdat anders Cloudfront de functie niet accepteert. Klik op "Create function" en geef het een naam, bijvoorbeeld addHTTPHeaders.  Kies voor runtime Node.js.6.10. Dit is op dit moment de enige mogelijkheid voor edge functions. Kies bij Rol "Create a new role from one or more templates". Alle functies moeten vanuit een security context worden uitgevoerd en dus niet meer rechten hebben dan strikt noodzakelijk. Deze rol geef je ook een naam zodat je deze kunt relateren aan de functie en deze documenteer je ook dat andere mensen in de organisatie weten wat het is zodat het kan worden opgeruimd als dingen veranderen. Daarna kies je een template policy die aan de rol gekoppeld wordt. Hier kies je voor Lambda@Edge permissions.
Nu zie je een stukje voorbeeld code voor de index.js. Deze maak je leeg en plak je onderstaande code:

'use strict';
exports.handler = (event, context, callback) => {
   const response = event.Records[0].cf.response;
   const headers = response.headers;
   
   headers['strict-transport-security'] = [{
       key: 'Strict-Transport-Security',
       value: "max-age=31536000; includeSubdomains; preload"
   }];
   headers['x-content-type-options'] = [{
       key: 'X-Content-Type-Options',
       value: "nosniff"
   }];
   
   headers['x-frame-options'] = [{
       key: 'X-Frame-Options',
       value: "DENY"
   }];
   
   headers['x-xss-protection'] = [{
       key: 'X-XSS-Protection',
       value: "1; mode=block"
   }];
   headers['referrer-policy'] = [{
       key: 'Referrer-Policy',
       value: "same-origin"
   }];
   
   callback(null, response);
};

Deze code bevat key value pairs voor de divers headers. De CSP header heb ik weggelaten omdat deze alle javascript op je website kreupel maakt. Dit is zeg maar voor gevorderden.

Sla de functie op. Nu moeten we hem alleen nog even aanzetten en dat doe je door bij Actions  op "Publish new version" te klikken. Boven Actions zie je nu een ARN verschijnen met een versienummer. Sla deze ARN even op in je kladblok. Dit is in feite het unieke object adres naar deze functie.

Ga nu naar CloudFront, kies een distributie die je aan wilt passen, ga naar de tab behaviors, klik op de default en kies Edit. Scroll naar beneden tot je "Lambda Functions Associations" ziet en kies in de keuzelijst "Viewer Response". Dit is in feite het moment dat de output van de functie aan een request (opvragen van een webpagina) wordt toegevoegd. Plak daar achter de ARN die je zonet hebt opgeslagen, vink "Include body" niet aan en druk op "Yes, Edit".
Ga naar https://observatory.mozilla.org/analyze/ en vul daar het webadres in wat je zonet hebt aangepast, bijvoorbeeld  www.mijnwebsite.nl en zie dat je nu ineens een B scoort.

Ik haal mijn kennis van het internet en de kracht van zoekmachines kan bijna niet overschat worden. Door te schrijven hoop ik zo ook iets toe te voegen. Als iets niet duidelijk is geef ik met liefde een toelichting. Tot slot de bron die mij geholpen heeft de basis voor elkaar te krijgen: