<?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>DEV Community: Alonso Suarez</title>
    <description>The latest articles on DEV Community by Alonso Suarez (@alonch).</description>
    <link>https://dev.to/alonch</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%2F1556708%2Fa1a39fa8-3c51-4a42-ad93-4c105e8d3bd4.jpg</url>
      <title>DEV Community: Alonso Suarez</title>
      <link>https://dev.to/alonch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alonch"/>
    <language>en</language>
    <item>
      <title>This is THE simplest way to create a serverless HTTP App</title>
      <dc:creator>Alonso Suarez</dc:creator>
      <pubDate>Wed, 03 Jul 2024 06:04:38 +0000</pubDate>
      <link>https://dev.to/aws-builders/this-is-the-simplest-way-to-create-a-serverless-http-app-4211</link>
      <guid>https://dev.to/aws-builders/this-is-the-simplest-way-to-create-a-serverless-http-app-4211</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Let’s provision a new HTTP server:&lt;/li&gt;
&lt;li&gt;Create a new Github Repo&lt;/li&gt;
&lt;li&gt;Add a workflow on push
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/on-push-main.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demo&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&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="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="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&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;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.backend.outputs.url }}&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check out repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ROLE_ARN }}&lt;/span&gt;
          &lt;span class="na"&gt;role-session-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.actor }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alonch/actions-aws-backend-setup@main&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
          &lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sample&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alonch/actions-aws-http-node@main&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions-aws-http-node-sample&lt;/span&gt;
          &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src&lt;/span&gt;
          &lt;span class="na"&gt;allow-public-access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;- entrypoint-file: plus&lt;/span&gt;
              &lt;span class="s"&gt;entrypoint-function: handler&lt;/span&gt;
              &lt;span class="s"&gt;path: "/plus/{z}"&lt;/span&gt;
              &lt;span class="s"&gt;method: post&lt;/span&gt;
              &lt;span class="s"&gt;parameters:&lt;/span&gt;
                &lt;span class="s"&gt;path:&lt;/span&gt;
                &lt;span class="s"&gt;- name: z&lt;/span&gt;
                  &lt;span class="s"&gt;type: number&lt;/span&gt;
                &lt;span class="s"&gt;query:&lt;/span&gt;
                &lt;span class="s"&gt;- name: x&lt;/span&gt;
                  &lt;span class="s"&gt;type: number&lt;/span&gt;
                &lt;span class="s"&gt;body: &lt;/span&gt;
                &lt;span class="s"&gt;- name: y&lt;/span&gt;
                  &lt;span class="s"&gt;type: number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create function handler
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/plus.js&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&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="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parameters&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;status&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;y&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;ul&gt;
&lt;li&gt;Add AWS ROLE_ARN repo secret&lt;/li&gt;
&lt;li&gt;Git push changes to Github&lt;/li&gt;
&lt;li&gt;Navigate to Github Actions Tab, less than a minute later, the api-docs will be generated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuov9f4avkdqsfk5fjzh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuov9f4avkdqsfk5fjzh5.png" alt="Screenshot of Github Actions Tab" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgknfwl4n4n1vpe5a0dmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgknfwl4n4n1vpe5a0dmo.png" alt="Screenshot of Swagger" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But wait there is more, clients sending invalid payload will get 400 status code with the following payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'https://riga7yssypqgxndyz3xigmzsxy0jkhip.lambda-url.us-east-1.on.aws/plus/2?x=1'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{ }'&lt;/span&gt;  &lt;span class="c"&gt;# &amp;lt;-- Invalid body  &lt;/span&gt;

&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"in"&lt;/span&gt;:[&lt;span class="s2"&gt;"request"&lt;/span&gt;,&lt;span class="s2"&gt;"body-params"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;"coercion"&lt;/span&gt;:&lt;span class="s2"&gt;"malli"&lt;/span&gt;,&lt;span class="s2"&gt;"type"&lt;/span&gt;:&lt;span class="s2"&gt;"request-coercion"&lt;/span&gt;,&lt;span class="s2"&gt;"value"&lt;/span&gt;:&lt;span class="o"&gt;{}&lt;/span&gt;,&lt;span class="s2"&gt;"humanized"&lt;/span&gt;:&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"y"&lt;/span&gt;:[&lt;span class="s2"&gt;"missing required key"&lt;/span&gt;&lt;span class="o"&gt;]}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code available on &lt;a href="https://github.com/alonch/actions-aws-http-node-sample"&gt;this&lt;/a&gt; sample repo and the full documentation &lt;a href="https://github.com/alonch/actions-aws-http-node"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>javascript</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Infra as GitHub Actions - AWS Serverless Function for nodejs</title>
      <dc:creator>Alonso Suarez</dc:creator>
      <pubDate>Thu, 13 Jun 2024 04:27:34 +0000</pubDate>
      <link>https://dev.to/aws-builders/infra-as-github-actions-aws-serverless-function-for-nodejs-25j2</link>
      <guid>https://dev.to/aws-builders/infra-as-github-actions-aws-serverless-function-for-nodejs-25j2</guid>
      <description>&lt;p&gt;In the last &lt;a href="https://dev.to/aws-builders/provisioning-aws-solutions-in-minutes-with-infra-as-github-actions-c25"&gt;post&lt;/a&gt; we talked about the need to simplify infra while also moving it back to the application repo&lt;/p&gt;

&lt;p&gt;As I started to work on the next infra as GitHub actions, which was a secured website with &lt;code&gt;authentication@edge&lt;/code&gt;. It became clear that AWS lambda was a fundamental building block in the journey&lt;/p&gt;

&lt;p&gt;Introducing &lt;a href="https://github.com/alonch/actions-aws-function-node"&gt;actions-aws-function-node&lt;/a&gt; 🎉&lt;br&gt;
Now with very few dependencies, you can provision your node backend in literally a minute 🏎️&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Let's start with familiar code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/index.js&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;statusCode&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;headers&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello world&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the workflow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .github/workflows/on-push-main.yml
name: demo
on:
  push:
    branches:
      - main
jobs:
  deploy:
    environment:
      name: main
      url: ${{ steps.backend.outputs.url }}
    permissions: 
      id-token: write
    runs-on: ubuntu-latest
    steps:
      - name: Check out repo
        uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: us-east-1
          role-to-assume: ${{ secrets.ROLE_ARN }}
          role-session-name: ${{ github.actor }}
      - uses: alonch/actions-aws-backend-setup@main
        with: 
          instance: sample
      - uses: alonch/actions-aws-function-node@main
        with: 
          name: actions-aws-function-node-sample
          entrypoint-file: index.js
          entrypoint-function: handler
          artifacts: src
          allow-public-access: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the secret &lt;code&gt;ROLE_ARN&lt;/code&gt; with access to AWS and that's it, after pushing to main you have a GitHub deployment with you backend running 🎉&lt;br&gt;
You can clone this &lt;a href="https://github.com/alonch/actions-aws-function-node-sample"&gt;sample&lt;/a&gt; from Github too&lt;br&gt;
Of course, there are a lot more options &lt;/p&gt;
&lt;h2&gt;
  
  
  Permissions
&lt;/h2&gt;

&lt;p&gt;You can allow access to services by just adding the resource name and the access, either read or write&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      - uses: alonch/actions-aws-function-node@main
        with: 
          name: actions-aws-function-node-demo
          entrypoint-file: index.js
          entrypoint-function: handler
          artifacts: src
          allow-public-access: true
          permissions: |
            s3: read
            dynamodb: write 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration will attach AmazonS3ReadOnly and AmazonDynamoDBFullAccess managed policies to the function's role&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Variables
&lt;/h2&gt;

&lt;p&gt;Similar to permissions, you can attach function variables as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      - uses: alonch/actions-aws-function-node@main
        with: 
          name: actions-aws-function-node-demo
          entrypoint-file: index.js
          entrypoint-function: handler
          artifacts: src
          allow-public-access: true
          env: |
            DD_ENV: production 
            DD_SERVICE: demo
            DD_VERSION: ${{ github.sha }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the options are standard attributes like memory, timeout or selecting ARM architecture&lt;/p&gt;

&lt;p&gt;The best part is that it takes a minute to provision it and even less time to destroy 👏&lt;/p&gt;

&lt;p&gt;I’m excited about the future developments and improvements that can be made to this workflow. If you have any feedback, questions, or suggestions, feel free to leave a comment below or reach out directly. Let’s continue this journey of simplifying infrastructure together!&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>aws</category>
      <category>githubactions</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Next Generation SQL Injection: Github Actions Edition</title>
      <dc:creator>Alonso Suarez</dc:creator>
      <pubDate>Fri, 07 Jun 2024 20:16:53 +0000</pubDate>
      <link>https://dev.to/aws-builders/next-generation-sql-injection-github-actions-edition-36a4</link>
      <guid>https://dev.to/aws-builders/next-generation-sql-injection-github-actions-edition-36a4</guid>
      <description>&lt;p&gt;In the evolving landscape of software development, Continuous Integration and Continuous Deployment (CI/CD) tools like GitHub Actions have become indispensable. However, with great power comes great responsibility, and it's crucial to be aware of potential security pitfalls. One such vulnerability is treating untrusted inputs, such as branch names or pull request (PR) titles, as static parameters.&lt;br&gt;
Spoiler alert, &lt;strong&gt;they should NOT be trusted&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I enjoy puzzles, so here goes one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
  - name: Generate summary
    run: |
      echo "Pull Request for [${{ github.event.pull_request.title }}](https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}) has been updated 🎉" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
      echo "Image tagged **v${{ needs.determine_app_version.outputs.app_version }}** has been built and pushed to the registry." &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
This will generate a workflow summary like:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you spot the vulnerability?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When a developer clicks on the Revert PR button in GitHub, the new PR title is &lt;code&gt;Revert "&amp;lt;OLD TITLE&amp;gt;"&lt;/code&gt;. This breaks the Generate summary step.&lt;/p&gt;

&lt;p&gt;Try again if you haven’t spotted the vulnerability&lt;/p&gt;

&lt;p&gt;The vulnerability lies in how &lt;code&gt;github.event.pull_request.title&lt;/code&gt; input is handled. &lt;strong&gt;GitHub Actions expressions dynamically generate code&lt;/strong&gt;. Unfortunately, if the PR title contains any special characters or unexpected input, it can cause the script to fail or behave unexpectedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Impact
&lt;/h2&gt;

&lt;p&gt;When developers click on Revert PR button, the PR title is &lt;code&gt;Revert "&amp;lt;OLD TITLE&amp;gt;"&lt;/code&gt;, the echo command in the Generate summary step generates the bash command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Pull Request for [Revert "&amp;lt;OLD TITLE&amp;gt;"](https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}) has been updated 🎉" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The presence of the double quotes within the PR title closes the echo early. However, this allows for bad actors to craft a title that could be used take full control of the runner&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;To prevent this issue, one approach is to use env as an input “encoder” and avoid directly using GitHub Actions &lt;code&gt;${{ }}&lt;/code&gt; expressions. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env:
  TITLE: ${{ github.event.pull_request.title }}
steps:
  - name: Generate summary
    run: |
      echo "Pull Request for [$TITLE](https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}) has been updated 🎉" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the &lt;code&gt;env&lt;/code&gt; context to store untrusted inputs, you avoid potential script-breaking issues caused by special characters pre-rendered by Github Actions.&lt;/p&gt;

&lt;p&gt;Leave a comment if you can think on a different way to solve this problem!&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Provisioning AWS solutions in minutes with Infra as Github Actions</title>
      <dc:creator>Alonso Suarez</dc:creator>
      <pubDate>Fri, 31 May 2024 21:40:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/provisioning-aws-solutions-in-minutes-with-infra-as-github-actions-c25</link>
      <guid>https://dev.to/aws-builders/provisioning-aws-solutions-in-minutes-with-infra-as-github-actions-c25</guid>
      <description>&lt;p&gt;I remember those days when I created infra by clicking in the console 😬 eventually that became a nightmare to manage and infra as code came to save the day 🦸 but with that, it also started an awkward phase of coupling infra code and app code&lt;br&gt;
Some platform teams decided to move infra code to their own repos, that worked, specially for access control, but that required exceptions like: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ignoring the image version since it was going to be managed by the app pipeline &lt;/li&gt;
&lt;li&gt;The awkward environment variables setup &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've been searching for ways to bring infra back infra code to app repos&lt;/p&gt;

&lt;p&gt;The first experiment was to keep network and LBs and move ECS services with Fargate to the app repo, this continuous to work surprisingly well after 3 years, environment variables changes are in the same PR as app that depended on it, another advantage was that terraform itself managed the newly built docker image tag. However, app developers rarely touched most of the terraform code, as terraform requires significant effort to learn, there has to be a better way 🤔 &lt;/p&gt;
&lt;h2&gt;
  
  
  Entering Infra as GitHub Actions
&lt;/h2&gt;

&lt;p&gt;With just a few line of YML, we can create pretty complex depended workflows, what if we can use Github Actions to compose infra? &lt;/p&gt;

&lt;p&gt;I write a couple of actions that will provision the S3, CloudFront and Route53 with fairly simple steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login to AWS&lt;/li&gt;
&lt;li&gt;Setup the Backend &lt;/li&gt;
&lt;li&gt;Provision the website&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole workflow relies on only 3 inputs- Instance name: an identifier for the infra- Domain: DNS for the website, you need to own it on Route53- Path: content to publish as root on the website&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;permissions: 
  id-token: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repo
        uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: us-east-1
          role-to-assume: ${{ secrets.ROLE_ARN }}
          role-session-name: ${{ github.actor }}
      - uses: alonch/actions-aws-backend-setup@main
        with: 
          instance: demo
      - uses: alonch/actions-aws-website@main
        with: 
          domain: ${{ env.DOMAIN }}
          content-path: public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;When a GitHub Action job is initialized, it checks out its source code from the repo, this unlocks interesting capabilities, for example: an action could apply terraform as if the terraform code is part of the current repo &lt;/p&gt;

&lt;h3&gt;
  
  
  actions-aws-backend-setup (&lt;a href="https://github.com/alonch/actions-aws-backend-setup"&gt;repo&lt;/a&gt;)
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - uses: alonch/actions-aws-backend-setup@main
    with: 
      instance: demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This action requires a custom instance name to query AWS by tag, we need to find the S3 and Dynamodb to setup the terraform backend &lt;/p&gt;

&lt;p&gt;In case where it doesn’t exist, it will provision it and setup the environment variables: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TF_BACKEND_s3&lt;/strong&gt;: bucket name&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TF_BACKEND_dynamodb&lt;/strong&gt;: table name&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  actions-aws-website (&lt;a href="https://github.com/alonch/actions-aws-website"&gt;repo&lt;/a&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      - uses: alonch/actions-aws-website@main
        with: 
          domain: ${{ env.DOMAIN }}
          content-path: public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This action assumes the backend setup has run, and it requires a domain and the path to the content that needs to be publish as the website &lt;br&gt;
Similar to the backend action, GitHub checks the source code which includes the terraform code to provision a Bucket, Cloudfront, Certificate and route53 routes&lt;br&gt;
Using Github Actions is incredible flexible as the only dependency is on the AWS role and the backend instance name, in the case were we need to upgrade the infra, we just need to tag the new action version and terraform will sync the resources to the latest desired state&lt;/p&gt;
&lt;h2&gt;
  
  
  New degree of freedom
&lt;/h2&gt;

&lt;p&gt;With Infra as Github Actions we basically can achieve ephemeral environments with a 31 lines of YML&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy Ephemeral Environment
on:
  pull_request:
    types: [opened, synchronize, reopened, closed]
env: 
  DOMAIN: ${{github.head_ref}}.test.realsense.ca
permissions: 
  id-token: write
jobs:
  deploy:
    environment:
      url: "https://${{ env.DOMAIN }}"
      name: ${{github.head_ref}}
    runs-on: ubuntu-latest
    steps:
      - name: Check out repo
        uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: us-east-1
          role-to-assume: ${{ secrets.ROLE_ARN }}
          role-session-name: ${{ github.actor }}
      - uses: alonch/actions-aws-backend-setup@main
        with: 
          instance: demo
      - uses: alonch/actions-aws-website@main
        with: 
          domain: ${{ env.DOMAIN }}
          content-path: public
          # destroy when PR closed
          action: ${{github.event.action == 'closed' &amp;amp;&amp;amp; 'destroy' || 'apply'}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new infra for that PR, update it in sync and destroy it when the PR is closed&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;This is just the beginning, I believe GitHub actions dependency could be use to compose and orchestre complex infra with simple interfaces&lt;br&gt;
I'm considering building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;actions-aws-http-lambda&lt;/strong&gt;: Serverless API from folder path&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;actions-aws-edge-auth&lt;/strong&gt;: Website behind social media login from client secrets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;actions-aws-http-server&lt;/strong&gt;: Web hosting from docker image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What do you think? What should I focus on next?&lt;/p&gt;

</description>
      <category>aws</category>
      <category>githubactions</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
