<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Serverless CISO - Medium]]></title>
        <description><![CDATA[We explore the benefits and cybersecurity of serverless computing. Serverless allows startups and large enterprises to build some amazing things by providing on-demand, event-based, and low-cost computing. - Medium]]></description>
        <link>https://medium.com/serverlessciso?source=rss----8c43e619bad9---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Serverless CISO - Medium</title>
            <link>https://medium.com/serverlessciso?source=rss----8c43e619bad9---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 25 May 2026 22:04:08 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/serverlessciso" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[How do you launch a website on AWS?]]></title>
            <link>https://medium.com/serverlessciso/how-do-you-launch-a-website-on-aws-fa2ab48f5f8f?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/fa2ab48f5f8f</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[serverless]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Wed, 07 Jan 2026 20:34:21 GMT</pubDate>
            <atom:updated>2026-01-07T20:34:19.870Z</atom:updated>
            <content:encoded><![CDATA[<h4>We will review the different ways you can launch a website using AWS services.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NkHPLVtgqiwAPazMnZMM7Q.png" /></figure><p>There are various ways to launch a website using AWS.</p><p>The key is to determine what type of website you want to launch.</p><p>Here are some examples:</p><ul><li>A company/marketing website</li><li>A blog site</li><li>A web application</li></ul><p>Let’s explore how we could implement each type.</p><h3>Launching a company/marketing website</h3><p>Many business want an online presence.</p><p>They want to be able to include a website on their business cards and email footers.</p><p>They may focus most of their efforts on X, Instagram, or LinkedIn, for example, but they want that anchor.</p><p>They feel having a website makes them legitimate.</p><p>Yet, they are price conscious.</p><p>Using a website builder service that charges $20+ per month may be something they do not want to spend money on.</p><p>They might want to go with the DIY approach so they save some money and have the most control.</p><p>Let’s explore how AWS can help them build their website.</p><h4>Use Case: Hosting a CMS site</h4><p>A content management suite (CMS), such as Wordpress and Ghost, comes to mind as a solution to many people.</p><p>These platforms provide rich features for hosting your website or blog.</p><p>You can use <strong>Amazon EC2</strong> to create a low cost virtual server.</p><p>You would follow the installation instructions to set up your server to meet the technical requirements and set up the server and web application.</p><p>It may take a few tries depending on how well written are the installation instructions and how comfortable you are with using Linux which is the common OS used for web servers.</p><p>EC2 charges by the hour and you may be able to pay as low as $10 per month.</p><p>If you take advance of AWS reservations, you can secure a discount if you reserve EC2 server for 1 year or longer.</p><p>Next, you will want to set up an SSL certificate so users can visit the HTTPS version of your site.</p><p>Search engines and web browsers will trust you more if you have a valid SSL certificate.</p><p>Some CMS will create the SSL certificate for you while others will require you install it.</p><p>You can use <strong>AWS Certificate Manager</strong> to create your SSL certificate.</p><p>They are usually free if you set them up for another AWS service which in our case would be EC2.</p><p>What is convenient is that you can configure it so AWS manages the annual certificate renewal for you.</p><p>Next, you may need set up an email server for the CMS to send emails.</p><p>You can use <strong>Amazon SES</strong> to set up an SMTP login for the CMS to use.</p><p>You will follow the steps on the AWS Management Console to create the SMTP login and put that information in the CMS settings page.</p><p>SES charges by the number of emails and it is very low cost.</p><p>You initially start with 200 emails from SES until you can verify the domain.</p><p>Follow the instructions in the AWS Management Console to verify the domain to unlock the limit.</p><h4>Use Case: Static HTML Website Template</h4><p>There are many website templates out there.</p><p>You can get some decent ones for free.</p><p>Or you can pay extra to get some nicer looking ones with fancy animations.</p><p>They are usually pretty low cost because they require you to make the edits.</p><p>You will need to know some HTML and basic CSS and JavaScript.</p><p>You will use your web browser to preview the code changes you made.</p><p>Once you are ready, you can upload all the HTML, CSS, JavaScript, icon, font and image files on an <strong>Amazon S3</strong> bucket.</p><p>S3 storage is extremely cost effective.</p><p>You can enable the static web hosting feature on S3 but this will only give you HTTP access.</p><p>It is better to use a <strong>CloudFront</strong> distribution to serve the files from S3.</p><p>CloudFront will give you an HTTPS web address and cache your website files for faster load times.</p><p>You will need to add a policy to S3 allowing CloudFront to access the bucket.</p><p>You can use <strong>Amazon Certificate Manager</strong> and <strong>Route 53</strong> to help you get a vanity domain so you are not using the auto-generated domain name.</p><p>The benefit of this approach is that you can save a lot of money on hosting costs because the S3 storage costs and the CloudFront data transfer fees are generally super cheap.</p><p>The downside is that the contact form that comes with the template will not work.</p><p>Most template sites give you a contact form that works with PHP.</p><p>Many template developers assume you will be hosting these files on a typical PHP web server.</p><p>This is where there be some extra manual effort.</p><p>You will need to modify the contact form to use JavaScript to make a fetch request to a <strong>Lambda</strong> function.</p><p>You will need to create a Lambda function that accepts the HTTP request, parse the HTTP body and send an email.</p><p>You can configure a Lambda function URL to make it web accessible.</p><p>You can use <strong>Amazon SES</strong> to send the email.</p><p>But you will make an API request to SES rather than using its SMTP server.</p><p>Next, you will need to define an IAM policy and assign it to the Lambda function.</p><p>The IAM policy will allow the send email action from the function to the SES service.</p><p>From my experience, I have only paid $0.50 per month or less for all the services.</p><p>The biggest cost is the Amazon Route 53 hosted zone, but everything else stayed within the AWS free trier.</p><h3>Launching a blog site</h3><p>You can use the use cases we already discussed to set up a blog site.</p><p>A typical CMS is already designed to support blogging.</p><p>Many HTML template have an example blog post page.</p><p>You will need to create a new HTML file for each post.</p><p>And you will need to update the page that lists all the blog post, the RSS file, and sitemap file.</p><p>If you still like the idea of low-cost serverless web hosting, there is a new use case we can explore.</p><h4>Use Case: Static Site Generation</h4><p>There are developer tools that can help you create web application.</p><p>Tools like Vue.js, Nuxt, React, and many others allow you to create website that can be deployed as HTML files.</p><p>These tools support what is called the JAMstack which relies on JavaScript, APIs and Markup.</p><p>You can configure these tools for static site generation mode.</p><p>This mode will create multiple HTML files that will make it more efficient to load a blog site.</p><p>Without this mode, you will get one huge HTML file that will put a lot of stress on the web browser.</p><p>You can deploy the SSG website the same way you deploy the static HTML website template.</p><h3>Launching a Web Application</h3><p>Again, you can deploy a CMS that is already a web application.</p><p>And you can deploy the a web application that was built with frontend framework like Vue.js, Nuxt, React or something else.</p><p>There is a little extra work to make the frontend framework fully functional.</p><h4>Use Case: Web Application with a Web Server API</h4><p>The JAMstack relies on APIs.</p><p>We already talked about using a Lambda function URL.</p><p>This is fine if you only need one API endpoint like for a contact form.</p><p>But it is not advisable for a full web application that has multiple API endpoints.</p><p>One way to create an API is to set up an EC2 instance to run Node.js, PHP or some other server language to accept HTTP requests.</p><p>This setup will work fine for low web traffic, but it will max out at some point.</p><p>You will need to start increasing the CPU and RAM as your web traffic increases.</p><p>But this will only take you so far.</p><p>At some point, there will be insufficient resources available to handle heavy traffic loads.</p><p>Before you get to this point, you will want to set up an <strong>Application Load Balancer</strong>.</p><p>The ALB will allow you to split the traffic among multiple servers.</p><p>With an advanced set up, you can have it create new EC2 instances as your demand spikes and delete them as it falls.</p><p>You will want to take advantage of EC2 images so you can spin up new instances with your web server already configured.</p><h4>Use Case: Web Application with a Serverless API</h4><p>Another solution is to set up <strong>API Gateway</strong>.</p><p>The API Gateway allow you to define your API endpoints.</p><p>You can use OpenAPI to set it up too.</p><p>Each API endpoint and method can point to other AWS resources.</p><p>You could have it point to an EC2 server and an ALB, but pointing to Lambda functions can be more efficient.</p><p>Each API endpoint should point to a Lambda function.</p><p>That way each endpoint and function code has a specific purpose.</p><p>Lambda already takes care of scaling.</p><p>API Gateway also does rate limiting to help you manage traffic spikes and it drops invalid API requests.</p><p>But you will have a lot of Lambda functions and each should have its own IAM policy.</p><p>You will have more resources deployed.</p><p>When API endpoint are retired, there will be more resources to clean up to avoid phantom resources that an adversary can exploit.</p><h3>Conclusion</h3><p>AWS allows you to deploy server-based and serverless solutions to meet your needs and use cases.</p><p>Some teams prefer pure server-based and other serverless.</p><p>Realistically, there could be a mix of both depending on what are your needs.</p><p>I wrote a book that teaches you step-by-step to build a serverless web application on AWS.</p><p>Get a copy if you’re interested in learning how to do this.</p><p><a href="https://masteringawsserverlessbook.com/">Mastering AWS Serverless Book</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fa2ab48f5f8f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/how-do-you-launch-a-website-on-aws-fa2ab48f5f8f">How do you launch a website on AWS?</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Protect Your AWS S3 Buckets from Ransomware]]></title>
            <link>https://medium.com/serverlessciso/how-to-protect-your-aws-s3-buckets-from-ransomware-8e37a8289ed5?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/8e37a8289ed5</guid>
            <category><![CDATA[cloud]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Wed, 22 Jan 2025 04:40:28 GMT</pubDate>
            <atom:updated>2025-01-22T04:46:20.866Z</atom:updated>
            <content:encoded><![CDATA[<h3>How To Protect Your AWS S3 Buckets From Ransomware</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8lQbXWrF1XuxgFUg" /><figcaption>Photo by <a href="https://unsplash.com/@jccards?utm_source=medium&amp;utm_medium=referral">Marek Studzinski</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>A recent article highlighted how files on an S3 bucket can be taken captive by a ransomware attack.</p><p><a href="https://www.techradar.com/pro/security/aws-s3-feature-exploited-by-ransomware-hackers-to-encrypt-storage-buckets">AWS S3 feature abused by ransomware hackers to encrypt storage buckets</a></p><h3>How The Attack Happens</h3><p>A malicious actor will do the following to ransom your S3 objects.</p><ol><li>Find an AWS IAM keys that are exposed.</li><li>They access your AWS accounts with the IAM keys.</li><li>The discover which S3 buckets to which the IAM key has privileges.</li><li>They use the SSE-C encryption method to encrypt the bucket.</li><li>They mark the buckets for deletion in one week using lifecycle rules.</li></ol><p>Even if you pay to have the objects decrypted, they might be automatically deleted before you even get a chance to decrypt them.</p><h3>How To Protect Yourself</h3><p>There are various ways to protect yourself from this type of attack.</p><h4>Protect Your IAM Keys</h4><ol><li>Do not commit them to your repos.</li><li>Do not shared them in Slack or other messaging tools.</li><li>Rotate the keys on a schedule.</li><li>Delete them when you no longer need them.</li><li>Enforce MFA with the associated IAM user.</li></ol><h4>Stop Using IAM Keys</h4><ol><li>Use AWS STS to issue you a temporary IAM access keys that expire after one hour.</li><li>AWS IAM Identity Center that provides temporary IAM access keys from its web-based portal.</li><li>Use a Lambda function to perform the request. Assign the function to have the permissions to perform the desired changes. Securely invoke the function.</li></ol><h4>Use Least Privilege IAM Policies</h4><ol><li>Write your policies to only have the necessary privileges to get the job done and nothing else.</li><li>The IAM users should not have access to more resources than needed.</li></ol><h4>Replication and Backups</h4><ol><li>Use AWS Backup to back up your S3 objects.</li><li>Replicate your S3 objects to a bucket in another region.</li><li>Replicate your S3 objects to another AWS account.</li></ol><h3>S3 Features</h3><ol><li>Turn on object lock which prevents modifying S3 objects.</li><li>Use lifecycle management that moves old objects to cold storage which takes a long time to retrieve. This could mess up the ransomware scripts.</li><li>Use S3 versioning. Even if the object is deleted, any old version are still retained unless explicitly deleted.</li></ol><h3>Podcast Discussion</h3><p>I discussed this topic on the LogiCast podcast.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.podbean.com%2Fplayer-v2%2F%3Fshare%3D1%26download%3D1%26rtl%3D0%26fonts%3DArial%26skin%3D1%26btn-skin%3Dff6d00%26multiple_size%3D315%26square_size%3D300%26order%3Depisodic%26filter%3Dall%26limit%3D10%26season%3Dall%26tag%3Dall%26i%3Dszic4-17bdf8b-pb&amp;display_name=Podbean&amp;url=https%3A%2F%2Flogicast.podbean.com%2Fe%2Fseason-4-episode-3-spots-servers-and-security%2F&amp;image=https%3A%2F%2Fd2bwo9zemjwxh5.cloudfront.net%2Fimage-logo%2F15510558%2FCaptain_Cloud_2000x2000_Squareb63vk_1200x628.jpg%3Fs%3D933aca0e34d77aa9cbfaad11753497fe%26e%3Dpng&amp;type=text%2Fhtml&amp;schema=podbean" width="500" height="150" frameborder="0" scrolling="no"><a href="https://medium.com/media/bc1f9ae668ce995838c409dbd864ec02/href">https://medium.com/media/bc1f9ae668ce995838c409dbd864ec02/href</a></iframe><h3>Before you go</h3><p>Did you know I wrote a book that will help you build a serverless application step-by-step?</p><p><a href="https://amzn.to/4a1dnqO">Mastering AWS Serverless: Architecting, developing, and deploying serverless solutions on AWS (English Edition)</a></p><p><em>As an Amazon Associate I earn from qualifying purchases.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8e37a8289ed5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/how-to-protect-your-aws-s3-buckets-from-ransomware-8e37a8289ed5">How To Protect Your AWS S3 Buckets from Ransomware</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I Have Paid Almost Nothing for Website Hosting in Over 15 Years. This is How I Did It.]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/serverlessciso/i-have-paid-almost-nothing-for-website-hosting-in-over-15-years-this-is-how-i-did-it-2bbcdb3ed4ec?source=rss----8c43e619bad9---4"><img src="https://cdn-images-1.medium.com/max/2600/0*TO0NGJSfA6b5NdJx" width="6000"></a></p><p class="medium-feed-snippet">I have been using Amazon S3, Amazon CloudFront, and Cloudflare Pages to host my websites.</p><p class="medium-feed-link"><a href="https://medium.com/serverlessciso/i-have-paid-almost-nothing-for-website-hosting-in-over-15-years-this-is-how-i-did-it-2bbcdb3ed4ec?source=rss----8c43e619bad9---4">Continue reading on Serverless CISO »</a></p></div>]]></description>
            <link>https://medium.com/serverlessciso/i-have-paid-almost-nothing-for-website-hosting-in-over-15-years-this-is-how-i-did-it-2bbcdb3ed4ec?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/2bbcdb3ed4ec</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[website]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Fri, 03 Jan 2025 16:01:49 GMT</pubDate>
            <atom:updated>2025-01-03T16:01:48.547Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Speed up AWS CDK deploys up to 80%]]></title>
            <link>https://medium.com/serverlessciso/speed-up-aws-cdk-deploys-up-to-80-c47afad1c18c?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/c47afad1c18c</guid>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:15:29 GMT</pubDate>
            <atom:updated>2023-05-23T00:24:35.150Z</atom:updated>
            <content:encoded><![CDATA[<h4>The ts-node package needed the speed boost</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FrqFCzXAAfvEBQhM" /><figcaption>Photo by <a href="https://unsplash.com/@sumo?utm_source=medium&amp;utm_medium=referral">PAUL SMITH</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The Amazon Web Services Cloud Development Kit is an infrastructure-as-code solution. CDK allows us to write code (in JavaScript, TypeScript, Python, for example) to programmatically deploy resources in our AWS account.</p><p>CDK is written in TypeScript and uses the ts-node package to deploy. When we run the cdk command in the terminal, the npm package uses the ts-node package to transpile the CDK code before running it.</p><h3>The issue</h3><p>I was finding it was taking “forever” when running a cdk deploy or cdk synth command. When I was troubleshooting or developing code, I wanted faster deploys. I was using the cdk watch command to hotswap changes during development. This was a “little” faster but still felt super slow. I wanted to find out why these CDK commands were taking so long.</p><h3>This was the solution</h3><p>I will share the solution upfront. The rest of the post will share my findings.</p><p>I installed a new ts-node transpiler using npm.</p><pre>npm i -D @swc/core @swc/helpers regenerator-runtime</pre><p>I updated my tsconfig.json file to tell ts-node to use the new SWC transpiler. I added the ts-node property and the swc property under it.</p><pre>{<br>  &quot;ts-node&quot;: {<br>    &quot;swc&quot;: true<br>  }<br>}</pre><p>I noticed a significant improvement when running cdk and npx ts-node commands in the terminal.</p><p>Keep in mind this note from the <a href="https://swc.rs/docs/migrating-from-tsc">SWC website</a>:</p><blockquote>SWC only transpiles the code and doesn’t perform type checking. Therefore, it’s recommended that you continue to use tsc for detecting any type errors.</blockquote><h3>How I found the solution</h3><p>I realized that ts-node could be the issue. I write command line scripts with TypeScript. I use the npx ts-node myfile.ts command to execute them. They took a while to execute but did not think much about it. When I was getting frustrated by the CDK command start times, I started to realize the TypeScript script execution time was slow too.</p><p>I decided to investigate if they were speed issues with the ts-node package.</p><p>I found a GitHub issue where others expressed their concerns with the slowness of ts-node.</p><p><a href="https://github.com/TypeStrong/ts-node/issues/1070">ts-node &amp; nodemon takes 2 minutes to start; too slow · Issue #1070 · TypeStrong/ts-node</a></p><p>The discussion taught me about the SWC transpiler that can speed up the time ts-node uses.</p><p><a href="https://typestrong.org/ts-node/docs/swc/">SWC | ts-node</a></p><p>I installed the SWC packages and updated my tsconfig.json file. I noticed a significant improvement when using cdk deploy , cdk synth , cdk watch , and npx ts-node commands in the terminal. Development time was much faster now.</p><p>I updated my CI/CD pipeline that deploys multiple CDK apps and runs various TypeScript command line scripts. My CI/CD pipeline execution time dropped from 345 seconds to 74 seconds when I added the ts-node SWC setting. Wow! That’s over 75%.</p><p>I needed to share this finding with the CDK community. I submitted a GitHub pull request to add the SWC settings to the TypeScript app template.</p><p><a href="https://github.com/aws/aws-cdk/pull/25089">chore(cdk): Speed up typescript app compile time by miguel-a-calles-mba · Pull Request #25089 · aws/aws-cdk</a></p><p>If the pull request is approved and merged, new CDK apps created by the cdk init command will get this speed boost.</p><h3>Empirical testing</h3><p>Let’s do some testing to see the effects of the SWC transpiler.</p><p>Let’s create a folder for our CDK apps. We will use the ~/cdkapps folder. Note: My setup <a href="https://medium.com/better-programming/stop-installing-node-js-and-global-npm-packages-use-docker-instead-42597990db13">uses Docker</a> rather than installing Node.js directly onto my machine.</p><pre>cd ~<br>mkdir cdkapps</pre><h4>The first test</h4><p>We will create a new CDK app.</p><pre>cd ~/cdkapps<br>mkdir test1-cdk<br>cd test1-cdk<br>npx cdk init app --language typescript</pre><p>Let’s test the time it takes to synthesize an empty app.</p><pre>time npm run cdk synth</pre><p>The command sent this output:</p><pre>real 0m38.681s<br>user 0m46.195s<br>sys 0m1.769s</pre><p>It took 46 seconds to synthesize a CDK app.</p><p>Now let’s test with the SWC transpiler. (The command assumes the steps to add the SWC transpiler were already done.)</p><pre>time npm run cdk synth</pre><p>The command sent this output:</p><pre>real 0m9.562s<br>user 0m9.105s<br>sys 0m0.703s</pre><p>It took 9 seconds to synthesize a CDK app when using SWC. That’s an 80% improvement!</p><h4>The second test</h4><p>Now let’s create a new CDK app with one TypeScript Lambda function.</p><p>We will create a new CDK app.</p><pre>cd ~/cdkapps<br>mkdir test2-cdk<br>cd test2-cdk<br>npx cdk init app --language typescript</pre><p>Let’s add the packages to help with adding a Lambda function.</p><pre>npm i -D @types/aws-lambda</pre><p>Let’s create the Lambda function.</p><pre>touch function.ts</pre><p>Let’s create the function code.</p><pre>/* ~/cdkapps/test2-cdk/function.ts */<br><br>import { Handler } from &#39;aws-lambda&#39;;<br><br>export const handler: Handler&lt;Event&gt; = async function(event, _context) {<br>  return;<br>}</pre><p>Let’s create the function resource.</p><pre>/* ~/cdkapps/test2-cdk/lib/test2-cdk-stack.ts */<br>import * as cdk from &#39;aws-cdk-lib&#39;;<br>import { Construct } from &#39;constructs&#39;;<br>import * as path from &#39;path&#39;;<br><br>export class Test2CdkStack extends cdk.Stack {<br>  constructor(scope: Construct, id: string, props?: cdk.StackProps) {<br>    super(scope, id, props);<br><br>    new cdk.aws_lambda_nodejs.NodejsFunction(this, &#39;function&#39;, {<br>      functionName: &#39;function&#39;,<br>      handler: &#39;handler&#39;,<br>      runtime: cdk.aws_lambda.Runtime.NODEJS_18_X,<br>      entry: path.resolve(&#39;__dirname&#39;, &#39;..&#39;, &#39;function.ts&#39;),<br>    });<br>  }<br>}</pre><p>Let’s test the time it takes to synthesize an app on a bare TypeScript Lambda function.</p><pre>time npm run cdk synth</pre><p>The command sent this output:</p><pre>real 0m49.314s<br>user 0m58.874s<br>sys 0m3.818s</pre><p>It took 58 seconds to synthesize a CDK app.</p><p>Now let’s test with the SWC transpiler. (The command assumes the steps to add the SWC transpiler were already done.)</p><pre>time npm run cdk synth</pre><p>The command sent this output:</p><pre>real 0m18.985s<br>user 0m18.625s<br>sys 0m2.186s</pre><p>It took 18 seconds to synthesize a CDK app when using SWC. That’s a 67% improvement.</p><h3>Conclusion</h3><p>Consider adding the SWC transpiler for ts-node to your AWS CDK apps. The time results will vary depending on your setup.</p><h4>Before you go</h4><p>Here are other posts you might enjoy.</p><ul><li><a href="https://medium.com/chapter-by-chapter/aws-cdk-serverless-cookbook-ebook-1d4d4e0488c">AWS CDK Serverless Cookbook</a></li><li><a href="https://betterprogramming.pub/stop-installing-node-js-and-global-npm-packages-use-docker-instead-42597990db13">Stop Installing Node.js and Global Npm Packages, Use Docker Instead</a></li><li><a href="https://aws.plainenglish.io/cloudflare-v-aws-a-comparison-of-their-serverless-offerings-a32e2a000735">Cloudflare v. AWS: A Comparison of Their Serverless Offerings</a></li><li><a href="https://aws.plainenglish.io/how-i-caused-an-amazon-api-gateway-denial-of-service-cba93810e18f">How I Caused an Amazon API Gateway Denial of Service</a></li></ul><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Join our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><em> community and follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em> and</em><strong><em> </em></strong><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></p><p><strong><em>Learn how to build awareness and adoption for your startup with </em></strong><a href="https://circuit.ooo/?utm=publication-post-cta"><strong><em>Circuit</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c47afad1c18c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/speed-up-aws-cdk-deploys-up-to-80-c47afad1c18c">Speed up AWS CDK deploys up to 80%</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How a Lack of API Security Allowed Me to Wreak Havoc on a Database using Python]]></title>
            <link>https://medium.com/serverlessciso/how-a-lack-of-api-security-allowed-me-to-wreak-havoc-on-a-database-using-python-b26656296a8c?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/b26656296a8c</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:14:38 GMT</pubDate>
            <atom:updated>2024-12-22T16:14:50.842Z</atom:updated>
            <content:encoded><![CDATA[<h3>How a Lack of API Security Allowed Me to Use Python to Wreak Havoc on a Database</h3><h4>A deep dive case study that highlights the importance of addressing the injection OWASP top 10 security risk.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rP8Yff_f44v40-fFpb5_Lw.png" /><figcaption><em>The awesome artwork used to head this article is called “Abduction” and it was created by </em><a href="https://dribbble.com/BurntToast"><em>Burnt Toast</em></a><em>.</em></figcaption></figure><p>Developers love Application Programming Interfaces (APIs) because they allow them to take advantage of services without building them. But do the developers who create the APIs feel the same way considering that the API exposes their service to potential mayhem from a security perspective?</p><p>I have worked with many vendors and used their APIs to integrate their services into my projects. Some are easy to integrate, and others are not so. In the end, the integration provides much value to my project. Furthermore, my skills and knowledge have increased through various trials of integrating third-party services.</p><p>In this case, I describe a lesson reiterated and reinforced throughout a specific integration effort. The <a href="https://owasp.org/Top10/">OWASP Top Ten</a> documents the ten most critical application risks. Developers and projects should take this risk seriously. The realization of these risks might result in significant damage.</p><p>This case study explores one specific OWASP Top Ten risk.</p><h3>OWASP A03:2021-Injection</h3><p>The injection risk was considered the highest by OWASP for several years before dropping to third in 2021. An injection allows an attacker to compromise, destroy or control a system. Input validation and sanitization are one way to prevent it. OWASP recommends: “The preferred option is to use a safe API, which avoids the use of the interpreter entirely or provides a parameterized interface” [<a href="https://owasp.org/Top10/A03_2021-Injection/">OWASP Top 10 A3:2021-Injection</a>].</p><p>Seems like common sense. Why is this still ranked as the third highest risk if it should be evident to developers to protect against it?</p><p>Schedule and cost are likely the most prominent opponents of addressing this risk. Your software manager might tell the developer, “Just get it working because we need to release the product soon,” or “We are running over budget. Make a note and secure it later.” The developer might think, “It’s secure enough. Plus, we have firewalls and antivirus to protect against an intrusion.” Whatever the reasons might be, this simple solution often gets overlooked.</p><h3>How I was Using the Vendor API</h3><p>I was working on a script to promote our vendor data from one stage to another in the pipeline. A pipeline is a set of environments configured to promote development code to production. In our pipeline, we had a development, testing, and production environment. The scripts interfaced with the data in the development environment and created it in the testing environment. When all the tests passed, the scripts created the data in the production environment.</p><p>The API provided interfaces to log in, log out, retrieve data objects, create data objects, and delete data objects. The script workflow worked in the following way: log into one environment, retrieve the primary data objects, retrieve the child objects, log out, log into another environment, use the retrieved data to create the primary and child objects, and log out. Below is an example of how it worked.</p><pre>#!/usr/bin/python<br>import vendor_api<br>import json</pre><pre># log into the deveplopment environment<br>try:<br>    vendor_api.login(<br>        &#39;username&#39;,<br>        &#39;password&#39;,<br>        &#39;development&#39;<br>    )<br>except:<br>    exit(1)</pre><pre># get primary object<br># retrieves JSON structure<br># {<br>#   &quot;uuid&quot;: &quot;primary uuid value&quot;,<br>#   &quot;attribute1&quot;: &quot;value1&quot;,<br>#   &quot;attribute2&quot;: &quot;value2&quot;,<br>#   &quot;children&quot;: [&quot;uuid1&quot;, &quot;uuid2&quot;]<br># }</pre><pre>primary_object = json.loads(<br>    vendor_api.get(vendor_api.PRIMARY)<br>)</pre><pre># get child objects one at a time<br># retrieves JSON structure<br># {<br>#   &quot;uuid&quot;: &quot;child uuid value&quot;,<br>#   &quot;attribute1&quot;: &quot;value1&quot;,<br>#   &quot;attribute2&quot;: &quot;value2&quot;<br># }</pre><pre>child_objects = []</pre><pre>for x in range(0, len(primary_object[&#39;children&#39;]):<br>    uuid = primary_object[&#39;children&#39;][x]<br>    child_object = json.loads(<br>        vendor_api.get(vendor_api.CHILD, uuid)<br>    )<br>    if &quot;uuid&quot; in child_object:<br>        child_objects.append(child_object)</pre><pre># log out<br>vendor_api.logout()</pre><pre># log into the testing environment<br>try:<br>    vendor_api.login(&#39;username&#39;, &#39;password&#39;, &#39;testing&#39;)<br>except:<br>    exit(2)</pre><pre># create primary object<br># API documentation states <br># the following required structure:<br># {<br>#    &quot;attribute1&quot;: &quot;value1&quot;,<br>#    &quot;attribute2&quot;: &quot;value2&quot;<br># }</pre><pre>try:<br>    vendor_api.post(<br>        vendor_api.PRIMARY,<br>        json.dumps(primary_object)<br>    )<br>except:<br>    exit(3)</pre><pre># create child objects<br># API documentation states <br># the following required structure:<br># {<br>#    &quot;attribute1&quot;: &quot;value1&quot;,<br>#    &quot;attribute2&quot;: &quot;value2&quot;<br># }</pre><pre>for x in range(0, len(child_objects)):<br>    try:<br>        vendor_api.post(<br>            vendor_api.CHILD,<br>            json.dumps(child_objects[x])<br>        )<br>    except:<br>        print(<br>            &quot;Failed to created child object {}&quot;.format(<br>                child_objects[x][&#39;uuid&#39;]<br>            )<br>        )</pre><pre># log out<br>vendor_api.logout()</pre><pre>exit(0)</pre><h3>Concerns With the Use of the API</h3><p>Do you notice something wrong here? (Ignore my lack of coding excellence.) Did you notice I did not delete the uuid attribute from the primary_object object and child_objects objects or I did not delete the children attribute from the primary_object? Why are these issues?</p><p>Let’s assume the vendor had a strict API. When I passed uuid and children to vendor_api.post for vendor_api.PRIMARY object type, the vendor API should have returned an INVALID ATTRIBUTES response. A looser API would have simply ignored them without an error response. An extremely loose API would have accepted them. An extremely loose API might accept an injection such as an rm -rf / command.</p><h3>How I Corrupted a Database with an Accidental Injection Attack</h3><p>I was deep into testing, and my test scenarios kept failing. I could not understand why they were failing. I was confident I did my due diligence in the development environment; everything worked fine there. The same scenarios were failing in the testing environment. I eventually contacted the vendor to investigate what might be the issue. I needed the vendor’s help since they provided limited debugging capability and needed to debug their infrastructure.</p><p>Their first diagnosis: you are misusing the API. I explained my script logic over a phone call and emailed them my script. They admitted my script seemed fine.</p><p>Their second diagnosis: your test scenarios are incorrect. I explained my test scenarios over a phone call and emailed them my scenarios. They admitted my test scenarios were acceptable.</p><h3>What Was the Source of the Issue?</h3><p>They continued to investigate for a while and returned with their conclusion: I managed to create duplicate UUIDs across multiple environments in a system that required unique UUIDs globally. I inquired how this was possible. They admitted their API accepted all attributes and inputs for the child objects. They considered their primary objects the most critical information and took considerable efforts to secure that part of the API. Given the cost and schedule, they felt securing the child object portion of the API was less important. Luckily, I was a partner in discovering this vulnerability before their API was widely adopted or a malicious agent attempted to exploit this finding. It took the vendor a few days to secure the API and fix all the environments.</p><p>This situation depicted why Injection is still among the highest OWASP security risks.</p><p><em>This article was edited and originally published on </em><a href="https://www.secjuice.com/wreaking-havoc-via-api-case-study/"><em>secjuice.com</em></a><em>.</em></p><h3>Before You Go</h3><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>.</em></p><p><em>Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a><em>, and </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><strong><em>.</em></strong></p><p><strong><em>Interested in scaling your software startup</em></strong><em>? Check out </em><a href="https://circuit.ooo/?utm=publication-post-cta"><strong><em>Circuit</em></strong></a><em>.</em></p><p>Here are other articles you might enjoy.</p><ul><li><a href="https://aws.plainenglish.io/how-i-caused-an-amazon-api-gateway-denial-of-service-cba93810e18f">How I Caused an Amazon API Gateway Denial of Service</a></li><li><a href="https://medium.com/geekculture/five-scary-linux-commands-you-should-not-run-4222773188bb">Five scary Linux commands you should not run</a></li><li><a href="https://betterprogramming.pub/how-to-remove-sensitive-data-and-plaintext-secrets-from-github-ca8ca0b7675a">How to Remove Sensitive Data and Plaintext Secrets From GitHub</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b26656296a8c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/how-a-lack-of-api-security-allowed-me-to-wreak-havoc-on-a-database-using-python-b26656296a8c">How a Lack of API Security Allowed Me to Wreak Havoc on a Database using Python</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cloudflare v. AWS: A Comparison of Their Serverless Offerings]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/serverlessciso/cloudflare-v-aws-a-comparison-of-their-serverless-offerings-a32e2a000735?source=rss----8c43e619bad9---4"><img src="https://cdn-images-1.medium.com/max/600/1*PLAi6B7M25GfqGTWrI7llQ.png" width="600"></a></p><p class="medium-feed-snippet">They both have their benefits and downsides</p><p class="medium-feed-link"><a href="https://medium.com/serverlessciso/cloudflare-v-aws-a-comparison-of-their-serverless-offerings-a32e2a000735?source=rss----8c43e619bad9---4">Continue reading on Serverless CISO »</a></p></div>]]></description>
            <link>https://medium.com/serverlessciso/cloudflare-v-aws-a-comparison-of-their-serverless-offerings-a32e2a000735?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/a32e2a000735</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cloud]]></category>
            <category><![CDATA[cloudflare]]></category>
            <category><![CDATA[serverless]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:14:11 GMT</pubDate>
            <atom:updated>2023-05-23T00:24:15.027Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Stop bots spamming a contact form without a captcha]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/serverlessciso/stop-bots-spamming-a-contact-form-without-a-captcha-87de4726a5c?source=rss----8c43e619bad9---4"><img src="https://cdn-images-1.medium.com/max/2600/0*J03GunhB02MCUrMo" width="5472"></a></p><p class="medium-feed-snippet">A simple modification tricks these robots</p><p class="medium-feed-link"><a href="https://medium.com/serverlessciso/stop-bots-spamming-a-contact-form-without-a-captcha-87de4726a5c?source=rss----8c43e619bad9---4">Continue reading on Serverless CISO »</a></p></div>]]></description>
            <link>https://medium.com/serverlessciso/stop-bots-spamming-a-contact-form-without-a-captcha-87de4726a5c?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/87de4726a5c</guid>
            <category><![CDATA[bots]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[website-development]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:13:46 GMT</pubDate>
            <atom:updated>2022-10-28T12:05:25.827Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Use Docker for Cloudflare Pages and Workers development]]></title>
            <link>https://medium.com/serverlessciso/use-docker-for-cloudflare-pages-and-workers-development-d0fa5acbb260?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/d0fa5acbb260</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:13:16 GMT</pubDate>
            <atom:updated>2022-11-19T16:10:57.078Z</atom:updated>
            <content:encoded><![CDATA[<h4>Improve local dev while protecting your system</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*mFMmWADcU8pAEkJYGEgQyg.png" /><figcaption>Example of how to do local development with Docker</figcaption></figure><p>About a couple of years ago, Cloudflare launched a new type of serverless offering. Their serverless solution allows us to deploy serverless functions at the edge and to host serverless websites served by a fast content delivery network (CDN).</p><h3>What is serverless computing?</h3><p>In short, serverless computing is a way to deploy code and solutions without managing a server. It is slightly different than a virtual machine (VM) in the cloud. Cloud VMs allow us to log into the server, whereas a serverless solution does not give us access to the server. Some serverless solutions use containers. (Containers are super small virtual machines that run the smallest operating system. Docker is an example of how we can run containers.) Other solutions run the code in isolated processes. The Cloudflare approach uses this approach.</p><h3>What is the Cloudflare serverless solution?</h3><p>Cloudflare launched their <a href="https://workers.cloudflare.com/">Workers</a> platform that runs JavaScript at their edge network data centers. The JavaScript code runs in isolated runtime processes. Rather than creating and destroying containers, their approach runs the code in isolation from the other code. This improves execution time and reduces the time to start the process execution. (This is called cold start time, which includes the time to create the container and wait for it to run the code.) And since the code runs at the edge, the network latency times are shortened.</p><p>In addition to the Workers solution, they launched the <a href="https://pages.cloudflare.com/">Pages</a> platform that runs a serverless website. We can use HTML files or a single-page application (SPA) like Vue.js or React.js to run our website. We can <a href="https://medium.com/geekculture/launch-a-free-website-in-4-steps-ef02533fe419">deploy a website</a> without ever needing to manage a web server.</p><p>Both of these together allow us to create an SPA with its application programming interface (SPA), all running within Cloudflare and a deployed from a single git repository.</p><h3>How to develop locally?</h3><p><a href="https://vuejs.org/">Vue.js</a>, <a href="https://reactjs.org/">React.js</a>, and other SPA frameworks allow us to run local servers before we deploy the final code to a web server or a serverless website. I will assume that we know how to do this or that we can read their developer docs to learn how.</p><p>Cloudflare has a <a href="https://developers.cloudflare.com/workers/wrangler/">Wrangler</a> tool that allows us to develop Pages and Workers locally. We can test our build SPA (i.e., the code that is final code ready to go to the serverless website) and our Workers JavaScript functions.</p><p>SPA and Cloudflare local dev approaches assume we are installing everything on our machine. I prefer to <a href="https://betterprogramming.pub/stop-installing-node-js-and-global-npm-packages-use-docker-instead-42597990db13">develop in Docker containers</a> to improve my cybersecurity and provide a consistent development environment to my development teams.</p><p>The rest of this post will share how my development environment uses Docker containers with <a href="https://docs.docker.com/compose/">Docker Compose</a> and allows me to develop a <a href="https://vuejs.org/">Vue.js</a> website and an API powered by Cloudflare Workers.</p><h3>How do I set up Docker on my machine?</h3><p>Follow the instructions in the “<a href="https://betterprogramming.pub/stop-installing-node-js-and-global-npm-packages-use-docker-instead-42597990db13">Stop Installing Node.js and Global Npm Packages, Use Docker Instead</a>” to get set up.</p><h3>How do we set up the project?</h3><p>We are going to use a monorepo project. We will have two directories at the top-level: functions and vuejs directories.</p><pre># native terminal A<br>$ mkdir functions<br>$ mkdir vuejs</pre><h3>How to set up a Vue.js local dev server with Docker?</h3><p>We create a docker-compose.yml file in the top-level directory with the following.</p><pre># docker-compose.yml<br>version: &#39;3&#39;<br>services:<br>  web:<br>    # runs the web server<br>    # docker compose run --rm --service-ports web<br>    # docker compose run --rm --service-ports web bash<br>    image: &#39;circleci/node:16-bullseye&#39;<br>    user: &#39;circleci&#39;<br>    working_dir: &#39;/home/web/vuejs&#39;<br>    environment:<br>      - &#39;NODE_ENV=development&#39;<br>    volumes:<br>      - &#39;./:/home/web&#39;<br>    ports:<br>      - &#39;8080:8080&#39;<br>    # runs the web server and exposes the 8080 port<br>    command: &#39;npm run dev -- --host&#39;</pre><p>This configuration will allow us to run a container named web that hosts the Vue.js local web server. We are using <a href="https://vitejs.dev/">Vite.js</a> as the local web server that runs the local web server.</p><p>We start the web container and get a bash terminal:</p><pre>docker compose run --rm --service-ports web bash</pre><p>The --rm flag destroys the container after closing it, and the --service-ports flag exposes the web server 8080 port to our machine. The web parameter starts that container, and the bash parameter tells it to run bash.</p><pre># web container&#39;s terminal<br>circleci@a1b2c3d4e5f6:/home/web$ <br># set up your vue application as needed</pre><p>We start the web container in another terminal window:</p><pre># native terminal B<br>docker compose run --rm --service-ports web</pre><p>We now have a local web server that we can visit http://localhost:8080 and use it to preview our website.</p><p><em>Note: We may want to change the </em><em>web name to </em><em>vuejs if that helps us keep track of the container names.</em></p><h3>How to set up Cloudflare Pages functions with Docker?</h3><p>We add the following code to our docker-compose.yml file right after the previous code.</p><pre># docker-compose.yml<br>services:<br>  web:<br>    # omitted for readability<br>  wrangler:<br>    # run CloudFlare Pages functions using wrangler<br>    # docker compose run --rm --service-ports wrangler<br>    # docker compose run --rm --service-ports wrangler bash<br>    image: &#39;circleci/node:16-bullseye&#39;<br>    user: &#39;circleci&#39;<br>    working_dir: &#39;/home/wrangler&#39;<br>    environment:<br>      - &#39;NODE_ENV=development&#39;<br>    volumes:<br>      - &#39;./:/home/wrangler&#39;<br>    ports:<br>      - &#39;8081:8081&#39; # port for the api<br>      - &#39;8976:8976&#39; # port for wrangler<br>    # serves our build Vue.js app and runs the Workers<br>    command: &#39;npx wrangler pages dev ./vuejs/dist --port 8081&#39;</pre><p>This configuration will allow us to run a container named wrangler that hosts the functions using the Cloudflare wrangler tool.</p><p>We start the web container and get a bash terminal:</p><pre># native terminal C<br>docker compose run --rm --service-ports wrangler bash</pre><p>We use the wrangler container’s terminal to set up our functions.</p><pre># wrangler container&#39;s terminal<br>circleci@a1b2c3d4e5f6:/home/wrangler$ npm init -y<br>circleci@a1b2c3d4e5f6:/home/wrangler$ npm i --save-dev wrangler<br># add TypeScript support<br>circleci@a1b2c3d4e5f6:/home/wrangler$ npm i --save-dev typescript @cloudflare/workers-types @types/node<br># create our functions<br>circleci@a1b2c3d4e5f6:/home/wrangler$ cd functions<br>circleci@a1b2c3d4e5f6:/home/wrangler$ touch tsconfig.json<br>circleci@a1b2c3d4e5f6:/home/wrangler$ mkdir api<br>circleci@a1b2c3d4e5f6:/home/wrangler$ cd api<br>circleci@a1b2c3d4e5f6:/home/wrangler$ touch categories.ts<br>circleci@a1b2c3d4e5f6:/home/wrangler$ touch posts.js</pre><p>The functions/api folder hosts the Pages functions code that powers the API. We need to add the TypeScript config to our functions directory: thefunctions/tsconfig.json file.</p><pre>{<br>  &quot;compilerOptions&quot;: {<br>    &quot;target&quot;: &quot;ES2020&quot;,<br>    &quot;module&quot;: &quot;CommonJS&quot;,<br>    &quot;lib&quot;: [&quot;ES2020&quot;],<br>    &quot;types&quot;: [&quot;@cloudflare/workers-types&quot;],<br>  },<br>  &quot;include&quot;: [&quot;**/*.ts&quot;]<br>}</pre><p>We start the wrangler container in another terminal window:</p><pre># native terminal D<br>docker compose run --rm --service-ports wrangler</pre><p>The wrangler tool is now serving the API at http://localhost:8081 .</p><p><em>Note: If there is an error, you may need to do the next step and try again.</em></p><h3>How do I build my Vue.js app in Docker?</h3><p>We need to build our Vue.js app to run the Workers functions that run in our Pages app. The wrangler assumes we already have a ready-to-deploy SPA when it deploys the functions for that Pages website. As a result, we need a build SPA for local development for the Pages Workers functions.</p><p>We must access the web container’s command line interface to build the app.</p><pre># web container&#39;s terminal<br>circleci@a1b2c3d4e5f6:/home/web$ npm run build</pre><h3>How does my Vue.js app use the Workers API?</h3><p>We will need a different URL depending on whether our app runs on a local web server or is hosted from Cloudflare Pages.</p><p>Since I am using Vite, we can define the API domain by doing the following:</p><pre>const apiDomain = import.meta.env.DEV ? &#39;http://localhost:8081&#39; : &#39;https://mysite.pages.dev&#39;;</pre><p>When our site is in development, it will use the local web server address. Otherwise, it will use the Cloudflare Pages address.</p><p>Now we should add cross-origin resource sharing (CORS) headers to add some API protection.</p><p>Let’s create the first function.</p><pre>/* functions/api/categories.ts */<br>export const onRequestGet: PagesFunction = (context) =&gt; {<br>  console.debug(&#39;context:&#39;, JSON.stringify(context, null, 1));<br>  const { request, env } = context;<br>  const headers = {<br>    &#39;Access-Control-Allow-Origin&#39;: env[&#39;ENV_NAME&#39;] === &#39;development&#39;<br>      ? &#39;http://localhost:8080&#39;<br>      : &#39;https://mysite.pages.dev&#39;,<br>    &#39;Access-Control-Allow-Methods&#39;: &#39;GET&#39;,<br>    &#39;Access-Control-Max-Age&#39;: &#39;86400&#39;,<br>  };<br>  console.debug(&#39;headers:&#39;, headers);<br>  return new Response(JSON.stringify([{<br>    id: 1,<br>    title: &#39;Category 1&#39;,<br>  }]), { headers });<br>}</pre><p>Let’s create the second function.</p><pre>/* functions/api/posts.js */<br>export const onRequestGet = (context) =&gt; {<br>  console.debug(&#39;context:&#39;, JSON.stringify(context, null, 1));<br>  const { request, env } = context;<br>  const headers = {<br>    &#39;Access-Control-Allow-Origin&#39;: env[&#39;ENV_NAME&#39;] === &#39;development&#39;<br>      ? &#39;http://localhost:8080&#39;<br>      : &#39;https://vote.hoahero.org&#39;,<br>    &#39;Access-Control-Allow-Methods&#39;: &#39;GET&#39;,<br>    &#39;Access-Control-Max-Age&#39;: &#39;86400&#39;,<br>  };<br>  console.debug(&#39;headers:&#39;, headers);<br>  return new Response(JSON.stringify([{<br>    id: 1,<br>    title: &#39;Post 1&#39;,<br>  }]), { headers });<br>}</pre><p>We can now use these APIs in our Vue.js app. For simplicity, I will add it to the top-level App.vue file.</p><pre>&lt;!-- App.vue --&gt;<br>&lt;script setup lang=&quot;ts&quot;&gt;<br>  import { onBeforeMount, onMounted } from &#39;vue&#39;;<br>  /* the environment variable comes from Vite */<br>  const apiDomain = import.meta.env.DEV ? <br>    &#39;http://localhost:8081&#39;<br>    : &#39;https://mysite.pages.dev&#39;;<br>  onBeforeMount(async () =&gt; {<br>    const categories = await (<br>      await fetch(`${apiDomain}/api/categories`)<br>    ).json();<br>    const posts = await (<br>      await fetch(`${apiDomain}/api/posts`)<br>    ).json();<br>  })<br>&lt;/script&gt;<br>&lt;template&gt;<br>  &lt;div&gt;&lt;/div&gt;<br>&lt;/template&gt;<br>&lt;style scoped&gt;<br>&lt;/style&gt;</pre><h3>Conclusion</h3><p>We can use Docker Compose to run containers that will allow us to develop a Vue.js (or other SPA) in one container and develop the Cloudflare Pages functions in another container.</p><h4>Before you go</h4><p>These are other articles you might enjoy:</p><ul><li><a href="https://medium.com/geekculture/launch-a-free-website-in-4-steps-ef02533fe419">Launch a free website in 4 steps</a></li><li><a href="https://betterprogramming.pub/stop-installing-node-js-and-global-npm-packages-use-docker-instead-42597990db13">Stop Installing Node.js and Global Npm Packages, Use Docker Instead</a></li><li><a href="https://aws.plainenglish.io/how-i-caused-an-amazon-api-gateway-denial-of-service-cba93810e18f">How I Caused an Amazon API Gateway Denial of Service</a></li><li><a href="https://medium.com/nerd-for-tech/create-a-serverless-website-on-aws-with-serverless-plugins-7b614f8253eb">Create a website on AWS with Serverless Framework plugins</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0fa5acbb260" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/use-docker-for-cloudflare-pages-and-workers-development-d0fa5acbb260">Use Docker for Cloudflare Pages and Workers development</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Launch a free website in 4 steps]]></title>
            <link>https://medium.com/serverlessciso/launch-a-free-website-in-4-steps-ef02533fe419?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/ef02533fe419</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[marketing]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[serverless]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:12:42 GMT</pubDate>
            <atom:updated>2022-10-27T17:29:18.945Z</atom:updated>
            <content:encoded><![CDATA[<h4>Focus more on your mission and less on website hosting</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*baN3JpvL5Ws998OF" /><figcaption>Photo by <a href="https://unsplash.com/@domenicoloia?utm_source=medium&amp;utm_medium=referral">Domenico Loia</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Serverless or JAMstack websites allow small businesses, side hustles, and startups to launch no-to-low-cost websites with some elbow grease. Here are some steps I used to launch a free website for a non-profit startup.</p><h3>Download a free or low-cost website theme</h3><p>Wix, EditorX, and other website builder services are nice, but they are expensive. Why pay for a service when the website is updated infrequently? You can achieve the same outcome by downloading a website theme.</p><p>I used <a href="https://bootstrapmade.com/">bootstrapmade.com</a> to download a free website theme built with Bootstrap. I like using Bootstrap for websites because they are responsive. These sites will adjust the layout depending on the screen size. The website will be mobile and tablet friendly from the get-go.</p><h3>Modify the theme</h3><p>Knowing some basic HTML and CSS will help with modifying the site. You can just update the text that is already there. Knowing HTML and CSS will allow you to make simple edits like readjusting the layout, changing the colors, and updating links and images.</p><p>You can learn HTML and CSS for free from <a href="https://www.w3schools.com/">w3schools.com</a>.</p><p>I used the <a href="https://bootstrapmade.com/flexstart-bootstrap-startup-template/">FlexStart</a> template and modified it as needed.</p><h3>Sign up for GitHub and create a private repository</h3><p><a href="https://github.com/">GitHub</a> is a free git-based source control repository service. They will host your website code. All the files you just modified can be saved and maintained in the GitHub repository.</p><p>Sign up for an account on GitHub.com, create a repository for your website, download the GitHub Desktop app, and clone the repository using GitHub Desktop.</p><p>I create a private repository since my code is not open source.</p><p>Here are some YouTube videos that might help.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fw3jLJU7DT5E%3Fstart%3D4%26feature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dw3jLJU7DT5E&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fw3jLJU7DT5E%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/38eb014e6d58270fb511b0135bd53bbb/href">https://medium.com/media/38eb014e6d58270fb511b0135bd53bbb/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FdJUwAEBWKfE&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdJUwAEBWKfE&amp;image=http%3A%2F%2Fi.ytimg.com%2Fvi%2FdJUwAEBWKfE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/3731ce459b18126133fc3563950a3e9b/href">https://medium.com/media/3731ce459b18126133fc3563950a3e9b/href</a></iframe><h3>Sign up for a serverless, static website provider</h3><p>You can use <a href="https://pages.github.com/">GitHub Pages</a>, <a href="https://pages.cloudflare.com/">Cloudflare Pages</a>, or a similar service to host your website by linking your GitHub repository. When you link the repository, both providers will automatically update your website when you make an update to the repository.</p><p>I used Cloudflare Pages because the website will be protected by Cloudflare security features.</p><p>Here are some YouTube videos that might help.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FWqOXxoGSpbs%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DWqOXxoGSpbs&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FWqOXxoGSpbs%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a2a44b35ddb6433def26d276e829dc2/href">https://medium.com/media/9a2a44b35ddb6433def26d276e829dc2/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FMTc2CTYoszY%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DMTc2CTYoszY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FMTc2CTYoszY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/4e7bebe923011a7da549fba0cf2d51ae/href">https://medium.com/media/4e7bebe923011a7da549fba0cf2d51ae/href</a></iframe><h3>Conclusion</h3><p>I explained how you could deploy a simple website in four steps. Instead of paying money to host your simple website, you can use services like Cloudflare Pages to host the website. You can use the money you saved to promote your project or startup.</p><p>I spent $0 on the website theme, GitHub repository, and Cloudflare Pages website. It took me about 3–4 hours to modify the theme to my liking and less than 30 minutes to get it up and running in Cloudflare Pages. I paid for a custom domain for about $12. Whenever I update the website code in GitHub, the changes are live in Cloudflare Pages in less than one minute.</p><h3>Before you go</h3><p>These are other articles you might enjoy:</p><ul><li><a href="https://miguelacallesmba.medium.com/be-careful-when-using-env-files-be2e67db0248">Be careful when using .env files</a></li><li><a href="https://medium.com/nerd-for-tech/create-a-serverless-website-on-aws-with-serverless-plugins-7b614f8253eb">Create a website on AWS with Serverless Framework plugins</a></li><li><a href="https://medium.com/nerd-for-tech/earn-passive-income-by-browsing-the-web-62d7a75bb9d">Earn passive income by browsing the web</a></li><li><a href="https://medium.com/stronger-content/advance-your-career-by-avoiding-these-ten-mistakes-3a79c092bb7">Advance your career by avoiding these ten mistakes</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ef02533fe419" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/launch-a-free-website-in-4-steps-ef02533fe419">Launch a free website in 4 steps</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Caused an Amazon API Gateway Denial of Service]]></title>
            <link>https://medium.com/serverlessciso/how-i-caused-an-amazon-api-gateway-denial-of-service-cba93810e18f?source=rss----8c43e619bad9---4</link>
            <guid isPermaLink="false">https://medium.com/p/cba93810e18f</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[amazon-web-services]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <dc:creator><![CDATA[Miguel A. Calles]]></dc:creator>
            <pubDate>Sun, 22 Dec 2024 16:11:53 GMT</pubDate>
            <atom:updated>2023-06-01T13:33:15.987Z</atom:updated>
            <content:encoded><![CDATA[<h4>The DoS attack was caused by a Lambda function</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/772/1*R0mhVw97EDCMX4gc31rXQA.png" /><figcaption>How the denial of service happened with the AWS services</figcaption></figure><p>In a former project, I worked within a serverless architecture running on Amazon Web Services. We used Lambda to run our function code, DynamoDB to host our database tables, and API Gateway to provide the application programming interface. The API Gateway provided an endpoint URI which redirected the HTTP payload to a Lambda function. The Lambda function made a query to a DynamoDB table to get data, and it responded to the API Gateway with that data. Finally, the API Gateway sent that data to the client.</p><p>We had an idea to optimize this process. The majority of the time, the data responded with the same content. That means we were calling the DynamoDB table to get the same data almost every time. We decided caching could reduce the impact on our functions and tables.</p><p>We enabled API Gateway caching so the API Gateway would send cached data. API Gateway would not send a request to the Lambda function but sent cached data instead. It seemed like a good idea at first.</p><p>We later noticed the API Gateway continued to serve cached data until the cache expired even after updating the data in the DynamoDB table. This was problematic because we wanted to serve the new data.</p><p>We decided to solve this by implementing a Lambda function that subscribed to DynamoDB table streams. The streams sent events when the DynamoDB table had write/delete/update activity. Whenever the second Lambda function received a DynamoDB stream event, it would make an AWS SDK API call to the API Gateway to clear the cache.</p><p>Again, it seemed like a good idea until we found unexpected behavior. The DynamoDB streams started sending old events in batches. The second Lambda function received multiple, outdated stream events. Each event resulted in a clear-cache request to the API Gateway. In time, the API Gateway started rate limiting the AWS SDK API calls.</p><p>While the AWS SDK API calls were rate limited, the performance of the API endpoints was also affected. The endpoints stopped responding to HTTP requests! It seemed the API Gateway experienced an internal Denial of Service attack.</p><p>Sometimes, what seems like a good design could have adverse effects. When working with event-driven architectures and serverless architectures, it is good to assess what might happen when the non-ideal occurs. In this story, DynamoDB streams should have only sent new events that happened infrequently, but it started sending old events that were no longer relevant.</p><p>A code review might have caught this issue had we considered all the negative-path scenarios (i.e., non-ideal or malicious inputs). The Lambda function should have done input validation to only act on an event that was X minutes old, came from the correct table, and had the proper action (e.g., update).</p><p>An architecture review could have caught the issue had we explicitly defined when the DynamoDB table was updated and when the API Gateway cache should be cleared. In this case, the table was only updated in the CI/CD deployment pipeline. Having the CI/CD pipeline make the AWS SDK API call to clear the API Gateway cache would have been more appropriate.</p><h3>Conclusion</h3><p>I hope this story highlighted how a well-meaning design could result in an undesired outcome. In this example, an internal Lambda function made excessive calls to the AWS SDK API, resulting in a Denial of Service attack on the API Gateway. We might avoid these types of situations by analyzing the architecture, doing a thorough code review, and brainstorming negative-path scenarios.</p><p>I shared this lesson in the <a href="https://serverlesssecuritybook.com">Serverless Security book</a> and the <a href="https://www.youtube.com/watch?v=E8YEUkbL7NY">OWASP 20th Anniversary event</a>.</p><p><a href="https://serverlesssecuritybook.com">What is Serverless Security on AWS, Azure and Google Cloud?</a></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FE8YEUkbL7NY%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DE8YEUkbL7NY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FE8YEUkbL7NY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/043940b37da4f868041c03485898db8f/href">https://medium.com/media/043940b37da4f868041c03485898db8f/href</a></iframe><h4>Before you go</h4><p>These are other articles you might enjoy:</p><ul><li><a href="https://medium.com/chapter-by-chapter/aws-cdk-serverless-cookbook-ebook-1d4d4e0488c">AWS CDK Serverless Cookbook</a></li><li><a href="https://medium.com/nerd-for-tech/create-a-serverless-website-on-aws-with-serverless-plugins-7b614f8253eb">Create a website on AWS with Serverless Framework plugins</a></li><li><a href="https://miguelacallesmba.medium.com/if-you-build-it-you-should-break-it-25e06f2d53b6">If you build it, you should break it.</a></li><li><a href="https://javascript.plainenglish.io/when-to-use-and-in-javascript-and-typescript-74533943d5f9">When to use ?? and || in JavaScript and TypeScript</a></li><li><a href="https://medium.com/geekculture/five-scary-linux-commands-you-should-not-run-4222773188bb">Five scary Linux commands you should not run</a></li></ul><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a><em>, and </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><em>. Interested in Growth Hacking? Check out </em><a href="https://circuit.ooo/"><strong><em>Circuit</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cba93810e18f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/serverlessciso/how-i-caused-an-amazon-api-gateway-denial-of-service-cba93810e18f">How I Caused an Amazon API Gateway Denial of Service</a> was originally published in <a href="https://medium.com/serverlessciso">Serverless CISO</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>