<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Éloi Alain</title>
    <description>The latest articles on Forem by Éloi Alain (@ealain).</description>
    <link>https://forem.com/ealain</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F813545%2Fc1554fcd-221a-4bd1-98e1-4ed8dd2108f1.jpeg</url>
      <title>Forem: Éloi Alain</title>
      <link>https://forem.com/ealain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ealain"/>
    <language>en</language>
    <item>
      <title>Clean authorization control in serverless functions</title>
      <dc:creator>Éloi Alain</dc:creator>
      <pubDate>Tue, 28 Nov 2023 12:47:45 +0000</pubDate>
      <link>https://forem.com/slsbytheodo/clean-authorization-control-in-serverless-functions-hm9</link>
      <guid>https://forem.com/slsbytheodo/clean-authorization-control-in-serverless-functions-hm9</guid>
      <description>&lt;p&gt;In this article, I walk you through some control points to clean up authorization code in your serverless functions.&lt;/p&gt;

&lt;p&gt;Serverless applications have a lot of benefits. They are easy to deploy and scale. They are also cheap to run. 🤑 However, they come with a few drawbacks. One of them being authorization hard to get right. On this matter is easy to make mistakes, write poorly maintainable code and introduce vulnerabilities. 😱&lt;/p&gt;

&lt;h1&gt;
  
  
  🕷️ Access control code can be ugly
&lt;/h1&gt;

&lt;p&gt;In a typical &lt;strong&gt;multitenant serverless application&lt;/strong&gt; on AWS, where Lambda is integrated with API Gateway for each endpoint, you &lt;strong&gt;have to write authorization code&lt;/strong&gt;. This is code that will check whether the user who originated the request is allowed to access data or perform an action.&lt;/p&gt;

&lt;p&gt;While in a monolithic application, you can rely on a framework to help you with that, &lt;strong&gt;you are on your own with serverless functions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As your application evolves and becomes more complex, this becomes hard to maintain and check for vulnerabilities.&lt;/p&gt;

&lt;p&gt;Hopefully, you can come up with a good access control strategy if you properly &lt;strong&gt;structure your code&lt;/strong&gt;. 🏗️&lt;/p&gt;

&lt;h1&gt;
  
  
  🤦‍♂️ Naive solution: authorization code in the business logic
&lt;/h1&gt;

&lt;p&gt;Let's consider a simple multitenant application to manage files for organizations. The application has two personas: CEO and user. CEO can access all files within their organization. Users can only access files they have created.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;poorly designed function&lt;/strong&gt; that handles the request to get a file might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// POORLY designed function&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Check that the user is in the requested organization&lt;/span&gt;
  &lt;span class="c1"&gt;// 🐍 authorization with business logic not directly related to the use case&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;organizationId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;organizationId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;organizations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;organizationId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Retrieve the file&lt;/span&gt;
  &lt;span class="c1"&gt;// 🚀 business logic&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Deny access if the user is not CEO or the author is not the user&lt;/span&gt;
  &lt;span class="c1"&gt;// 🐍 access control happening late&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CEO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  🧅 Share authorization code that all your functions use
&lt;/h1&gt;

&lt;p&gt;In many cases, you will have to write the same authorization code in multiple functions. For example, you might want to check that the user is in the requested organization. You can &lt;strong&gt;share this code in a middleware&lt;/strong&gt;. If you are using AWS Lambda, you can rely on &lt;a href="https://middy.js.org/"&gt;middy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using a middleware will separate authorization code from the business logic and make it much &lt;strong&gt;easier to read&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Organizing your code in layers helps a lot. For example, you can enrich the context with the user information in a middleware, before authorization, for later use in subsequent steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add the user to the context to use this information later in the authorization step&lt;/span&gt;
&lt;span class="c1"&gt;// src/middlewares/addUserToContext.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addUserToContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  ⏱️ Early check authorization
&lt;/h1&gt;

&lt;p&gt;Denying a rogue access as early as possible is a good practice.&lt;/p&gt;

&lt;p&gt;Frameworks like &lt;a href="https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html"&gt;Spring&lt;/a&gt; and &lt;a href="https://docs.nestjs.com/security/authorization"&gt;Nest&lt;/a&gt; have &lt;strong&gt;decorators&lt;/strong&gt; that you can use as soon as your function definition.&lt;/p&gt;

&lt;p&gt;Find a way to &lt;strong&gt;check authorization as early as possible&lt;/strong&gt; in the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/handlers/getFile.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Check that the user is in the requested organization&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;organizations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;organizationId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// If the user is not CEO, add a filter to only retrieve the files created by the user&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CEO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Retrieve the file&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Deny access if the user is not CEO or the author is not the user&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;middy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addUserToContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, leverage middleware to extract the authorization code from the business logic. ⛏️ See the next section for a full example.&lt;/p&gt;

&lt;h1&gt;
  
  
  📁 Use file hierarchy to identify shared and specific code
&lt;/h1&gt;

&lt;p&gt;Mind the &lt;strong&gt;file hierarchy&lt;/strong&gt;. You should identify shared and specific code at a glance 👀 Below you can see that every handler might have a specific &lt;code&gt;validateAccess&lt;/code&gt; logic, while shared middleware is available higher in the hierarchy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  handlers/
    getFile/
      getFile.ts
      index.ts
      validateAccess.ts
  middlewares/
    addUserToContext/
      addUserToContext.ts
      index.ts
    validateTenancy/
      validateTenancy.ts
      index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;function now only contains business logic&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/handlers/getFile/getFile.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Retrieve the file&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Middleware can be found at the handler definition level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/handlers/getFile/index.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;middy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addUserToContext&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validateTenancy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validateAccess&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shared middleware to validate tenancy (user is requesting a resource in their organization).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/middlewares/validateTenancy.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validateTenancy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Check that the user is in the requested organization&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;organizations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;organizationId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specific middleware to validate access (user is requesting a resource they have access to).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/handlers/getFile/validateAccess.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validateAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CEO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fileId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pro tip 🚀 prefer &lt;strong&gt;allow list based authorization&lt;/strong&gt; over deny list based authorization. This is a best practice, that will deny access by default.&lt;/p&gt;

&lt;h1&gt;
  
  
  Useful links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/what-is/restful-api/"&gt;AWS RESTful API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS Lambda middleware tooling: &lt;a href="https://middy.js.org/"&gt;middy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;With a proper code structure, you can easily evolve to &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html"&gt;API Gateway Lambda authorizers&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Deliver perfect HTTP security headers with AWS CloudFront</title>
      <dc:creator>Éloi Alain</dc:creator>
      <pubDate>Wed, 25 Jan 2023 15:30:01 +0000</pubDate>
      <link>https://forem.com/slsbytheodo/deliver-perfect-http-security-headers-with-aws-cloudfront-4din</link>
      <guid>https://forem.com/slsbytheodo/deliver-perfect-http-security-headers-with-aws-cloudfront-4din</guid>
      <description>&lt;p&gt;– Did you just say security headers?&lt;/p&gt;

&lt;p&gt;– Yes.&lt;/p&gt;

&lt;p&gt;– Are you talking about CORS headers?&lt;/p&gt;

&lt;p&gt;– No.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;AWS CloudFront enables you to easily make your users browse safer with managed security headers. Quickly check your compliance with &lt;a href="https://www.sls-mentor.dev/" rel="noopener noreferrer"&gt;sls-mentor&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP security headers: a very simple addition to your website to efficiently prevent attacks
&lt;/h2&gt;

&lt;p&gt;In the last 5 years, I have worked in a dozen teams to develop and run web applications. However, I have learnt about &lt;strong&gt;HTTP security headers&lt;/strong&gt; very late in my full stack developer journey. This is only very recently, when I joined &lt;a href="https://www.theodo.fr/" rel="noopener noreferrer"&gt;Theodo&lt;/a&gt;, that I was explained what HTTP security headers actually are. 😮&lt;/p&gt;

&lt;p&gt;HTTP security headers are a mechanism to &lt;strong&gt;protect your application from common attacks&lt;/strong&gt;. They are, as their name suggests, a set of HTTP headers with security purposes. They are set by the server and read by the browser, which then applies the &lt;strong&gt;security policy&lt;/strong&gt; described by the header.&lt;/p&gt;

&lt;p&gt;HTTP security headers are good &lt;em&gt;deployment&lt;/em&gt; practices. Thus, they fall under the responsibility of ops teams, rather than dev teams. But more and more, dev teams are also responsible for the deployment of their applications.&lt;/p&gt;

&lt;p&gt;The table below shows a subset of HTTP security headers. The description mentions the common attacks that the header protects against. The recommended value column contains optimal header values to protect your users against these threats.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Recommended value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security" rel="noopener noreferrer"&gt;Strict-Transport-Security&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;max-age=31536000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it using HTTP should automatically be converted to HTTPS. The user's inputs will never be readable by a man on the middle (except potentially the first call ever, which does not contain any sensitive information).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options" rel="noopener noreferrer"&gt;X-Content-Type-Options&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nosniff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prevents older browsers from guessing the content of files sent by the server rather than trusting the Content-Type header. This prevents the detection and execution of malicious Javascript in an image uploaded by an attacker and then retrieved by a victim.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options" rel="noopener noreferrer"&gt;X-Frame-Options&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SAMEORIGIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prevents the display of the site in an iframe, and thus protects against click-jacking.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection" rel="noopener noreferrer"&gt;X-XSS-Protection&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1; mode=block&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prevents rendering of the page if an XSS attack is detected.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy" rel="noopener noreferrer"&gt;Referrer-Policy&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;strict-origin-when-cross-origin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prevents sending sensitive information (origin, path and query string) to another website or when the protocol is downgraded (HTTPS → HTTP)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#security" rel="noopener noreferrer"&gt;extensive list&lt;/a&gt; can be found on the Mozilla Developer Network (MDN).&lt;/p&gt;

&lt;p&gt;These headers do not impact the application itself. Thus adding these can be done at a very low cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Side note on CORS headers
&lt;/h3&gt;

&lt;p&gt;Let’s digress a little bit to mention the Cross Origin Resource Sharing (CORS) headers. As a web application developer, you certainly already have come across them. Otherwise, believe me, you will encounter them sooner or later. 😉&lt;/p&gt;

&lt;p&gt;HTTP security headers differ from CORS headers because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they strengthen security features of the browser (instead of weakening the same origin policy)&lt;/li&gt;
&lt;li&gt;they integrate very well in your development journey 😂&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demystifying HTTP security headers on AWS
&lt;/h2&gt;

&lt;p&gt;AWS mentions &lt;a href="https://aws.amazon.com/websites/" rel="noopener noreferrer"&gt;several methods&lt;/a&gt; to deploy your website. Let's focus here on S3 and CloudFront and see how to configure security headers.&lt;/p&gt;

&lt;h3&gt;
  
  
  S3
&lt;/h3&gt;

&lt;p&gt;Amazon Simple Storage Service (S3) offers the option to host static websites. However, with this method, configuring HTTPS and all the more so HTTP security headers is &lt;em&gt;not possible&lt;/em&gt;. 😮&lt;/p&gt;

&lt;h3&gt;
  
  
  CloudFront
&lt;/h3&gt;

&lt;p&gt;On the contrary, &lt;strong&gt;HTTP security headers can be very easily enabled on CloudFront&lt;/strong&gt;. If this is your first time dealing with CloudFront:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;don’t worry, this is actually pretty easy and cheap&lt;/li&gt;
&lt;li&gt;brace yourself, CloudFront’s performance is mind blowing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in!&lt;/p&gt;

&lt;p&gt;The CloudFront service works by creating &lt;em&gt;distributions&lt;/em&gt;. These describe how your content will be delivered to your users.&lt;/p&gt;

&lt;p&gt;An option that CloudFront offers is managing headers policies for you. The service defines subsets of headers with relevant values (like the one above) that you can easily add to request and responses in the flow.&lt;/p&gt;

&lt;p&gt;Head over to the CloudFront service in the console.&lt;/p&gt;

&lt;p&gt;Create or modify the distribution of your choice. Here, let’s assume the origin is S3 (alternatively this could be your own HTTP server).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fealain%2Farticles%2Fmaster%2Fblog-posts%2Fsls-security-headers%2Fassets%2Fedit-behavior.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fealain%2Farticles%2Fmaster%2Fblog-posts%2Fsls-security-headers%2Fassets%2Fedit-behavior.png" title="Edit the behavior of your distribution" alt="edit-behavior" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can look for the &lt;em&gt;Response headers policy&lt;/em&gt; section and choose &lt;code&gt;SecurityHeadersPolicy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fealain%2Farticles%2Fmaster%2Fblog-posts%2Fsls-security-headers%2Fassets%2Fenable-security-headers.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fealain%2Farticles%2Fmaster%2Fblog-posts%2Fsls-security-headers%2Fassets%2Fenable-security-headers.png" title="Enable security headers on your distribution" alt="enable-security-headers" width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it! See, this was quite straightforward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further thoughts
&lt;/h2&gt;

&lt;p&gt;As I dived in this topic, I added a &lt;strong&gt;security check&lt;/strong&gt; to the &lt;strong&gt;audit tool&lt;/strong&gt; that I use in my team: &lt;a href="https://www.sls-mentor.dev/" rel="noopener noreferrer"&gt;sls-mentor&lt;/a&gt;. This is an &lt;strong&gt;open source&lt;/strong&gt; audit tool that helps us enforce &lt;strong&gt;best practices&lt;/strong&gt; on our projects. Don’t hesitate to try it and send feedback to the team via a &lt;a href="https://github.com/sls-mentor/sls-mentor/pulls" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt;, the project is actively maintained. 😉&lt;/p&gt;

&lt;p&gt;In the future, I will improve this security check to support projects that use their own managed policies on CloudFront. sls-mentor will check for the presence of the headers, and make finer recommendations on each header.&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
      <category>cloudfront</category>
      <category>security</category>
      <category>aws</category>
      <category>audit</category>
    </item>
    <item>
      <title>sls-mentor 1.0.0 available now! Your Free Open Source audit tool for AWS architectures!</title>
      <dc:creator>Éloi Alain</dc:creator>
      <pubDate>Tue, 20 Sep 2022 13:12:54 +0000</pubDate>
      <link>https://forem.com/slsbytheodo/guardian-100-available-now-your-free-open-source-audit-tool-for-aws-architectures-54cd</link>
      <guid>https://forem.com/slsbytheodo/guardian-100-available-now-your-free-open-source-audit-tool-for-aws-architectures-54cd</guid>
      <description>&lt;h3&gt;
  
  
  Hi there! &lt;strong&gt;sls-mentor 1.0.0&lt;/strong&gt; is now available! 🚀
&lt;/h3&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/sls-mentor/sls-mentor" rel="noopener noreferrer"&gt;sls-mentor&lt;/a&gt; is a command line tool that produces a detailed &lt;strong&gt;report&lt;/strong&gt; of the &lt;strong&gt;improvements&lt;/strong&gt; you can make to your &lt;strong&gt;AWS architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  As a developer, I use sls-mentor to ensure that my project meets the highest quality standards
&lt;/h3&gt;

&lt;p&gt;sls-mentor is the result of a two-year journey learning and improving AWS architectures.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sls-mentor covers a &lt;strong&gt;wide range of concerns&lt;/strong&gt;: green IT, costs, security and more below),&lt;/li&gt;
&lt;li&gt;sls-mentor has a &lt;strong&gt;thorough documentation&lt;/strong&gt; of its checks to help your team understand the underlying issues,&lt;/li&gt;
&lt;li&gt;sls-mentor &lt;strong&gt;suggests detailed actions&lt;/strong&gt; to solve issues,&lt;/li&gt;
&lt;li&gt;sls-mentor provides a &lt;strong&gt;clear API&lt;/strong&gt; for the community to maintain and add new checks,&lt;/li&gt;
&lt;li&gt;sls-mentor is &lt;strong&gt;framework agnostic&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The one liner of your dreams
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx sls-mentor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3i0inddqzv6z3z04j5o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3i0inddqzv6z3z04j5o.gif" title="Simple sls-mentor run" alt="npx sls-mentor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How does sls-mentor work?
&lt;/h3&gt;

&lt;p&gt;Under the hood, sls-mentor uses the AWS SDK to check your provisioned resources against a set of rules. As a result, sls-mentor is &lt;strong&gt;compatible with all frameworks&lt;/strong&gt; (Serverless, CDK, Terraform, CloudFormation, ...).&lt;/p&gt;

&lt;h1&gt;
  
  
  sls-mentor is designed for you
&lt;/h1&gt;

&lt;h3&gt;
  
  
  I know... You know the installation process
&lt;/h3&gt;

&lt;p&gt;Of course you can install sls-mentor globally to use it across all your projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; sls-mentor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, you can add sls-mentor to your project's development dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; sls-mentor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To help you quickly understand the improvements you can bring your infrastructure, a bit at a time, sls-mentor comes with tons of &lt;strong&gt;options&lt;/strong&gt; to reduce the scope of the analysis in a run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Focus the analysis on a specific CloudFormation stack
&lt;/h3&gt;

&lt;p&gt;Use the option &lt;code&gt;-c&lt;/code&gt; to focus the analysis on specific CloudFormation stacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx sls-mentor &lt;span class="nt"&gt;-c&lt;/span&gt; my-stack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Focus the analysis on specific tags
&lt;/h3&gt;

&lt;p&gt;Use the option &lt;code&gt;-t&lt;/code&gt; to focus the analysis on specific tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx sls-mentor &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-tag,Value&lt;span class="o"&gt;=&lt;/span&gt;my-value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Because AWS has quite &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#api-requests" rel="noopener noreferrer"&gt;restrictive rate limiting policy&lt;/a&gt;, it may be required to use at least one option if you have really big stacks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;sls-mentor is &lt;strong&gt;optimized&lt;/strong&gt; to reduce its number of requests. For projects with a lot of resources, it will &lt;strong&gt;throttle&lt;/strong&gt; requests to respect AWS quotas. This might cause a longer analysis time.&lt;/p&gt;

&lt;h2&gt;
  
  
  sls-mentor is best run in your CI
&lt;/h2&gt;

&lt;p&gt;I recommend adding sls-mentor checks to a recurring job in your CI platform to get a periodic report of the improvements you can bring to your infrastructure. Depending on how often your infrastructure changes, you can run sls-mentor once a day, once a week or once a month.&lt;/p&gt;

&lt;p&gt;By default, sls-mentor will exit with a non-zero code if it finds any issue. I recommend keeping this default setting and optionally use your CI provider option to allow this failing job. This way, you will be notified of any issue, and you will not block your deployment flow. Otherwise, you can use the option &lt;code&gt;--noFail&lt;/code&gt; to always exit with a success code.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI snippets
&lt;/h3&gt;

&lt;h4&gt;
  
  
  GitLab CI
&lt;/h4&gt;

&lt;p&gt;This snippet will run sls-mentor after merge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;sls-mentor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:16.17.0&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;post-deploy-test&lt;/span&gt; &lt;span class="c1"&gt;# the stage after your deployment&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.setup-cli&lt;/span&gt; &lt;span class="c1"&gt;# setup AWS CLI (export environment variables)&lt;/span&gt;
  &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install&lt;/span&gt; &lt;span class="c1"&gt;# the job that installs your dependencies&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;yarn sls-mentor -r eu-west-1 -c &amp;lt;stacks&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# fill in the stacks you want to check&lt;/span&gt;
  &lt;span class="na"&gt;allow_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# allow the job to fail, when you want to run subsequent tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Circle CI
&lt;/h4&gt;

&lt;p&gt;This snippet will run sls-mentor at 01:00 on Sundays.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sls-mentor-checks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cimg/node:16.17.0&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt; &lt;span class="c1"&gt;# checkout your code&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;setup-aws-cli&lt;/span&gt; &lt;span class="c1"&gt;# setup AWS CLI (export environment variables)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install&lt;/span&gt; &lt;span class="c1"&gt;# install your dependencies&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn sls-mentor -p my-aws-profile -c my-stack-1 my-stack-2&lt;/span&gt;
&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;weekly-sls-mentor-checks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;triggers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0'&lt;/span&gt; &lt;span class="c1"&gt;# run at 01:00 on Sundays&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sls-mentor-checks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠ You should be running at least Node v16 to get the appropriate return code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Some issues are more important to you than others
&lt;/h2&gt;

&lt;p&gt;That's why sls-mentor organizes the checks in 5 categories.&lt;/p&gt;

&lt;p&gt;🌱 &lt;strong&gt;Green IT&lt;/strong&gt;: this one is my favorite, it's about reducing your carbon footprint&lt;/p&gt;

&lt;p&gt;💲 &lt;strong&gt;Costs&lt;/strong&gt;: this one helps you reduce your AWS bill,&lt;/p&gt;

&lt;p&gt;🔒 &lt;strong&gt;Security&lt;/strong&gt;: you know, the thing that is important to you,&lt;/p&gt;

&lt;p&gt;⚡ &lt;strong&gt;Speed&lt;/strong&gt;: you know, the thing that is important to your users,&lt;/p&gt;

&lt;p&gt;🧘 &lt;strong&gt;Stability&lt;/strong&gt;: that's for your team.&lt;/p&gt;

&lt;p&gt;To illustrate, let's consider the following two checks.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. ARM – 🌱 + 💲 + ⚡
&lt;/h4&gt;

&lt;p&gt;The default architecture for &lt;strong&gt;Lambdas functions&lt;/strong&gt; is x86_64 but &lt;strong&gt;should be configure to arm64&lt;/strong&gt;. Lambda functions that use arm64 architecture (AWS &lt;strong&gt;Graviton2&lt;/strong&gt; CPU) can achieve &lt;a href="https://aws.amazon.com/blogs/compute/migrating-aws-lambda-functions-to-arm-based-aws-graviton2-processors/" rel="noopener noreferrer"&gt;34% better price performance&lt;/a&gt; than the equivalent function running on x86_64 architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/kumo/that-one-aws-lambda-hidden-configuration-that-will-make-you-a-hero-guardian-is-watching-over-you-5gi7"&gt;Full article on Lambda function architectures&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  2. S3 Intelligent Tiering – 💲
&lt;/h4&gt;

&lt;p&gt;sls-mentor not only has checks for Lambda, but other AWS services as well. For example, the S3 Intelligent Tiering storage class is designed to optimize storage costs by automatically moving data to the most cost-effective access tier. For a small monthly charge, S3 Intelligent Tiering monitors access patterns and automatically moves objects that have not been accessed for a long time to lower-cost access tiers.&lt;/p&gt;

&lt;h3&gt;
  
  
  As I mentioned in the introduction, new checks are frequently added
&lt;/h3&gt;

&lt;p&gt;We are currently working on a check to avoid infinite log retention in CloudWatch.&lt;/p&gt;

&lt;p&gt;Starting from version 1.0.0, whenever a new rule is added, at least the minor version will be bumped.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ If sls-mentor is configured to stop your deployment whenever a rule fails, do not to allow any minor version update (see &lt;a href="https://docs.npmjs.com/cli/v6/using-npm/semver" rel="noopener noreferrer"&gt;semver&lt;/a&gt;), as the introduction of a new rule could suddenly stop your deployment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  sls-mentor: AWS Trusted Advisor's little brother?
&lt;/h1&gt;

&lt;p&gt;On your path to a perfect AWS Cloud architecture, sls-mentor is a good first step before the advanced &lt;a href="https://aws.amazon.com/premiumsupport/technology/trusted-advisor/" rel="noopener noreferrer"&gt;AWS Trusted Advisor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;sls-mentor's background is a different from AWS Trusted Advisor because rules are sourced from the community. Because sls-mentor uses the AWS SDK, power users can also add their own rules with maximum flexibility.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sls-mentor&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Community&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trusted Advisor&lt;/td&gt;
&lt;td&gt;Start from $29 / month (&lt;a href="https://aws.amazon.com/premiumsupport/pricing" rel="noopener noreferrer"&gt;depends on your plan and monthly AWS charges&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the end, both tools may be used together. ✨&lt;/p&gt;

&lt;h1&gt;
  
  
  About Kumo
&lt;/h1&gt;

&lt;p&gt;This project was started at &lt;a href="https://www.theodo.com/experts/serverless" rel="noopener noreferrer"&gt;Kumo&lt;/a&gt;, a group of passionate developers highly experienced in Serverless architectures for the Web, to bring the highest quality solutions to our clients. sls-mentor has many valuable learnings of our team to help &lt;em&gt;you&lt;/em&gt; learn faster.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to us on &lt;a href="https://twitter.com/kumoserverless" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; if you have any questions or feedback.&lt;/p&gt;

&lt;h1&gt;
  
  
  See also
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/kumo/aws-lambda-101-shave-that-bundle-down-48c7"&gt;AWS Lambda 101: Shave That Bundle Down&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/kumo/aws-lambda-versions-time-to-clean-up-guardian-is-watching-over-you-jkd"&gt;AWS Lambda Versions: Time to clean up! - sls-mentor is watching over you&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/kumo"&gt;Kumo's blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theodo.com/" rel="noopener noreferrer"&gt;Theodo's website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>lambda</category>
      <category>codequality</category>
      <category>aws</category>
      <category>audit</category>
    </item>
    <item>
      <title>AWS Lambda 101: Shave That Bundle Down</title>
      <dc:creator>Éloi Alain</dc:creator>
      <pubDate>Tue, 14 Jun 2022 13:05:44 +0000</pubDate>
      <link>https://forem.com/slsbytheodo/aws-lambda-101-shave-that-bundle-down-48c7</link>
      <guid>https://forem.com/slsbytheodo/aws-lambda-101-shave-that-bundle-down-48c7</guid>
      <description>&lt;p&gt;&lt;em&gt;This article is part of a series on &lt;a href="https://github.com/sls-mentor/sls-mentor" rel="noopener noreferrer"&gt;sls-mentor&lt;/a&gt;, an open-source, highly configurable, automated best-practice audit tool for AWS serverless architectures.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The lighter, the better
&lt;/h1&gt;

&lt;p&gt;A light bundle will positively impact your Serverless architecture for at least two reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A light deployment package reduces the cold start of your Lambda function
&lt;/h2&gt;

&lt;p&gt;Reducing the size of the bundle will reduce the time it takes to upload the bundle, and also significantly reduce the lambda's cold start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fealain%2Farticles%2Fmaster%2Fblog-posts%2Fsls-mentor-bundle-size%2Fassets%2Fbundle-size-impact-on-cold-start.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fealain%2Farticles%2Fmaster%2Fblog-posts%2Fsls-mentor-bundle-size%2Fassets%2Fbundle-size-impact-on-cold-start.png" title="Cold start durations per deployment size (https://mikhail.io/serverless/coldstarts/aws/#does-package-size-matter)" alt="Cold start durations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should use appropriate tools to bundle your Lambda functions with a minimal size. For example, the Serverless Framework, with the &lt;a href="https://github.com/floydspace/serverless-esbuild" rel="noopener noreferrer"&gt;serverless-esbuild&lt;/a&gt; plugin, automatically bundles your code and uploads it to AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. AWS enforces quotas on deployment resources
&lt;/h2&gt;

&lt;p&gt;Smaller bundles will help you respect &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html" rel="noopener noreferrer"&gt;AWS quotas&lt;/a&gt;, allowing more functions in your AWS account!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Quota&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lambda function deployment package (zipped)&lt;/td&gt;
&lt;td&gt;50 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda function deployment package (uncompressed)&lt;/td&gt;
&lt;td&gt;250 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total deployment packages&lt;/td&gt;
&lt;td&gt;75 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  sls-mentor is your solution to easily check the size of your bundles
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/sls-mentor/sls-mentor" rel="noopener noreferrer"&gt;sls-mentor&lt;/a&gt; now offers a &lt;strong&gt;new rule&lt;/strong&gt; to warn you when uploading bundles over 5 MB.&lt;/p&gt;

&lt;p&gt;sls-mentor comes with &lt;strong&gt;many rules&lt;/strong&gt; to help you make the best decisions for your Serverless project. It will help you identify where your code can be optimized to achieve better performance at a lower cost.&lt;/p&gt;

&lt;h1&gt;
  
  
  sls-mentor how-to
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @sls-mentor/sls-mentor
npx sls-mentor -p &amp;lt;your_aws_profile&amp;gt; -c &amp;lt;your_stack_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sls-mentor is available on &lt;a href="https://www.npmjs.com/package/sls-mentor" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;. You will find instructions to use sls-mentor in your CI.&lt;/p&gt;

&lt;h1&gt;
  
  
  See also
&lt;/h1&gt;

&lt;p&gt;There are plenty of tools out there to optimize the size of your bundles. For instance the &lt;a href="https://github.com/adriencaccia/serverless-analyze-bundle-plugin" rel="noopener noreferrer"&gt;Serverless Analyze Bundle Plugin&lt;/a&gt; integrates with the Serverless Framework and helps you diagnose which of your NodeJS dependency is not properly tree-shaked.&lt;/p&gt;

&lt;p&gt;For more details on bundle size impact, take a look at &lt;a href="https://mikhail.io/serverless/coldstarts/aws/#does-package-size-matter" rel="noopener noreferrer"&gt;Mikhail Shilkov's blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>lambda</category>
      <category>codequality</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
