<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sri</title>
    <description>The latest articles on Forem by Sri (@kasukur).</description>
    <link>https://forem.com/kasukur</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%2F643937%2Fcd8d3f00-3a1b-4ac1-89cc-6b50a2e021de.JPG</url>
      <title>Forem: Sri</title>
      <link>https://forem.com/kasukur</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kasukur"/>
    <language>en</language>
    <item>
      <title>Building Secure Jenkins-Slack Integration with AWS Lambda - Part 2: Troubleshooting Real-World Issues</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Tue, 14 Oct 2025 11:08:28 +0000</pubDate>
      <link>https://forem.com/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-2-troubleshooting-real-world-429d</link>
      <guid>https://forem.com/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-2-troubleshooting-real-world-429d</guid>
      <description>&lt;p&gt;Welcome back! In &lt;a href="https://dev.to/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-1-complete-setup-guide-lgd"&gt;Part 1&lt;/a&gt;, we built the foundation of our secure Jenkins-Slack integration. Now it's time to tackle the real-world challenges that make or break production deployments.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;Part 2&lt;/strong&gt; of our series, where we'll dive deep into troubleshooting common issues, implementing critical fixes, and adding production-ready enhancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality Check
&lt;/h2&gt;

&lt;p&gt;After deploying the initial setup from Part 1, you'll likely encounter several roadblocks. Based on real-world experience, here are the most common issues and their battle-tested solutions:&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 Critical Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Jenkins Authentication Failure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Jenkins login with admin/ not working&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Symptoms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jenkins stuck in initial setup mode&lt;/li&gt;
&lt;li&gt;"Invalid username or password" errors&lt;/li&gt;
&lt;li&gt;Cannot access Jenkins dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Jenkins was in initial setup wizard mode, not accepting default credentials&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Complete Jenkins Reset with Programmatic Admin Creation&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="c"&gt;# Create the final-fix.sh script&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; final-fix.sh &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
#!/bin/bash
echo "🚀 Starting Jenkins reset and setup..."

# Stop Jenkins
sudo systemctl stop jenkins
echo "✅ Jenkins stopped"

# Clean existing user files
sudo rm -rf /var/lib/jenkins/users /var/lib/jenkins/init.groovy.d
echo "✅ Cleaned existing user files"

# Create proper admin user script
sudo mkdir -p /var/lib/jenkins/init.groovy.d
sudo tee /var/lib/jenkins/init.groovy.d/create-admin.groovy &amp;gt; /dev/null &amp;lt;&amp;lt; 'GROOVY'
#!/usr/bin/env groovy
import jenkins.model.*
import hudson.security.*

def instance = Jenkins.getInstance()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("admin", "your-secure-password")
instance.setSecurityRealm(hudsonRealm)

def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
strategy.setDenyAnonymousReadAccess(false)
instance.setAuthorizationStrategy(strategy)

instance.setCrumbIssuer(null)  // Disable CSRF
instance.save()
println "Admin user created and CSRF disabled"
GROOVY

sudo chown jenkins:jenkins /var/lib/jenkins/init.groovy.d/create-admin.groovy
echo "✅ Created admin user script"

# Start Jenkins
sudo systemctl start jenkins
echo "✅ Jenkins started"

# Wait for initialization
echo "⏳ Waiting for Jenkins initialization..."
sleep 30

# Test authentication
echo "🧪 Testing authentication..."
curl -u admin:your-secure-password http://localhost:8080/api/json &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
if [ &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="sh"&gt; -eq 0 ]; then
    echo "✅ Authentication successful!"
else
    echo "❌ Authentication failed. Check Jenkins logs."
fi

echo "🎉 Setup complete! Access Jenkins at http://localhost:8080 with admin/your-secure-password"
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x final-fix.sh
./final-fix.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Files Created&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;final-fix.sh&lt;/code&gt; - Complete Jenkins setup script&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create-admin.groovy&lt;/code&gt; - Programmatic admin user creation&lt;/li&gt;
&lt;li&gt;CSRF protection disabled for API access&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue 2: CSRF Token Errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: "403 No valid crumb was included in the request" errors&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Symptoms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda getting 401 Unauthorized for CSRF endpoints&lt;/li&gt;
&lt;li&gt;Jenkins API calls failing with crumb errors&lt;/li&gt;
&lt;li&gt;Authentication works but job triggers fail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Jenkins CSRF protection blocking API calls from Lambda&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Disable CSRF Protection Programmatically&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="c"&gt;# Create CSRF disable script&lt;/span&gt;
&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /var/lib/jenkins/init.groovy.d/disable-csrf.groovy &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
#!/usr/bin/env groovy
import jenkins.model.*
def instance = Jenkins.getInstance()
instance.setCrumbIssuer(null)
instance.save()
println "CSRF protection disabled"
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="nb"&gt;sudo chown &lt;/span&gt;jenkins:jenkins /var/lib/jenkins/init.groovy.d/disable-csrf.groovy
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Works&lt;/strong&gt;: For API-only access scenarios, CSRF protection can be safely disabled since we're using proper authentication and the API is not exposed to browsers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 3: Slack Slash Command dispatch_unknown_error
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: &lt;code&gt;dispatch_unknown_error&lt;/code&gt; when using &lt;code&gt;/run_test&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Symptoms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slack command returns error immediately&lt;/li&gt;
&lt;li&gt;No response from API Gateway&lt;/li&gt;
&lt;li&gt;Lambda function not being invoked&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Slack app not properly installed or missing permissions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Proper Slack App Configuration&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verify App Installation&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://api.slack.com/apps" rel="noopener noreferrer"&gt;https://api.slack.com/apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Select your app → "Install App"&lt;/li&gt;
&lt;li&gt;Ensure it shows "Installed" with green checkmark&lt;/li&gt;
&lt;li&gt;If not installed, click "Install to Workspace"&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check Request URL&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Go to "Slash Commands" → Edit &lt;code&gt;/run_test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Verify URL is exactly: &lt;code&gt;https://your-api-gateway-url/prod/trigger&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No extra spaces or characters&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Test with Webhook&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;# Use webhook.site for testing&lt;/span&gt;
   &lt;span class="c"&gt;# 1. Go to https://webhook.site&lt;/span&gt;
   &lt;span class="c"&gt;# 2. Copy unique URL&lt;/span&gt;
   &lt;span class="c"&gt;# 3. Temporarily update Slack command to use webhook URL&lt;/span&gt;
   &lt;span class="c"&gt;# 4. Test command - should see request in webhook.site&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reinstall App&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Uninstall app from workspace&lt;/li&gt;
&lt;li&gt;Reinstall with proper permissions&lt;/li&gt;
&lt;li&gt;Grant "Send messages" permission&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Issue 4: Lambda Function Evolution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Lambda function needs optimization for Slack integration&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Evolution Path&lt;/strong&gt;: Basic → CSRF-aware → Slack-optimized&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Solution&lt;/strong&gt;: Slack-Optimized Lambda Function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// main_slack_fixed.go - Final optimized version&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"net/url"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/aws/aws-lambda-go/events"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/aws/aws-lambda-go/lambda"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/aws/aws-sdk-go/aws"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/aws/aws-sdk-go/aws/session"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/aws/aws-sdk-go/service/ssm"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SlackRequest&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Text&lt;/span&gt;        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"text"`&lt;/span&gt;
    &lt;span class="n"&gt;UserName&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"user_name"`&lt;/span&gt;
    &lt;span class="n"&gt;ChannelName&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"channel_name"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;JenkinsCredentials&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"username"`&lt;/span&gt;
    &lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"password"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Parse Slack request (handles both JSON and form data)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;slackReq&lt;/span&gt; &lt;span class="n"&gt;SlackRequest&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;slackReq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Handle form data&lt;/span&gt;
        &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;slackReq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;slackReq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user_name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;slackReq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChannelName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"channel_name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Parse parameters from text&lt;/span&gt;
    &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"dev"&lt;/span&gt;
    &lt;span class="n"&gt;testSuite&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"smoke"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;slackReq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slackReq&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;testSuite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Get Jenkins credentials from SSM&lt;/span&gt;
    &lt;span class="n"&gt;sess&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSession&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;ssmClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ssm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;jenkinsURLParam&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"/jenkins-slack-demo/jenkins_url"&lt;/span&gt;
    &lt;span class="n"&gt;jenkinsCredsParam&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"/jenkins-slack-demo/jenkins_credentials"&lt;/span&gt;

    &lt;span class="n"&gt;jenkinsURLResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ssmClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ssm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetParameterInput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jenkinsURLParam&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createErrorResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get Jenkins URL"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;credsResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ssmClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ssm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetParameterInput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jenkinsCredsParam&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;WithDecryption&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createErrorResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get Jenkins credentials"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt; &lt;span class="n"&gt;JenkinsCredentials&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unmarshal&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;credsResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Trigger Jenkins job&lt;/span&gt;
    &lt;span class="n"&gt;jobURL&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s/job/run_test/buildWithParameters"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;jenkinsURLResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ENVIRONMENT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TEST_SUITE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testSuite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jobURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createErrorResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to create request"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetBasicAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createErrorResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to trigger Jenkins job"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Create Slack-compatible response&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;201&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Successfully triggered"&lt;/span&gt;
        &lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"🚀"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Failed to trigger"&lt;/span&gt;
        &lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"❌"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
        &lt;span class="s"&gt;"response_type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"in_channel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s Jenkins job triggered!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;• Environment: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;• Test Suite: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;• Status: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testSuite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createErrorResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
        &lt;span class="s"&gt;"response_type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ephemeral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"❌ "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&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;h2&gt;
  
  
  🛠️ Production Enhancements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security Improvements
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Slack Signature Verification
&lt;/h4&gt;

&lt;p&gt;Add proper Slack request signature validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/hmac"&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/sha256"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/hex"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;verifySlackSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signingSecret&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Remove "v0=" prefix&lt;/span&gt;
    &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"v0="&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create signature base string&lt;/span&gt;
    &lt;span class="n"&gt;sigBasestring&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"v0:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;

    &lt;span class="c"&gt;// Compute HMAC&lt;/span&gt;
    &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signingSecret&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sigBasestring&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;expectedSignature&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expectedSignature&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;h4&gt;
  
  
  2. Enhanced IAM Roles
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# terraform/iam.tf - Enhanced IAM configuration&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"lambda_execution_role"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-lambda-execution-role"&lt;/span&gt;

  &lt;span class="nx"&gt;assume_role_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
    &lt;span class="nx"&gt;Statement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Principal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lambda.amazonaws.com"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role_policy"&lt;/span&gt; &lt;span class="s2"&gt;"lambda_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-lambda-policy"&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lambda_execution_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
    &lt;span class="nx"&gt;Statement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s2"&gt;"logs:CreateLogGroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"logs:PutLogEvents"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nx"&gt;Resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:logs:*:*:*"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s2"&gt;"ssm:GetParameter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"ssm:GetParameters"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nx"&gt;Resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s2"&gt;"arn:aws:ssm:${var.aws_region}:*:parameter/${var.project_name}/*"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
        &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s2"&gt;"ec2:CreateNetworkInterface"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"ec2:DescribeNetworkInterfaces"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"ec2:DeleteNetworkInterface"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nx"&gt;Resource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Monitoring and Observability
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. CloudWatch Alarms
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# terraform/monitoring.tf&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_metric_alarm"&lt;/span&gt; &lt;span class="s2"&gt;"lambda_errors"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-lambda-errors"&lt;/span&gt;
  &lt;span class="nx"&gt;comparison_operator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GreaterThanThreshold"&lt;/span&gt;
  &lt;span class="nx"&gt;evaluation_periods&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt;
  &lt;span class="nx"&gt;metric_name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Errors"&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS/Lambda"&lt;/span&gt;
  &lt;span class="nx"&gt;period&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"300"&lt;/span&gt;
  &lt;span class="nx"&gt;statistic&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Sum"&lt;/span&gt;
  &lt;span class="nx"&gt;threshold&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_description&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Lambda function errors"&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_actions&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;dimensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;FunctionName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_lambda_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkins_trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;function_name&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_metric_alarm"&lt;/span&gt; &lt;span class="s2"&gt;"jenkins_response_time"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-jenkins-response-time"&lt;/span&gt;
  &lt;span class="nx"&gt;comparison_operator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GreaterThanThreshold"&lt;/span&gt;
  &lt;span class="nx"&gt;evaluation_periods&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt;
  &lt;span class="nx"&gt;metric_name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Duration"&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS/Lambda"&lt;/span&gt;
  &lt;span class="nx"&gt;period&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"300"&lt;/span&gt;
  &lt;span class="nx"&gt;statistic&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Average"&lt;/span&gt;
  &lt;span class="nx"&gt;threshold&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10000"&lt;/span&gt;  &lt;span class="c1"&gt;# 10 seconds&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_description&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Jenkins response time too high"&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_actions&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alerts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;dimensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;FunctionName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_lambda_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jenkins_trigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;function_name&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;h4&gt;
  
  
  2. Structured Logging
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LstdFlags&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lshortfile&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LogRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"REQUEST: user=%s channel=%s text=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LogJenkinsTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testSuite&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"JENKINS_TRIGGER: env=%s testSuite=%s status=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testSuite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ERROR: operation=%s error=%v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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;h3&gt;
  
  
  Advanced Features
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Dynamic Parameter Parsing
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;CommandParser&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;CommandParser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ParseCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Default values&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"ENVIRONMENT"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dev"&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"TEST_SUITE"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"smoke"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Parse key=value pairs&lt;/span&gt;
    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SplitN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToUpper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Job Status Callbacks
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;JobStatusCallback&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;WebhookURL&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Channel&lt;/span&gt;    &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;JobStatusCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
        &lt;span class="s"&gt;"channel"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Job %s: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jobName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="s"&gt;"attachments"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"color"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;getStatusColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s"&gt;"fields"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}{&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Details"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"short"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sendToSlack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getStatusColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"good"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"failure"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"danger"&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"warning"&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;h2&gt;
  
  
  🔧 Troubleshooting Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common Debugging Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check Lambda logs&lt;/span&gt;
aws logs &lt;span class="nb"&gt;tail&lt;/span&gt; /aws/lambda/jenkins-slack-demo-jenkins-trigger &lt;span class="nt"&gt;--follow&lt;/span&gt;

&lt;span class="c"&gt;# Test API Gateway directly&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://your-api-gateway-url/prod/trigger &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/x-www-form-urlencoded"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"text=dev smoke&amp;amp;user_name=testuser&amp;amp;channel_name=general"&lt;/span&gt;

&lt;span class="c"&gt;# Check Jenkins connectivity from Lambda subnet&lt;/span&gt;
aws ec2 describe-instances &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=tag:Name,Values=jenkins-slack-demo-*"&lt;/span&gt;

&lt;span class="c"&gt;# Verify SSM parameters&lt;/span&gt;
aws ssm get-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/jenkins-slack-demo/jenkins_url"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws ssm get-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/jenkins-slack-demo/jenkins_credentials"&lt;/span&gt; &lt;span class="nt"&gt;--with-decryption&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Test Jenkins API directly&lt;/span&gt;
curl &lt;span class="nt"&gt;-u&lt;/span&gt; admin:your-secure-password http://localhost:8080/api/json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Performance Optimization
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Connection Pooling
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MaxIdleConns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;MaxIdleConnsPerHost&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IdleConnTimeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="m"&gt;90&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Transport&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&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;h4&gt;
  
  
  2. SSM Parameter Caching
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ParameterCache&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;mutex&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RWMutex&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ParameterCache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RUnlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RUnlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Fetch from SSM and cache&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// SSM fetch logic here&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;

    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 Key Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Worked Well
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code&lt;/strong&gt;: Terraform made the setup reproducible and version-controlled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private Jenkins&lt;/strong&gt;: Keeping Jenkins in private subnets provided excellent security&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSM Parameter Store&lt;/strong&gt;: Centralized secret management eliminated hardcoded credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Lambda Functions&lt;/strong&gt;: Fast, efficient, and easy to debug&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What Didn't Work Initially
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins Initial Setup&lt;/strong&gt;: Manual setup wizard was unreliable for automation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSRF Tokens&lt;/strong&gt;: Added unnecessary complexity for API-only access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack App Installation&lt;/strong&gt;: Required careful attention to permissions and URLs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda VPC Configuration&lt;/strong&gt;: ENI management required proper cleanup&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Best Practices Discovered
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automate Everything&lt;/strong&gt;: Use scripts for Jenkins setup, not manual configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Each Layer&lt;/strong&gt;: Verify infrastructure, Lambda, Jenkins, and Slack separately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Everything&lt;/strong&gt;: Keep detailed notes of fixes and workarounds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Early&lt;/strong&gt;: Set up CloudWatch alarms from day one&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🚀 Production Deployment Checklist
&lt;/h2&gt;

&lt;p&gt;Before going live, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Security Review&lt;/strong&gt;: All secrets in SSM, no hardcoded credentials&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Monitoring&lt;/strong&gt;: CloudWatch alarms for errors and performance&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Backup Strategy&lt;/strong&gt;: Jenkins configuration and job definitions&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Disaster Recovery&lt;/strong&gt;: Terraform state in S3 with DynamoDB locking&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Access Control&lt;/strong&gt;: Proper IAM roles with least privilege&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Network Security&lt;/strong&gt;: Security groups reviewed and tightened&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Documentation&lt;/strong&gt;: Runbooks for common operations&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Testing&lt;/strong&gt;: End-to-end tests for all critical paths&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📊 Performance Metrics
&lt;/h2&gt;

&lt;p&gt;After implementing all optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lambda Execution&lt;/strong&gt;: ~2-3 seconds (down from 5-8 seconds)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins Job Trigger&lt;/strong&gt;: ~1-2 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-End Response&lt;/strong&gt;: ~5 seconds (down from 10-15 seconds)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Rate&lt;/strong&gt;: &amp;lt;1% (down from 15-20%)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Deployment&lt;/strong&gt;: ~8 minutes (consistent)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎉 Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a production-ready Jenkins-Slack integration is more than just connecting the dots. The real value comes from understanding the challenges, implementing robust solutions, and continuously improving the system.&lt;/p&gt;

&lt;p&gt;Key takeaways from this journey:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Automation is Critical&lt;/strong&gt;: Manual setup processes are error-prone and don't scale&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Security by Design&lt;/strong&gt;: Private subnets, SSM parameters, and least privilege IAM&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Monitoring Matters&lt;/strong&gt;: You can't fix what you can't see&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Documentation Saves Time&lt;/strong&gt;: Detailed troubleshooting guides prevent future headaches&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Iterative Improvement&lt;/strong&gt;: Start simple, then add complexity as needed&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Resources and Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository&lt;/strong&gt;: &lt;a href="https://github.com/kasukur/jenkins-slack-aws-integration" rel="noopener noreferrer"&gt;jenkins-slack-aws-integration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 1&lt;/strong&gt;: &lt;a href="https://dev.to/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-1-complete-setup-guide-lgd"&gt;Complete Setup Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Documentation&lt;/strong&gt;: &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html" rel="noopener noreferrer"&gt;Lambda in VPC&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins Documentation&lt;/strong&gt;: &lt;a href="https://www.jenkins.io/doc/book/using/remote-access-api/" rel="noopener noreferrer"&gt;REST API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack API&lt;/strong&gt;: &lt;a href="https://api.slack.com/interactivity/slash-commands" rel="noopener noreferrer"&gt;Slash Commands&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤝 Community Contributions
&lt;/h2&gt;

&lt;p&gt;This project is open source and welcomes contributions! Areas for improvement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Additional CI/CD Tools&lt;/strong&gt;: Support for GitLab, GitHub Actions, or Azure DevOps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Monitoring&lt;/strong&gt;: Prometheus metrics, Grafana dashboards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Environment&lt;/strong&gt;: Support for multiple Jenkins instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Features&lt;/strong&gt;: Job scheduling, parameter validation, approval workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Ready to build something amazing? Start with &lt;a href="https://dev.to/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-1-complete-setup-guide-lgd"&gt;Part 1&lt;/a&gt; if you haven't already, then implement these production enhancements. Have questions or want to share your own solutions? Drop a comment below!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Remember: The best DevOps solutions are built through iteration, collaboration, and learning from real-world challenges. Happy building! 🚀&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@dlxmedia" rel="noopener noreferrer"&gt;@dlxmedia.hu&lt;/a&gt; from &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>slack</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Building Secure Jenkins-Slack Integration with AWS Lambda - Part 1: Complete Setup Guide</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Tue, 14 Oct 2025 11:08:20 +0000</pubDate>
      <link>https://forem.com/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-1-complete-setup-guide-lgd</link>
      <guid>https://forem.com/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-1-complete-setup-guide-lgd</guid>
      <description>&lt;h1&gt;
  
  
  Building Secure Jenkins-Slack Integration with AWS Lambda - Part 1: Complete Setup Guide
&lt;/h1&gt;

&lt;p&gt;Ever wished you could trigger your CI/CD pipelines directly from Slack without exposing Jenkins to the public internet? In this comprehensive two-part series, we'll build a production-ready solution that lets your team trigger Jenkins jobs using Slack slash commands while maintaining enterprise-grade security.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;Part 1&lt;/strong&gt; of our series, focusing on architecture design, infrastructure setup, and initial implementation. &lt;a href="https://dev.to/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-2-troubleshooting-real-world-429d"&gt;Part 2&lt;/a&gt; will dive deep into troubleshooting real-world issues and production enhancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We'll Build
&lt;/h2&gt;

&lt;p&gt;This solution enables teams to trigger Jenkins CI/CD pipelines from Slack using a secure, serverless architecture. The key innovation is keeping Jenkins completely private while providing a public API endpoint through AWS Lambda and API Gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack Overview
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure&lt;/strong&gt;: Terraform (IaC), AWS VPC, EC2, Lambda, API Gateway, ALB, NAT Gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Go 1.20 (Lambda functions), Jenkins (CI/CD orchestration)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage/Secrets&lt;/strong&gt;: AWS SSM Parameter Store&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt;: Slack API (Slash Commands, Webhooks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: CloudWatch Logs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS&lt;/strong&gt;: Amazon Linux 2&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Deep Dive
&lt;/h2&gt;

&lt;p&gt;Let's start with the complete architecture flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│                        Architecture Flow                        │
└─────────────────────────────────────────────────────────────────┘

👥 Slack User                    🌐 API Gateway
/run_test environment=staging ──→ /prod/trigger
                                        │
                                        ▼
                                ⚡ AWS Lambda
                                jenkins-trigger
                                        │
                    ┌───────────────────┼───────────────────┐
                    │                   │                   │
                    ▼                   ▼                   ▼
            🔐 AWS SSM Parameter    🔧 Jenkins (Private EC2)    🛡️ Bastion Host
            Store                   CI/CD Orchestration        SSH Access Gateway
            Jenkins URL &amp;amp;           ◄─────────────────────────┘
            Credentials             │
                    │               │
                    └───────────────┼───────────────────────────┐
                                    │                           │
                                    ▼                           ▼
                            ⚖️ Internal ALB              Job Status
                            Load Balancer                Notifications
                                    │                           │
                                    └───────────────────────────┘
                                                              │
                                                              ▼
                                                        👥 Slack User
                                                        (Status Updates)

Legend:
🟠 AWS Services (API Gateway, Lambda, SSM, ALB, Bastion)
🟣 Slack Integration
🔴 Jenkins (Private EC2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Components Explained
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;🔒 VPC with Public/Private Subnets&lt;/strong&gt;: Jenkins runs in a private subnet with no internet access, while the bastion host provides secure SSH access from the public subnet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚡ Lambda Function in VPC&lt;/strong&gt;: The Lambda function runs in the private subnet to communicate with Jenkins while being invoked by API Gateway from the internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌐 API Gateway&lt;/strong&gt;: Provides a public HTTPS endpoint that Slack can reach, while the Lambda function handles the secure communication with Jenkins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐 SSM Parameter Store&lt;/strong&gt;: Stores Jenkins credentials and configuration securely, eliminating the need for hardcoded secrets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛡️ Bastion Host&lt;/strong&gt;: Provides secure SSH access to Jenkins for administrative tasks without exposing Jenkins directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚖️ Internal Load Balancer&lt;/strong&gt;: Distributes traffic to Jenkins instances and provides health checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Public Exposure&lt;/strong&gt;: Jenkins never faces the internet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted Secrets&lt;/strong&gt;: All credentials stored in SSM with encryption&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Isolation&lt;/strong&gt;: Private subnets with controlled access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least Privilege&lt;/strong&gt;: IAM roles with minimal required permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS account with appropriate permissions (EC2, Lambda, API Gateway, SSM, VPC)&lt;/li&gt;
&lt;li&gt;Terraform &amp;gt;= 1.0.0 installed&lt;/li&gt;
&lt;li&gt;AWS CLI configured with credentials&lt;/li&gt;
&lt;li&gt;Go 1.20+ installed (for Lambda function builds)&lt;/li&gt;
&lt;li&gt;Slack workspace with admin privileges&lt;/li&gt;
&lt;li&gt;SSH key pair for EC2 access&lt;/li&gt;
&lt;li&gt;Basic understanding of Jenkins, Lambda, and Terraform&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 0: Initial Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Configure AWS CLI
&lt;/h4&gt;

&lt;p&gt;First, configure your AWS CLI with proper credentials:&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="c"&gt;# Configure AWS CLI&lt;/span&gt;
aws configure

&lt;span class="c"&gt;# Enter your AWS Access Key ID, Secret Access Key, region (us-east-1), and output format (json)&lt;/span&gt;
&lt;span class="c"&gt;# Verify configuration&lt;/span&gt;
aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Create SSH Key Pair
&lt;/h4&gt;

&lt;p&gt;Create an EC2 key pair for SSH access:&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="c"&gt;# Option 1: Create via AWS CLI&lt;/span&gt;
aws ec2 create-key-pair &lt;span class="nt"&gt;--key-name&lt;/span&gt; jenkins-slack-key &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'KeyMaterial'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; jenkins-slack-key.pem
&lt;span class="nb"&gt;chmod &lt;/span&gt;400 jenkins-slack-key.pem

&lt;span class="c"&gt;# Option 2: Create via AWS Console&lt;/span&gt;
&lt;span class="c"&gt;# Go to EC2 → Key Pairs → Create Key Pair → Name: jenkins-slack-key → Download .pem file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step-by-Step Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Clone and Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kasukur/jenkins-slack-aws-integration
&lt;span class="nb"&gt;cd &lt;/span&gt;jenkins-slack-aws-integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Build Lambda Functions
&lt;/h3&gt;

&lt;p&gt;Build the Lambda function binaries:&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="c"&gt;# Navigate to Lambda function directories&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;lambda/jenkins_trigger
go mod tidy
&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 go build &lt;span class="nt"&gt;-o&lt;/span&gt; bootstrap main.go
zip jenkins_trigger.zip bootstrap

&lt;span class="nb"&gt;cd&lt;/span&gt; ../slack_verification
go mod tidy
&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 go build &lt;span class="nt"&gt;-o&lt;/span&gt; bootstrap main.go
zip slack_verification.zip bootstrap

&lt;span class="c"&gt;# Copy zips to terraform directory&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;jenkins_trigger.zip ../../terraform/
&lt;span class="nb"&gt;cp &lt;/span&gt;slack_verification.zip ../../terraform/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── terraform/           # Infrastructure as Code
│   ├── main.tf         # Provider and key pair
│   ├── vpc.tf          # VPC, subnets, security groups
│   ├── jenkins.tf      # Jenkins EC2 and ALB
│   ├── lambda.tf       # Lambda functions
│   ├── api_gateway.tf  # API Gateway configuration
│   ├── iam.tf          # IAM roles and policies
│   └── variables.tf    # Variable definitions
├── lambda/             # Lambda function source code
│   ├── jenkins_trigger/    # Main Lambda function
│   └── slack_verification/ # Slack signature verification
└── jenkins/            # Jenkins pipeline definitions
    └── Jenkinsfile     # Test pipeline configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Configure Slack App
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create Slack App
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to Slack API&lt;/strong&gt;: &lt;a href="https://api.slack.com/apps" rel="noopener noreferrer"&gt;https://api.slack.com/apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click "Create New App"&lt;/strong&gt; → "From scratch"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App Name&lt;/strong&gt;: &lt;code&gt;Jenkins CI/CD Integration&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace&lt;/strong&gt;: Select your workspace&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Create App"&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Configure Slash Command
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;In your app settings&lt;/strong&gt;, go to &lt;strong&gt;"Slash Commands"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Create New Command"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fill in the details&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Command&lt;/strong&gt;: &lt;code&gt;/run_test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request URL&lt;/strong&gt;: &lt;code&gt;https://your-api-gateway-url/prod/trigger&lt;/code&gt; (we'll get this after deployment)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short Description&lt;/strong&gt;: &lt;code&gt;Trigger Jenkins test pipeline&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage Hint&lt;/strong&gt;: &lt;code&gt;[environment] [test_suite]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Save"&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Enable Incoming Webhooks
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to "Incoming Webhooks"&lt;/strong&gt; in your app settings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toggle "Activate Incoming Webhooks"&lt;/strong&gt; to On&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Add New Webhook to Workspace"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select a channel&lt;/strong&gt; (e.g., #devops)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Allow"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy the webhook URL&lt;/strong&gt; (starts with &lt;code&gt;https://hooks.slack.com/services/&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Get App Credentials
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to "Basic Information"&lt;/strong&gt; in your app settings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In "App Credentials" section&lt;/strong&gt;, copy:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App-Level Token&lt;/strong&gt; (starts with &lt;code&gt;xapp-&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signing Secret&lt;/strong&gt; (long random string)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Install App to Workspace
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to "Install App"&lt;/strong&gt; in your app settings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Install to Workspace"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review permissions&lt;/strong&gt; and click "Allow"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy the Bot User OAuth Token&lt;/strong&gt; (starts with &lt;code&gt;xoxb-&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Save these values for the Terraform configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App-Level Token (xapp-...)&lt;/li&gt;
&lt;li&gt;Signing Secret&lt;/li&gt;
&lt;li&gt;Webhook URL&lt;/li&gt;
&lt;li&gt;Bot User OAuth Token (xoxb-...)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Prepare Terraform Variables
&lt;/h3&gt;

&lt;p&gt;Copy the example configuration:&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="nb"&gt;cp &lt;/span&gt;terraform/terraform.tfvars.example terraform/terraform.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;terraform/terraform.tfvars&lt;/code&gt; with your values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic Configuration&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="nx"&gt;project_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"jenkins-slack-demo"&lt;/span&gt;

&lt;span class="c1"&gt;# Network Configuration&lt;/span&gt;
&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="nx"&gt;public_subnet_cidrs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"10.0.2.0/24"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;private_subnet_cidrs&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"10.0.101.0/24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"10.0.102.0/24"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# SSH Access&lt;/span&gt;
&lt;span class="nx"&gt;key_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-key-pair-name"&lt;/span&gt;
&lt;span class="nx"&gt;public_key&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ssh-rsa AAAAB3NzaC1yc2E... your-email@example.com"&lt;/span&gt;

&lt;span class="c1"&gt;# Jenkins Configuration&lt;/span&gt;
&lt;span class="nx"&gt;jenkins_admin_username&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"admin"&lt;/span&gt;
&lt;span class="nx"&gt;jenkins_admin_password&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-secure-password"&lt;/span&gt;

&lt;span class="c1"&gt;# Slack Configuration&lt;/span&gt;
&lt;span class="nx"&gt;slack_app_token&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"xapp-your-app-token"&lt;/span&gt;
&lt;span class="nx"&gt;slack_signing_secret&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-signing-secret"&lt;/span&gt;
&lt;span class="nx"&gt;slack_webhook_url&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://hooks.slack.com/services/your/webhook/url"&lt;/span&gt;
&lt;span class="nx"&gt;slack_bot_token&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"xoxb-your-bot-token"&lt;/span&gt;
&lt;span class="nx"&gt;slack_channel&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"#devops"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Deploy Infrastructure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;terraform

&lt;span class="c"&gt;# Initialize Terraform&lt;/span&gt;
terraform init

&lt;span class="c"&gt;# Review the plan (should show ~25 resources)&lt;/span&gt;
terraform plan

&lt;span class="c"&gt;# Deploy the infrastructure&lt;/span&gt;
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Save the outputs displayed after successful deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api_gateway_url = "https://&amp;lt;your-api-gateway-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/prod/trigger"
bastion_public_ip = "&amp;lt;bastion-public-ip&amp;gt;"
jenkins_url = "http://&amp;lt;internal-alb-url&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Update Slack Configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go back to your Slack app settings&lt;/li&gt;
&lt;li&gt;Update the slash command Request URL with the API Gateway URL from Step 5&lt;/li&gt;
&lt;li&gt;Save the changes&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 7: Configure Jenkins
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Access Jenkins
&lt;/h4&gt;

&lt;p&gt;Set up SSH tunnel through the bastion host:&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="c"&gt;# SSH to bastion host with port forwarding&lt;/span&gt;
ssh &lt;span class="nt"&gt;-i&lt;/span&gt; your-key.pem &lt;span class="nt"&gt;-L&lt;/span&gt; 8080:&amp;lt;jenkins_private_ip&amp;gt;:8080 ec2-user@&amp;lt;bastion_public_ip&amp;gt; &lt;span class="nt"&gt;-N&lt;/span&gt;

&lt;span class="c"&gt;# In another terminal, access Jenkins via localhost&lt;/span&gt;
&lt;span class="c"&gt;# Open browser: http://localhost:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Initial Jenkins Setup
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Wait for Jenkins initialization&lt;/strong&gt; (5-10 minutes), then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get the initial admin password&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;# SSH to Jenkins instance&lt;/span&gt;
   ssh &lt;span class="nt"&gt;-i&lt;/span&gt; your-key.pem ec2-user@&amp;lt;bastion_public_ip&amp;gt;
   ssh ec2-user@&amp;lt;jenkins_private_ip&amp;gt;

   &lt;span class="c"&gt;# Get initial password&lt;/span&gt;
   &lt;span class="nb"&gt;sudo cat&lt;/span&gt; /var/lib/jenkins/secrets/initialAdminPassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Access Jenkins&lt;/strong&gt; at &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enter the initial admin password&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install suggested plugins&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create admin user&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Username: &lt;code&gt;admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Password: &lt;code&gt;&amp;lt;your-secure-password&amp;gt;&lt;/code&gt; (use a strong password)&lt;/li&gt;
&lt;li&gt;Full name: &lt;code&gt;Administrator&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Email: &lt;code&gt;admin@yourcompany.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Install Slack Plugin
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to&lt;/strong&gt;: Manage Jenkins → Manage Plugins → Available&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search for&lt;/strong&gt;: "Slack Notification"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the box&lt;/strong&gt; and click &lt;strong&gt;"Install without restart"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait for installation&lt;/strong&gt; to complete&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go to&lt;/strong&gt;: Manage Jenkins → Configure System&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find "Slack" section&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workspace&lt;/strong&gt;: Your workspace name&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default Channel&lt;/strong&gt;: #devops (or your preferred channel)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Token&lt;/strong&gt;: Paste your Bot User OAuth Token (xoxb-...)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click "Test Connection"&lt;/strong&gt; - should show "Success"&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Save"&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Create Pipeline Job
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Click "New Item"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enter item name&lt;/strong&gt;: &lt;code&gt;run_test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select "Pipeline"&lt;/strong&gt; and click &lt;strong&gt;"OK"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In Pipeline section&lt;/strong&gt;, select &lt;strong&gt;"Pipeline script"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy the content&lt;/strong&gt; from &lt;code&gt;jenkins/Jenkinsfile&lt;/code&gt; into the script area&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click "Save"&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 8: Update SSM Parameters
&lt;/h3&gt;

&lt;p&gt;Verify the Jenkins URL in SSM Parameter Store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm get-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/jenkins-slack-demo/jenkins_url"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If needed, update it with the correct internal ALB URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm put-parameter &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/jenkins-slack-demo/jenkins_url"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"http://&amp;lt;internal-alb-url&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--overwrite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verification and Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test 1: Verify Infrastructure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check EC2 instances&lt;/span&gt;
aws ec2 describe-instances &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=tag:Name,Values=jenkins-slack-demo-*"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Check Lambda functions&lt;/span&gt;
aws lambda list-functions &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Check API Gateway&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://your-api-gateway-url/prod/trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test 2: Verify Lambda Function
&lt;/h3&gt;

&lt;p&gt;Test the Lambda function directly:&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="c"&gt;# Test Lambda function&lt;/span&gt;
aws lambda invoke &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; jenkins-slack-demo-jenkins-trigger &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--payload&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  /tmp/lambda-response.json &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/lambda-response.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test 3: Verify Jenkins Connectivity
&lt;/h3&gt;

&lt;p&gt;Test Jenkins accessibility from Lambda:&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="c"&gt;# SSH to Jenkins and verify it's running&lt;/span&gt;
ssh &lt;span class="nt"&gt;-i&lt;/span&gt; your-key.pem ec2-user@&amp;lt;bastion_public_ip&amp;gt;
ssh ec2-user@&amp;lt;jenkins_private_ip&amp;gt;

&lt;span class="c"&gt;# Check Jenkins status&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status jenkins
curl &lt;span class="nt"&gt;-u&lt;/span&gt; admin:&amp;lt;your-secure-password&amp;gt; http://localhost:8080/api/json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test 4: Test Slack Command
&lt;/h3&gt;

&lt;p&gt;In any Slack channel where your app is installed, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/run_test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected behavior&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immediate response in Slack: "Job triggered successfully!"&lt;/li&gt;
&lt;li&gt;Jenkins job appears in the dashboard&lt;/li&gt;
&lt;li&gt;Job runs with default parameters (ENVIRONMENT=dev, TEST_SUITE=smoke)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Test 5: Verify Jenkins Job Execution
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check Jenkins dashboard&lt;/strong&gt; for the &lt;code&gt;run_test&lt;/code&gt; job&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify job parameters&lt;/strong&gt; (ENVIRONMENT=dev, TEST_SUITE=smoke)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check job logs&lt;/strong&gt; for successful execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirm Slack receives&lt;/strong&gt; success/failure notifications&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Test 6: End-to-End Test with Parameters
&lt;/h3&gt;

&lt;p&gt;Test with custom parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/run_test environment=staging test_suite=regression
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Monitor the complete flow&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Slack&lt;/strong&gt; → API Gateway → Lambda&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt; → Jenkins (job trigger with parameters)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jenkins&lt;/strong&gt; → Slack (status notification)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Key Code Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lambda Function (Go)
&lt;/h3&gt;

&lt;p&gt;The Lambda function handles the core integration logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Get Jenkins URL and credentials from SSM&lt;/span&gt;
    &lt;span class="n"&gt;jenkinsURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getSSMParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jenkinsURLParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;credsJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getSSMParameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jenkinsCredsParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Get CSRF crumb for Jenkins security&lt;/span&gt;
    &lt;span class="n"&gt;crumbField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crumb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getJenkinsCrumb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jenkinsURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Trigger Jenkins job&lt;/span&gt;
    &lt;span class="n"&gt;jobURL&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s/job/run_test/buildWithParameters"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jenkinsURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ENVIRONMENT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TEST_SUITE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"smoke"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Make authenticated request with crumb&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Jenkins-Crumb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crumb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetBasicAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIGatewayProxyResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;`{"message": "Job triggered! Status: 201"}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Jenkins Pipeline
&lt;/h3&gt;

&lt;p&gt;The Jenkinsfile defines the test pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;

    &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s1"&gt;'ENVIRONMENT'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;defaultValue:&lt;/span&gt; &lt;span class="s1"&gt;'dev'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;description:&lt;/span&gt; &lt;span class="s1"&gt;'Environment to run tests against'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s1"&gt;'TEST_SUITE'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;defaultValue:&lt;/span&gt; &lt;span class="s1"&gt;'smoke'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;description:&lt;/span&gt; &lt;span class="s1"&gt;'Test suite to run'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Prepare'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Preparing to run tests in ${params.ENVIRONMENT} environment"&lt;/span&gt;
                &lt;span class="n"&gt;slackSend&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="s1"&gt;'#FFFF00'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;message:&lt;/span&gt; &lt;span class="s2"&gt;"STARTED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run Tests'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running ${params.TEST_SUITE} tests against ${params.ENVIRONMENT}"&lt;/span&gt;
                &lt;span class="c1"&gt;// Your actual test commands here&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;slackSend&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="s1"&gt;'#00FF00'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;message:&lt;/span&gt; &lt;span class="s2"&gt;"SUCCESS: Job completed successfully"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;failure&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;slackSend&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="s1"&gt;'#FF0000'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;message:&lt;/span&gt; &lt;span class="s2"&gt;"FAILED: Job failed"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Congratulations! You've successfully built the foundation of a secure Jenkins-Slack integration. At this point, you should have:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Working Infrastructure&lt;/strong&gt;: VPC, Jenkins, Lambda, API Gateway&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Basic Integration&lt;/strong&gt;: Slack can trigger Jenkins jobs&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Security&lt;/strong&gt;: Private Jenkins with secure access patterns&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Monitoring&lt;/strong&gt;: CloudWatch logs for observability&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming Up in Part 2
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-2-troubleshooting-real-world-429d"&gt;Part 2 of this series&lt;/a&gt;, we'll dive deep into:&lt;/p&gt;

&lt;p&gt;🔧 &lt;strong&gt;Real-World Troubleshooting&lt;/strong&gt;: Common issues you'll encounter and battle-tested solutions&lt;br&gt;&lt;br&gt;
🛠️ &lt;strong&gt;Production Enhancements&lt;/strong&gt;: Security improvements, monitoring, and scaling considerations&lt;br&gt;&lt;br&gt;
🚨 &lt;strong&gt;Critical Fixes&lt;/strong&gt;: Jenkins authentication issues, CSRF token problems, and Slack integration challenges&lt;br&gt;&lt;br&gt;
📊 &lt;strong&gt;Advanced Features&lt;/strong&gt;: Parameter parsing, job status callbacks, and multi-environment support&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;This architecture demonstrates several important DevOps and AWS best practices:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Security First&lt;/strong&gt;: Jenkins is never exposed to the internet, following zero-trust principles&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Infrastructure as Code&lt;/strong&gt;: Everything is defined in Terraform, making it reproducible and version-controlled&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Serverless Integration&lt;/strong&gt;: Lambda provides cost-effective, scalable integration without managing servers&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Secret Management&lt;/strong&gt;: SSM Parameter Store eliminates hardcoded credentials&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Network Isolation&lt;/strong&gt;: VPC with public/private subnets provides proper network segmentation&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Observability&lt;/strong&gt;: CloudWatch logs provide visibility into system behavior&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Ready to tackle the real-world challenges? Check out &lt;a href="https://dev.to/aws-builders/building-secure-jenkins-slack-integration-with-aws-lambda-part-2-troubleshooting-real-world-429d"&gt;Part 2&lt;/a&gt; where we'll solve the tricky issues that make or break production deployments!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have questions or suggestions for improvements? Feel free to reach out or contribute to the project repository!&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@dlxmedia" rel="noopener noreferrer"&gt;@dlxmedia.hu&lt;/a&gt; from &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>slack</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Setting up AWS Client VPN with CloudFormation and AWS CLI</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sat, 26 Jul 2025 03:16:24 +0000</pubDate>
      <link>https://forem.com/aws-builders/setting-up-aws-client-vpn-with-cloudformation-and-aws-cli-1nnf</link>
      <guid>https://forem.com/aws-builders/setting-up-aws-client-vpn-with-cloudformation-and-aws-cli-1nnf</guid>
      <description>&lt;p&gt;After I published my blog on &lt;a href="https://dev.to/kasukur/how-to-setup-an-aws-client-vpn-51f"&gt;How to Set Up an AWS Client VPN&lt;/a&gt;, someone asked if I could share a CloudFormation template to automate the setup. In response, I’ve put together this follow-up post to walk you through deploying an AWS Client VPN endpoint using CloudFormation and AWS CLI. You’ll learn how to associate the VPN with your VPC, configure access rules, and handle the critical manual step of updating security group rules. I’ve also included a handy shell script to simplify and automate the entire deployment process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is AWS Client VPN?&lt;/li&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;
Step-by-Step Deployment with CloudFormation

&lt;ul&gt;
&lt;li&gt;1. Generate Client and Server Certificates&lt;/li&gt;
&lt;li&gt;2. Deploy VPC and EC2 Instance Optional&lt;/li&gt;
&lt;li&gt;3. Deploy the Client VPN CloudFormation Stack&lt;/li&gt;
&lt;li&gt;4. Manual Step Update Security Group Rule&lt;/li&gt;
&lt;li&gt;5. Authorize Clients to Access the Network&lt;/li&gt;
&lt;li&gt;6. Optional Add Route to Enable Traffic from VPN to VPC&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Deploying with AWS CLI Alternate Method

&lt;ul&gt;
&lt;li&gt;1. Create Client VPN Endpoint&lt;/li&gt;
&lt;li&gt;2. Associate Client VPN Endpoint with a Subnet&lt;/li&gt;
&lt;li&gt;3. Authorize Client VPN Ingress&lt;/li&gt;
&lt;li&gt;4. Revoke Client VPN Ingress Optional&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Deployment Script&lt;/li&gt;

&lt;li&gt;Cleanup&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;li&gt;Referrals&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is AWS Client VPN?
&lt;/h2&gt;

&lt;p&gt;AWS Client VPN is a managed client-based VPN service that enables you to securely access your AWS resources and on-premises networks from any location. It provides a highly available and scalable solution for remote access, allowing your users to connect to your private networks using a VPN client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account.&lt;/li&gt;
&lt;li&gt;AWS CLI installed and configured with appropriate permissions.&lt;/li&gt;
&lt;li&gt;OpenSSL installed for certificate generation (if not using existing certificates).&lt;/li&gt;
&lt;li&gt;A VPC where you want to deploy the Client VPN endpoint. The provided CloudFormation template assumes a new VPC will be created.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step-by-Step Deployment with CloudFormation
&lt;/h2&gt;

&lt;p&gt;AWS CloudFormation allows you to define your AWS infrastructure as code, making it easy to deploy and manage resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Generate Client and Server Certificates
&lt;/h3&gt;

&lt;p&gt;AWS Client VPN requires mutual authentication, which means both the server and client need certificates. You can generate these using OpenSSL. The provided &lt;code&gt;generate_certs.sh&lt;/code&gt; script in the attached zip file can help you with this, as detailed in the original blog post: &lt;a href="https://dev.to/kasukur/how-to-setup-an-aws-client-vpn-51f"&gt;How to Set Up an AWS Client VPN&lt;/a&gt;. Make sure to upload these certificates to AWS Certificate Manager (ACM).&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="c"&gt;# Example command to generate certificates (from generate_certs.sh)&lt;/span&gt;
&lt;span class="c"&gt;# This is a simplified example, refer to the actual script for full details.&lt;/span&gt;
&lt;span class="c"&gt;# You will need to import these into ACM.&lt;/span&gt;

&lt;span class="c"&gt;# Generate server certificate and key&lt;/span&gt;
openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; server.key 2048
openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; server.key &lt;span class="nt"&gt;-out&lt;/span&gt; server.csr
openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; server.csr &lt;span class="nt"&gt;-signkey&lt;/span&gt; server.key &lt;span class="nt"&gt;-out&lt;/span&gt; server.crt

&lt;span class="c"&gt;# Generate client certificate and key&lt;/span&gt;
openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; client.key 2048
openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; client.key &lt;span class="nt"&gt;-out&lt;/span&gt; client.csr
openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; client.csr &lt;span class="nt"&gt;-signkey&lt;/span&gt; client.key &lt;span class="nt"&gt;-out&lt;/span&gt; client.crt

&lt;span class="c"&gt;# Import server certificate to ACM&lt;/span&gt;
aws acm import-certificate &lt;span class="nt"&gt;--certificate&lt;/span&gt; fileb://server.crt &lt;span class="nt"&gt;--private-key&lt;/span&gt; fileb://server.key &lt;span class="nt"&gt;--certificate-chain&lt;/span&gt; fileb://ca.crt

&lt;span class="c"&gt;# Import client certificate to ACM&lt;/span&gt;
aws acm import-certificate &lt;span class="nt"&gt;--certificate&lt;/span&gt; fileb://client.crt &lt;span class="nt"&gt;--private-key&lt;/span&gt; fileb://client.key &lt;span class="nt"&gt;--certificate-chain&lt;/span&gt; fileb://ca.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Note down the ARNs of the imported server and client certificates. You will need them for the CloudFormation deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deploy VPC and EC2 Instance (Optional)
&lt;/h3&gt;

&lt;p&gt;If you don't have an existing VPC and an EC2 instance in a private subnet, you can use the &lt;code&gt;vpc-ec2.yaml&lt;/code&gt; CloudFormation template (provided in the attached zip file) to set up a basic environment. This template creates a VPC, a private subnet, a route table, a security group, and an EC2 instance within that private subnet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2010-09-09'&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VPC, subnet, security group, and EC2 instance for AWS Client VPN demo.&lt;/span&gt;

&lt;span class="na"&gt;Parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;KeyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;String&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name of an existing EC2 KeyPair to enable SSH access&lt;/span&gt;
  &lt;span class="na"&gt;LatestAmiId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS::SSM::Parameter::Value&amp;lt;AWS::EC2::Image::Id&amp;gt;'&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SSM parameter for the latest Amazon Linux 2 AMI&lt;/span&gt;

&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyVPC&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::VPC&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.0.0/16&lt;/span&gt;
      &lt;span class="na"&gt;EnableDnsSupport&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;EnableDnsHostnames&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;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyClientVPNVPC&lt;/span&gt;

  &lt;span class="na"&gt;MyPrivateSubnet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Subnet&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
      &lt;span class="na"&gt;CidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.0/24&lt;/span&gt;
      &lt;span class="na"&gt;MapPublicIpOnLaunch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;AvailabilityZone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Select&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;!GetAZs&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;

  &lt;span class="na"&gt;MyRouteTable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::RouteTable&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateRouteTable&lt;/span&gt;

  &lt;span class="na"&gt;MySubnetRouteTableAssociation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SubnetRouteTableAssociation&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;
      &lt;span class="na"&gt;RouteTableId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyRouteTable&lt;/span&gt;

  &lt;span class="na"&gt;MySecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow SSH from Client VPN&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSG&lt;/span&gt;

  &lt;span class="na"&gt;MyInstanceProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::IAM::InstanceProfile&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="nv"&gt;MyInstanceRole&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="na"&gt;MyInstanceRole&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::IAM::Role&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AssumeRolePolicyDocument&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2012-10-17'&lt;/span&gt;
        &lt;span class="na"&gt;Statement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;
            &lt;span class="na"&gt;Principal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;Service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ec2.amazonaws.com&lt;/span&gt;
            &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sts:AssumeRole&lt;/span&gt;
      &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/'&lt;/span&gt;
      &lt;span class="na"&gt;ManagedPolicyArns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore&lt;/span&gt;

  &lt;span class="na"&gt;MyEC2Instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Instance&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;InstanceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;t3.micro&lt;/span&gt;
      &lt;span class="na"&gt;KeyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;KeyName&lt;/span&gt;
      &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="nv"&gt;MySecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;IamInstanceProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyInstanceProfile&lt;/span&gt;
      &lt;span class="na"&gt;ImageId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;LatestAmiId&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateEC2&lt;/span&gt;

&lt;span class="na"&gt;Outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VPC ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
  &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Private Subnet ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;
  &lt;span class="na"&gt;SecurityGroupId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Group ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MySecurityGroup&lt;/span&gt;
  &lt;span class="na"&gt;InstanceId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EC2 Instance ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyEC2Instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To deploy this stack, you can use the AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation deploy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyVPCAndEC2Stack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; vpc-ec2.yaml &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_NAMED_IAM &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--parameter-overrides&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;KeyName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_KEY_PAIR_NAME &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;LatestAmiId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/aws/service/ami-amazon-linux-2/latest/amzn2-ami-hvm-x86_64-gp2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;YOUR_KEY_PAIR_NAME&lt;/code&gt; with your actual key pair name. If you deploy this stack, you will need to retrieve the &lt;code&gt;VpcId&lt;/code&gt;, &lt;code&gt;SubnetId&lt;/code&gt;, and &lt;code&gt;SecurityGroupId&lt;/code&gt; from its outputs to use in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Deploy the Client VPN CloudFormation Stack
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;aws-client-vpn.yaml&lt;/code&gt; CloudFormation template (provided in the attached zip file) defines the necessary AWS resources for the Client VPN endpoint. This template assumes you have an existing VPC and subnet, or have deployed them using the previous step. It sets up the Client VPN endpoint itself, and includes a security group for the EC2 instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2010-09-09'&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;AWS Client VPN and EC2 setup.&lt;/span&gt;
  &lt;span class="s"&gt;- VPC: 192.168.0.0/16&lt;/span&gt;
  &lt;span class="s"&gt;- Private Subnet: 192.168.1.0/24&lt;/span&gt;
  &lt;span class="s"&gt;- EC2 Instance in private subnet&lt;/span&gt;
  &lt;span class="s"&gt;- Security group for EC2&lt;/span&gt;
  &lt;span class="s"&gt;- Client VPN endpoint (client CIDR: 10.0.0.0/22, does not overlap with VPC)&lt;/span&gt;

&lt;span class="na"&gt;Parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;KeyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;String&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name of an existing EC2 KeyPair to enable SSH access&lt;/span&gt;
  &lt;span class="na"&gt;ServerCertificateArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;String&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ARN of the ACM server certificate for the Client VPN endpoint&lt;/span&gt;
  &lt;span class="na"&gt;ClientCertificateArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;String&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ARN of the ACM client certificate for mutual authentication&lt;/span&gt;
  &lt;span class="na"&gt;LatestAmiId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS::SSM::Parameter::Value&amp;lt;AWS::EC2::Image::Id&amp;gt;'&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SSM parameter for the latest Amazon Linux 2 AMI&lt;/span&gt;

&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyVPC&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::VPC&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.0.0/16&lt;/span&gt;
      &lt;span class="na"&gt;EnableDnsSupport&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;EnableDnsHostnames&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;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyClientVPNVPC&lt;/span&gt;

  &lt;span class="na"&gt;MyPrivateSubnet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Subnet&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
      &lt;span class="na"&gt;CidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.0/24&lt;/span&gt;
      &lt;span class="na"&gt;MapPublicIpOnLaunch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;AvailabilityZone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Select&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;!GetAZs&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;

  &lt;span class="na"&gt;MyRouteTable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::RouteTable&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateRouteTable&lt;/span&gt;

  &lt;span class="na"&gt;MySubnetRouteTableAssociation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SubnetRouteTableAssociation&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;
      &lt;span class="na"&gt;RouteTableId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyRouteTable&lt;/span&gt;

  &lt;span class="na"&gt;MySecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow SSH from Client VPN&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSG&lt;/span&gt;

  &lt;span class="na"&gt;MyInstanceProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::IAM::InstanceProfile&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Roles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="nv"&gt;MyInstanceRole&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="na"&gt;MyInstanceRole&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::IAM::Role&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AssumeRolePolicyDocument&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2012-10-17'&lt;/span&gt;
        &lt;span class="na"&gt;Statement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;
            &lt;span class="na"&gt;Principal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;Service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ec2.amazonaws.com&lt;/span&gt;
            &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sts:AssumeRole&lt;/span&gt;
      &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/'&lt;/span&gt;
      &lt;span class="na"&gt;ManagedPolicyArns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore&lt;/span&gt;

  &lt;span class="na"&gt;MyEC2Instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Instance&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;InstanceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;t3.micro&lt;/span&gt;
      &lt;span class="na"&gt;KeyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;KeyName&lt;/span&gt;
      &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="nv"&gt;MySecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;IamInstanceProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyInstanceProfile&lt;/span&gt;
      &lt;span class="na"&gt;ImageId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;LatestAmiId&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyPrivateEC2&lt;/span&gt;

  &lt;span class="na"&gt;MyClientVPNEndpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::ClientVpnEndpoint&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AuthenticationOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;certificate-authentication&lt;/span&gt;
          &lt;span class="na"&gt;MutualAuthentication&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;ClientRootCertificateChainArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;ClientCertificateArn&lt;/span&gt;
      &lt;span class="na"&gt;ConnectionLogOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;ServerCertificateArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;ServerCertificateArn&lt;/span&gt;
      &lt;span class="na"&gt;ClientCidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10.0.0.0/22&lt;/span&gt;
      &lt;span class="na"&gt;DnsServers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8.8.8.8&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8.8.4.4&lt;/span&gt;
      &lt;span class="na"&gt;SplitTunnel&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;TagSpecifications&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ResourceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client-vpn-endpoint&lt;/span&gt;
          &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
              &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyClientVPNEndpoint&lt;/span&gt;

  &lt;span class="na"&gt;MyClientVPNAuthorizationRule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::ClientVpnAuthorizationRule&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ClientVpnEndpointId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyClientVPNEndpoint&lt;/span&gt;
      &lt;span class="na"&gt;TargetNetworkCidr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.0/24&lt;/span&gt; &lt;span class="c1"&gt;# Your VPC subnet&lt;/span&gt;
      &lt;span class="na"&gt;AuthorizeAllGroups&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;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow access to VPC subnet&lt;/span&gt;

&lt;span class="na"&gt;Outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VPC ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyVPC&lt;/span&gt;
  &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Private Subnet ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyPrivateSubnet&lt;/span&gt;
  &lt;span class="na"&gt;SecurityGroupId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Group ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MySecurityGroup&lt;/span&gt;
  &lt;span class="na"&gt;InstanceId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EC2 Instance ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyEC2Instance&lt;/span&gt;
  &lt;span class="na"&gt;ClientVpnEndpointId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Client VPN Endpoint ID&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyClientVPNEndpoint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To deploy this stack, you can use the AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation deploy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyClientVPNStack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; aws-client-vpn.yaml &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_NAMED_IAM &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--parameter-overrides&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;KeyName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_KEY_PAIR_NAME &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;ServerCertificateArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_SERVER_CERT_ARN &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;ClientCertificateArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_CLIENT_CERT_ARN &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;LatestAmiId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/aws/service/ami-amazon-linux-2/latest/amzn2-ami-hvm-x86_64-gp2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;YOUR_KEY_PAIR_NAME&lt;/code&gt;, &lt;code&gt;YOUR_SERVER_CERT_ARN&lt;/code&gt;, and &lt;code&gt;YOUR_CLIENT_CERT_ARN&lt;/code&gt; with your actual values.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Manual Step: Update Security Group Rule
&lt;/h3&gt;

&lt;p&gt;After the CloudFormation stack is deployed, you need to manually update the security group associated with your EC2 instance to allow ingress from the Client VPN. This step is crucial because the Client VPN endpoint assigns IP addresses from its own CIDR block (e.g., 10.0.0.0/22 in our template), and your EC2 instance's security group needs to explicitly allow traffic from this range.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Navigate to the EC2 console and find the security group created by the CloudFormation stack (e.g., &lt;code&gt;MyPrivateSG&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Go to the Inbound Rules tab and click &lt;code&gt;Edit inbound rules&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Add a new rule:

&lt;ul&gt;
&lt;li&gt;Type: All TCP (or specific ports like SSH if preferred)&lt;/li&gt;
&lt;li&gt;Source: Custom, and enter the Client VPN CIDR block (e.g., &lt;code&gt;10.0.0.0/22&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Description: Allow traffic from Client VPN.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; Save the rules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This manual step is necessary because CloudFormation does not inherently know the dynamically assigned Client VPN CIDR block at the time of stack creation, and it's a best practice to explicitly define ingress rules for security groups.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Authorize Clients to Access the Network
&lt;/h3&gt;

&lt;h3&gt;
  
  
  6. (Optional) Add Route to Enable Traffic from VPN to VPC
&lt;/h3&gt;

&lt;p&gt;To allow VPN clients to route traffic to your VPC, you need to add a route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 create-client-vpn-route &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--client-vpn-endpoint-id&lt;/span&gt; &amp;lt;VPN_ENDPOINT_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--destination-cidr-block&lt;/span&gt; 192.168.1.0/24 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-vpc-subnet-id&lt;/span&gt; &amp;lt;SUBNET_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;VPN_ENDPOINT_ID&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;SUBNET_ID&amp;gt;&lt;/code&gt; with your actual values. This is essential for traffic to flow from VPN clients to private resources in the VPC.&lt;/p&gt;

&lt;p&gt;Even after associating the Client VPN endpoint with a subnet, clients cannot access resources until authorization rules are defined. This rule specifies which network resources clients can access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 authorize-client-vpn-ingress &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--client-vpn-endpoint-id&lt;/span&gt; &amp;lt;VPN_ENDPOINT_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-network-cidr&lt;/span&gt; 192.168.1.0/24 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--authorize-all-groups&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Allow access to VPC subnet"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;VPN_ENDPOINT_ID&amp;gt;&lt;/code&gt; with the actual ID of your Client VPN endpoint, which you can get from the CloudFormation stack outputs or the AWS console. The &lt;code&gt;target-network-cidr&lt;/code&gt; should be the CIDR block of the subnet you want your VPN clients to access (e.g., &lt;code&gt;192.168.1.0/24&lt;/code&gt; for the private subnet in our CloudFormation template).&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying with AWS CLI (Alternate Method)
&lt;/h2&gt;

&lt;p&gt;For those who prefer a more granular approach or need to integrate into existing scripts, here are the AWS CLI commands to set up an AWS Client VPN. This section assumes you have already generated and imported your server and client certificates into ACM.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create Client VPN Endpoint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 create-client-vpn-endpoint &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--client-cidr-block&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/22"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--server-certificate-arn&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:acm:ap-south-1:123456789012:certificate/your-server-cert-id"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--authentication-options&lt;/span&gt; &lt;span class="nv"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;certificate-authentication,MutualAuthentication&lt;span class="o"&gt;={&lt;/span&gt;&lt;span class="nv"&gt;ClientRootCertificateChainArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:acm:ap-south-1:123456789012:certificate/your-client-cert-id"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--connection-log-options&lt;/span&gt; &lt;span class="nv"&gt;Enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--dns-servers&lt;/span&gt; &lt;span class="s2"&gt;"8.8.8.8"&lt;/span&gt; &lt;span class="s2"&gt;"8.8.4.4"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--split-tunnel&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=client-vpn-endpoint,Tags=[{Key=Name,Value=MyClientVPNEndpointCLI}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace the ARN values with your actual certificate ARNs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Associate Client VPN Endpoint with a Subnet
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 associate-client-vpn-target-network &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--client-vpn-endpoint-id&lt;/span&gt; &amp;lt;VPN_ENDPOINT_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; &amp;lt;SUBNET_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;VPN_ENDPOINT_ID&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;SUBNET_ID&amp;gt;&lt;/code&gt; with your respective IDs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Authorize Client VPN Ingress
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 authorize-client-vpn-ingress &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--client-vpn-endpoint-id&lt;/span&gt; &amp;lt;VPN_ENDPOINT_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target-network-cidr&lt;/span&gt; 192.168.1.0/24 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--authorize-all-groups&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Allow access to VPC subnet"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Revoke Client VPN Ingress (Optional)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 revoke-client-vpn-ingress &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--client-vpn-endpoint-id&lt;/span&gt; &amp;lt;VPN_ENDPOINT_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target-network-cidr&lt;/span&gt; 192.168.1.0/24 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--revoke-all-groups&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment Script
&lt;/h2&gt;

&lt;p&gt;To automate the deployment process, you can use a shell script. This script provides options to deploy an optional VPC and EC2 instance, deploy the Client VPN CloudFormation stack, automatically add the necessary security group rules, and includes a cleanup function to tear down the deployed resources. Make sure you have the &lt;code&gt;aws-client-vpn.yaml&lt;/code&gt;, &lt;code&gt;vpc-ec2.yaml&lt;/code&gt;, and &lt;code&gt;generate_certs.sh&lt;/code&gt; files in the same directory as this script.&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Variables (customize these)&lt;/span&gt;
&lt;span class="nv"&gt;STACK_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"MyClientVPNStack"&lt;/span&gt;
&lt;span class="nv"&gt;KEY_PAIR_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY_PAIR_NAME"&lt;/span&gt;
&lt;span class="nv"&gt;SERVER_CERT_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_SERVER_CERT_ARN"&lt;/span&gt;
&lt;span class="nv"&gt;CLIENT_CERT_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_CLIENT_CERT_ARN"&lt;/span&gt;
&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ap-south-1"&lt;/span&gt;
&lt;span class="nv"&gt;TARGET_NETWORK_CIDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"192.168.1.0/24"&lt;/span&gt;

&lt;span class="c"&gt;# 1. Deploy CloudFormation Stack&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deploying CloudFormation stack..."&lt;/span&gt;
aws cloudformation deploy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STACK_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--template-file&lt;/span&gt; aws-client-vpn.yaml &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_NAMED_IAM &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--parameter-overrides&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;KeyName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KEY_PAIR_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;ServerCertificateArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVER_CERT_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;ClientCertificateArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLIENT_CERT_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nv"&gt;LatestAmiId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/aws/service/ami-amazon-linux-2/latest/amzn2-ami-hvm-x86_64-gp2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"CloudFormation deployment failed. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"CloudFormation stack deployed successfully. Waiting for resources..."&lt;/span&gt;
aws cloudformation &lt;span class="nb"&gt;wait &lt;/span&gt;stack-create-complete &lt;span class="nt"&gt;--stack-name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STACK_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Ensure Client VPN endpoint is in available state&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Waiting for VPN endpoint to become available..."&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;15

&lt;span class="c"&gt;# Get Client VPN Endpoint ID from stack outputs&lt;/span&gt;
&lt;span class="nv"&gt;VPN_ENDPOINT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws cloudformation describe-stacks &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STACK_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Stacks[0].Outputs[?OutputKey==&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s2"&gt;ClientVpnEndpointId&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s2"&gt;].OutputValue"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VPN_ENDPOINT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Could not retrieve Client VPN Endpoint ID. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Client VPN Endpoint ID: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VPN_ENDPOINT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 2. Authorize Client VPN Ingress Rule&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Authorizing Client VPN ingress rule..."&lt;/span&gt;
aws ec2 authorize-client-vpn-ingress &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--client-vpn-endpoint-id&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VPN_ENDPOINT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-network-cidr&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TARGET_NETWORK_CIDR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--authorize-all-groups&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Allow access to VPC subnet"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to authorize client VPN ingress. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Client VPN ingress rule authorized successfully."&lt;/span&gt;

&lt;span class="c"&gt;# 3. Get Security Group ID from stack outputs&lt;/span&gt;
&lt;span class="nv"&gt;SECURITY_GROUP_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws cloudformation describe-stacks &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STACK_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Stacks[0].Outputs[?OutputKey==&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s2"&gt;SecurityGroupId&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s2"&gt;].OutputValue"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SECURITY_GROUP_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Could not retrieve Security Group ID. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Security Group ID: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SECURITY_GROUP_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 4. Get Client VPN CIDR Block&lt;/span&gt;
&lt;span class="nv"&gt;CLIENT_VPN_CIDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws ec2 describe-client-vpn-endpoints &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--client-vpn-endpoint-ids&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VPN_ENDPOINT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"ClientVpnEndpoints[0].ClientCidrBlock"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLIENT_VPN_CIDR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Could not retrieve Client VPN CIDR Block. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Client VPN CIDR Block: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLIENT_VPN_CIDR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 5. Add Ingress Rule to EC2 Security Group&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Adding ingress rule to EC2 Security Group..."&lt;/span&gt;
aws ec2 authorize-security-group-ingress &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--group-id&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SECURITY_GROUP_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 22 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cidr&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLIENT_VPN_CIDR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Allow SSH from Client VPN"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to add ingress rule to security group. Exiting."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ingress rule added to security group successfully."&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deployment complete!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Save the above script as &lt;code&gt;deploy_client_vpn.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Make it executable: &lt;code&gt;chmod +x deploy_client_vpn.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Customize the variables at the beginning of the script (&lt;code&gt;STACK_NAME&lt;/code&gt;, &lt;code&gt;KEY_PAIR_NAME&lt;/code&gt;, &lt;code&gt;SERVER_CERT_ARN&lt;/code&gt;, &lt;code&gt;CLIENT_CERT_ARN&lt;/code&gt;, &lt;code&gt;REGION&lt;/code&gt;, &lt;code&gt;TARGET_NETWORK_CIDR&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Run the script: &lt;code&gt;./deploy_client_vpn.sh&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;To avoid incurring unnecessary costs, it is important to clean up the AWS resources created by these CloudFormation stacks when they are no longer needed. You can delete the stacks using the AWS CLI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deleting the Client VPN Stack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation delete-stack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyClientVPNStack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the stack deletion to complete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation &lt;span class="nb"&gt;wait &lt;/span&gt;stack-delete-complete &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyClientVPNStack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deleting the VPC and EC2 Stack (if deployed)
&lt;/h3&gt;

&lt;p&gt;If you deployed the optional VPC and EC2 stack, you should delete it as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation delete-stack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyVPCAndEC2Stack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the stack deletion to complete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation &lt;span class="nb"&gt;wait &lt;/span&gt;stack-delete-complete &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyVPCAndEC2Stack &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Ensure that any associated resources (like EC2 instances, security groups, etc.) are properly terminated before attempting to delete the VPC, as CloudFormation might not delete resources that have dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Setting up an AWS Client VPN provides a secure and flexible way to access your AWS resources remotely. Whether you prefer the infrastructure-as-code approach with CloudFormation or the direct control of AWS CLI, both methods allow you to establish a robust VPN solution. Remember the crucial step of updating the security group ingress rules to ensure proper connectivity from your VPN clients to your target resources. The provided deployment script automates this process, streamlining your setup.&lt;/p&gt;

&lt;p&gt;Happy VPNing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Referrals
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html#mutual" rel="noopener noreferrer"&gt;Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/cvpn-getting-started.html" rel="noopener noreferrer"&gt;Getting started with Client VPN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;VPN Photo by &lt;a href="https://unsplash.com/@privecstasy" rel="noopener noreferrer"&gt;@privecstasy&lt;/a&gt; from &lt;a href="https://unsplash.com/photos/CXlqHmQy3MY" rel="noopener noreferrer"&gt;unsplash&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>My AWS Certified Security Specialty Certification Study Guide</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sat, 22 Mar 2025 04:34:13 +0000</pubDate>
      <link>https://forem.com/aws-builders/my-aws-certified-security-specialty-certification-study-guide-2cio</link>
      <guid>https://forem.com/aws-builders/my-aws-certified-security-specialty-certification-study-guide-2cio</guid>
      <description>&lt;p&gt;&lt;em&gt;Important: Having a solid foundation in AWS core services is essential. If you're new to AWS, I recommend completing the &lt;a href="https://aws.amazon.com/certification/certified-solutions-architect-associate/" rel="noopener noreferrer"&gt;AWS Certified Solutions Architect - Associate&lt;/a&gt; certification first.&lt;/em&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  1. Study Guide for AWS Security Specialty
&lt;/h6&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;No&lt;/th&gt;
&lt;th&gt;Course/Resource&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Comments&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.udemy.com/course/ultimate-aws-certified-security-specialty/" rel="noopener noreferrer"&gt;Stephane Maarek's Ultimate AWS Certified Security Specialty&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;4 weeks&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Comprehensive course with hands-on labs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a href="https://portal.tutorialsdojo.com/courses/aws-certified-security-specialty-practice-exams-scs-c02/" rel="noopener noreferrer"&gt;Tutorial Dojo Practice Exams&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2 weeks&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Highly recommended for exam preparation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;a href="https://explore.skillbuilder.aws/learn/courses/18291/exam-prep-standard-course-aws-certified-security-specialty-scs-c02-english" rel="noopener noreferrer"&gt;AWS Security Specialty Exam Readiness Course&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 week&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Essential AWS official prep material&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/kasukur/AWS_CCP_Notes/blob/main/AWS%20Security%20Speciality/AWS_Certified_Security_Speciality.md" rel="noopener noreferrer"&gt;AWS Certified Security - Specialty Study Notes&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 week&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Comprehensive community study notes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h6&gt;
  
  
  2. Essential AWS Security Workshops:
&lt;/h6&gt;

&lt;p&gt;Practice hands-on with these official AWS workshops:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://catalog.workshops.aws/security-hub/en-US" rel="noopener noreferrer"&gt;AWS Security Hub Workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://catalog.workshops.aws/identity/en-US" rel="noopener noreferrer"&gt;AWS Identity Workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://catalog.workshops.aws/networkfirewall/en-US" rel="noopener noreferrer"&gt;AWS Network Firewall Workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://catalog.workshops.aws/waf/en-US" rel="noopener noreferrer"&gt;AWS WAF Workshop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  3. Key Focus Areas:
&lt;/h6&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Identity and Access Management (IAM)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IAM policies and permissions&lt;/li&gt;
&lt;li&gt;IAM roles and federation&lt;/li&gt;
&lt;li&gt;AWS Organizations&lt;/li&gt;
&lt;li&gt;AWS SSO/IAM Identity Center&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Data Protection&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KMS and CloudHSM&lt;/li&gt;
&lt;li&gt;AWS Certificate Manager&lt;/li&gt;
&lt;li&gt;Secrets Manager&lt;/li&gt;
&lt;li&gt;AWS Shield and WAF&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Infrastructure Security&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC Security&lt;/li&gt;
&lt;li&gt;Network ACLs and Security Groups&lt;/li&gt;
&lt;li&gt;AWS Network Firewall&lt;/li&gt;
&lt;li&gt;AWS Security Hub&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Incident Response&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CloudWatch&lt;/li&gt;
&lt;li&gt;CloudTrail&lt;/li&gt;
&lt;li&gt;AWS Config&lt;/li&gt;
&lt;li&gt;Amazon Detective&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compliance and Audit&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Audit Manager&lt;/li&gt;
&lt;li&gt;AWS Control Tower&lt;/li&gt;
&lt;li&gt;AWS Artifact&lt;/li&gt;
&lt;li&gt;Amazon Macie&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h6&gt;
  
  
  FAQs:
&lt;/h6&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;How long does it take to prepare?&lt;br&gt;
With prior AWS experience, expect 2-3 months of dedicated study. Without significant AWS security experience, 4-6 months might be more realistic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What prerequisites are recommended?&lt;br&gt;
While not mandatory, having an AWS Associate-level certification (particularly Solutions Architect) provides a strong foundation for the security concepts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How is this exam different from Associate-level exams?&lt;br&gt;
This is a specialty exam focusing deeply on security services and concepts. Questions are typically more scenario-based and require detailed understanding of security implementations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What's the exam format?&lt;br&gt;
The exam consists of 65 questions to be completed in 170 minutes. Questions are multiple choice and multiple response.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h6&gt;
  
  
  Exam Tips:
&lt;/h6&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Focus on understanding security services in-depth, particularly IAM, KMS, and security-related aspects of VPC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practice with real-world scenarios through AWS workshops and labs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pay special attention to compliance frameworks and AWS's shared responsibility model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review AWS security whitepapers and best practices documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For non-native English speakers, you can request ESL+30 minutes accommodation through &lt;a href="https://www.certmetrics.com/amazon/" rel="noopener noreferrer"&gt;certmetrics&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h6&gt;
  
  
  Additional Resources:
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/security/" rel="noopener noreferrer"&gt;AWS Security Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/security/" rel="noopener noreferrer"&gt;AWS Security Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/architecture/security-identity-compliance/" rel="noopener noreferrer"&gt;AWS Security Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/whitepapers/?whitepapers-main.sort-by=item.additionalFields.sortDate&amp;amp;whitepapers-main.sort-order=desc&amp;amp;awsf.whitepapers-content-type=*all&amp;amp;awsf.whitepapers-tech-category=tech-category%23security-identity-compliance" rel="noopener noreferrer"&gt;AWS Security Whitepapers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Note: Keep in mind that AWS regularly updates its services and exam content. Always verify the latest exam guide from the official AWS Certification page before starting your preparation.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>certification</category>
      <category>security</category>
    </item>
    <item>
      <title>Deploying a Simple Static Website on AWS with CDK and TypeScript</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Wed, 01 Jan 2025 02:27:55 +0000</pubDate>
      <link>https://forem.com/aws-builders/deploying-a-simple-static-website-on-aws-with-cdk-and-typescript-oij</link>
      <guid>https://forem.com/aws-builders/deploying-a-simple-static-website-on-aws-with-cdk-and-typescript-oij</guid>
      <description>&lt;p&gt;You may have come across several blogs on hosting static websites on S3. This guide demonstrates how to create and deploy a simple static website using AWS CDK with TypeScript. The project will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up a basic AWS CDK project structure.&lt;/li&gt;
&lt;li&gt;Defining infrastructure as code (IaC) with TypeScript.&lt;/li&gt;
&lt;li&gt;Creating AWS resources necessary for hosting a static website.&lt;/li&gt;
&lt;li&gt;Deploying the website to AWS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The website source code is hosted on GitHub: &lt;a href="https://github.com/kasukur/cdk-s3-website" rel="noopener noreferrer"&gt;kasukur/cdk-s3-website&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Step 1: Initialize the Project&lt;/li&gt;
&lt;li&gt;Step 2: Create a Simple Website&lt;/li&gt;
&lt;li&gt;Step 3: Write CDK Code to Host the Website&lt;/li&gt;
&lt;li&gt;Step 4: Deploy the Website&lt;/li&gt;
&lt;li&gt;Full Command History&lt;/li&gt;
&lt;li&gt;Clean Up&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Referrals&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, ensure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; (&amp;gt;= 14.x)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt; (configured with credentials)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CDK&lt;/strong&gt; (&amp;gt;= 2.x)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install AWS CDK globally:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 1: Initialize the Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a project directory&lt;/strong&gt; and navigate to it:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;mkdir &lt;/span&gt;cdk-s3-website &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;cdk-s3-website
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialize a new CDK app&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; cdk init app &lt;span class="nt"&gt;--language&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install dependencies for the CDK constructs we'll use:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; @aws-cdk/aws-s3 @aws-cdk/aws-s3-deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify the setup by synthesizing the stack:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; cdk synth
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command generates the CloudFormation template for your stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Create a Simple Website
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download the website tempalte from &lt;a href="https://html5up.net/dimension/download" rel="noopener noreferrer"&gt;html5up.net&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;unzip the file, navigate to the folder and copy all the files to the website folder.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; ~/Downloads/html5up-dimension ~/Documents/cdk-s3-website/website/.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Write CDK Code to Host the Website
&lt;/h2&gt;

&lt;p&gt;Edit the &lt;code&gt;lib/cdk-s3-website-stack.ts&lt;/code&gt; file to define the resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3deploy&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-s3-deployment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CdkS3WebsiteStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create an S3 bucket for website hosting&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;websiteBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebsiteBucket&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="na"&gt;websiteIndexDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;publicReadAccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;removalPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RemovalPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DESTROY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Allow deletion of non-empty bucket&lt;/span&gt;
      &lt;span class="na"&gt;autoDeleteObjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Automatically delete objects when bucket is removed&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Deploy the website content to the S3 bucket&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3deploy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BucketDeployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DeployWebsite&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="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;s3deploy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
      &lt;span class="na"&gt;destinationBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;websiteBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Output the website URL&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CfnOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebsiteURL&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="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;websiteBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucketWebsiteUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Deploy the Website
&lt;/h2&gt;

&lt;p&gt;Run the following commands to deploy your website:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bootstrap the environment&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; cdk bootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You might noticed the following error:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; Error: Cannot use &lt;span class="s1"&gt;'publicReadAccess'&lt;/span&gt; property on a bucket           without allowing bucket-level public access through &lt;span class="s1"&gt;'blockPublicAccess'&lt;/span&gt; property.
at new Bucket &lt;span class="o"&gt;(&lt;/span&gt;/Users/sridharkasukurthy/Documents/cdk-s3-website/node_modules/aws-cdk-lib/aws-s3/lib/bucket.js:1:24460&lt;span class="o"&gt;)&lt;/span&gt;
     ...
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Troubleshooting: The error occurs because the &lt;code&gt;publicReadAccess: true&lt;/code&gt; property is used without explicitly allowing public access by disabling the &lt;code&gt;blockPublicAccess&lt;/code&gt; feature. AWS CDK enforces stricter controls to prevent unintended public access.&lt;/p&gt;

&lt;p&gt;Solution: To fix this, we need to configure the bucket to allow public access explicitly by setting the &lt;code&gt;blockPublicAccess&lt;/code&gt; feature.&lt;/p&gt;

&lt;p&gt;Updated Code:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3Deploy&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-s3-deployment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CdkS3WebsiteStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

     &lt;span class="c1"&gt;// Create an S3 bucket for the website with public access explicitly allowed&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;websiteBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SriSriWebsiteBucket&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="na"&gt;websiteIndexDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;publicReadAccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;removalPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RemovalPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DESTROY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Optional: Remove the bucket on stack deletion&lt;/span&gt;
       &lt;span class="na"&gt;blockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BlockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOCK_ACLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Allows public access but blocks ACLs&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;

     &lt;span class="c1"&gt;// Deploy website contents to the bucket&lt;/span&gt;
     &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3Deploy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BucketDeployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DeployWebsite&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="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;s3Deploy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
       &lt;span class="na"&gt;destinationBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;websiteBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;

     &lt;span class="c1"&gt;// Output the website URL&lt;/span&gt;
     &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CfnOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WebsiteURL&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="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;websiteBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucketWebsiteUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bootstrap the environment again&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; cdk bootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy the stack&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; cdk deploy
&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;Do you wish to deploy these changes (y/n)? y&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During deployment, the CDK will output the URL for the hosted website. You can access your site using this URL.&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Command History
&lt;/h2&gt;

&lt;p&gt;Here’s a reference of all commands used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;1  &lt;span class="nb"&gt;mkdir &lt;/span&gt;cdk-s3-website &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;cdk-s3-website
2  cdk init app &lt;span class="nt"&gt;--language&lt;/span&gt; typescript
3  npm &lt;span class="nb"&gt;install&lt;/span&gt; @aws-cdk/aws-s3 @aws-cdk/aws-s3-deployment
4  git clone https://github.com/kasukur/s3-website.git website
5  cdk synth
6  cdk bootstrap
7  cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqxmdm4gc9aelk1nwg68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqxmdm4gc9aelk1nwg68.png" alt="Image description" width="800" height="843"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Clean Up
&lt;/h2&gt;

&lt;p&gt;To avoid incurring unnecessary charges, delete the stack. If the &lt;code&gt;cdk destroy&lt;/code&gt; command fails due to non-empty buckets, empty the bucket manually or use the &lt;code&gt;autoDeleteObjects&lt;/code&gt; property in your stack as shown above:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Manually empty the bucket&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws s3 &lt;span class="nb"&gt;rm &lt;/span&gt;s3://&amp;lt;bucket-name&amp;gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Destroy the stack&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   cdk destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrated how to use AWS CDK with TypeScript to deploy a simple static website on AWS. The focus was on showcasing the CDK’s capabilities for infrastructure provisioning and deployment automation. You can now customize and expand upon this setup for more complex use cases.&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referrals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cdkworkshop.com/20-typescript/20-create-project/500-deploy.html" rel="noopener noreferrer"&gt;AWS CDK Create Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/60310575/how-to-add-s3-bucketpolicy-with-aws-cdk" rel="noopener noreferrer"&gt;How to Add S3 BucketPolicy with AWS CDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/62694166/how-to-force-delete-a-non-empty-s3-bucket-with-versioning-enabled" rel="noopener noreferrer"&gt;How to Force Delete a Non-Empty S3 Bucket with Versioning Enabled&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://debugthis.dev/cdk/2020-07-08-aws-cdk-errors/" rel="noopener noreferrer"&gt;Debugging AWS CDK Errors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cover Image by &lt;a href="https://unsplash.com/@glenncarstenspeters" rel="noopener noreferrer"&gt;@glenncarstenspeters&lt;/a&gt; from &lt;a href="https://unsplash.com/photos/person-using-macbook-pro-npxXWgQ33ZQ" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>aws</category>
      <category>cdk</category>
      <category>ts</category>
    </item>
    <item>
      <title>My AWS DevOps Engineer Professional Study Guide</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sat, 27 Apr 2024 12:56:10 +0000</pubDate>
      <link>https://forem.com/aws-builders/my-aws-devops-engineer-professional-study-guide-1p6c</link>
      <guid>https://forem.com/aws-builders/my-aws-devops-engineer-professional-study-guide-1p6c</guid>
      <description>&lt;p&gt;&lt;em&gt;Important: Complete both the courses and study material suggested in the &lt;a href="https://dev.to/kasukur/my-aws-sys-ops-associate-study-guide-1ogl"&gt;My AWS SysOps Associate study guide&lt;/a&gt; and &lt;a href="https://dev.to/aws-builders/my-aws-developer-associate-study-guide-298l"&gt;My AWS Developer Associate study guide&lt;/a&gt; first as this has some overlap. After you have completed these, then follow the study guide below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Please review the following in addition to my &lt;br&gt;
&lt;a href="https://github.com/kasukur/AWS_CCP_Notes/blob/main/AWS_DevOps_Engineer_Professional.txt" rel="noopener noreferrer"&gt;AWS DevOps Engineer Professional Notes&lt;/a&gt;.&lt;/p&gt;
&lt;h6&gt;
  
  
  1. My Study Guide for AWS DevOps Engineer Professional
&lt;/h6&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;No&lt;/th&gt;
&lt;th&gt;Course&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Comments&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.udemy.com/course/aws-certified-devops-engineer-professional-hands-on/?couponCode=NVDPPOT42722" rel="noopener noreferrer"&gt;Stephane's AWS Certified DevOps Engineer Professional&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;15 days&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Preferable if you have all three associate certifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a href="https://tutorialsdojo.com/courses/aws-certified-devops-engineer-professional-practice-exams/" rel="noopener noreferrer"&gt;Tutorial Dojo Practice Exams&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;7 days&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Highly recommend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.udemy.com/course/aws-certified-devops-engineer-professional-practice-exam-dop/?couponCode=NVDPPOT42722" rel="noopener noreferrer"&gt;Stephane Maarek Practice Exams&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 day&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Highly recommend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.udemy.com/course/aws-certified-devops-engineer-professional-practice-exams-course/?couponCode=NVDPPOT42722" rel="noopener noreferrer"&gt;Neal Davis Practice Exams&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;2 days&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;Highly recommend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;a href="https://explore.skillbuilder.aws/learn/course/internal/view/elearning/16512/exam-prep-enhanced-course-aws-certified-devops-engineer-professional-dop-c02-english" rel="noopener noreferrer"&gt;AWS SkillBuilder - Exam Prep Standard Course: AWS Certified DevOps Engineer - Professional&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 week&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;You MUST COMPLETE this course before taking the exam.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;a href="https://wmx-api-production.s3.amazonaws.com/courses/56802/supplementary/AWS%20Exam%20Preparation%20Official%20Practice%20Question%20Sets%20Overview%20and%20Instructions.pdf" rel="noopener noreferrer"&gt;AWS SkillBuilder - AWS Exam Preparation Official Practice Question Sets Overview and Instructions.pdf&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;Completed&lt;/td&gt;
&lt;td&gt;You MUST COMPLETE this course before taking the exam.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.whizlabs.com/aws-devops-certification-training/" rel="noopener noreferrer"&gt;Whizlabs - Hands-on Labs&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;7 days&lt;/td&gt;
&lt;td&gt;some labs&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h6&gt;
  
  
  2. AWS Workshops for DevOps:
&lt;/h6&gt;

&lt;p&gt;AWS DevOps Engineer Professional Exam tests your hands on experience, So I highly recommend you gain some hands on experience using the following workshops:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://catalog.us-east-1.prod.workshops.aws/workshops/752fd04a-f7c3-49a0-a9a0-c9b5ed40061b/en-US" rel="noopener noreferrer"&gt;Introduction to AWS Code Family&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://catalog.us-east-1.prod.workshops.aws/workshops/63320e83-6abc-493d-83d8-f822584fb3cb/en-US/" rel="noopener noreferrer"&gt;Building event-driven architectures on AWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://catalog.workshops.aws/cfn101/en-US" rel="noopener noreferrer"&gt;AWS CloudFormation Workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://catalog.workshops.aws/observability/en-US" rel="noopener noreferrer"&gt;One Observability Workshop&lt;/a&gt; - Focus on AWS CloudWatch&lt;/li&gt;
&lt;/ul&gt;
&lt;h6&gt;
  
  
  FAQs:
&lt;/h6&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Which video courses do I need to take?&lt;br&gt;
If you haven't completed all three associate certifications, then I recommend completing Stephane's Sys Ops and Developer Associate courses first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How long does it take to prepare?&lt;br&gt;
If you have completed Sys Ops and Developer Associate exams then probably a month or two. Otherwise you might need at least 4-6 months.&lt;br&gt;
It took me six months in total (part time and a bit on and off due to some other activities).&lt;br&gt;
I suggest taking the exam as soon as you can after completing the Associate level certifications as the concepts will be fresh in your mind and you would have built up the momentum to complete the next certification level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What if I do not feel confident to take the exam?&lt;br&gt;
I didn't feel confident even after completing the practice exams, so I took &lt;code&gt;AWS SkillBuilder - Exam Prep Standard Course: AWS Certified DevOps Engineer - Professional&lt;/code&gt; which helped me gain confidence. This course has precisely everything that is needed for the Professional exam (re:Invent videos, FAQs, blogs, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How is the Professional exam different to an Associate exam?&lt;br&gt;
The Professional exam is very different to the Associate exam as some of the questions are longer and some questions have two correct answers. It is important to pick the most appropriate answer based on the requirement in the question. Most importantly, AWS DevOps Engineer Professional exam tests your hands on experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What happens if I don't pass the practice exams? &lt;br&gt;
Try to score close to 70% in any practice exam in your first attempt. Don't be worried if you don't pass on your first attempt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What do I do if I discover that I still have some weak areas after doing the practice exams? &lt;br&gt;
During the practice exams, if you find any areas that you seem to be weak in, then read more about those particular services in the AWS documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What tools do I get to use during the exam at the test centre?&lt;br&gt;
I was given a pen and erasable sheet. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Where should I take the exam - online or at the test centre?&lt;br&gt;
You can take the exam anywhere but my preference is taking the test at a test center.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: I haven't included white-papers, FAQ's and workshops in this guide as I completed them during my preparation for the Associate exam.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h6&gt;
  
  
  3. AWS DevOps Engineer Professional Notes
&lt;/h6&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kasukur" rel="noopener noreferrer"&gt;
        kasukur
      &lt;/a&gt; / &lt;a href="https://github.com/kasukur/AWS_CCP_Notes" rel="noopener noreferrer"&gt;
        AWS_CCP_Notes
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AWS Certification Notes
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AWS Certification Preparation Notes&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;AWS Certified Cloud Practioner Notes&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;AWS Solution Architect Associate Notes&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;AWS Certified Developer Associate Notes&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;AWS Solution Architect Professional Notes&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;AWS DevOps Engineer Professional Notes&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://start.me/p/1kjb2D/new-page" rel="nofollow noopener noreferrer"&gt;AWS Workshops/Labs&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;More to follow...&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Disclaimer:&lt;/h2&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;The information has been taken from the content in &lt;a href="https://acloudguru.com/" rel="nofollow noopener noreferrer"&gt;acloudguru&lt;/a&gt; for AWS Solution Architect Associate.&lt;/p&gt;
&lt;p&gt;I highly recommend you to purchase the course from &lt;a href="https://acloudguru.com/" rel="nofollow noopener noreferrer"&gt;acloudguru&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The purpose of these notes is to help students with their revision prior to taking the certification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kasukur/AWS_CCP_Notes" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
 




&lt;h6&gt;
  
  
  4. Exam Tips
&lt;/h6&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;During the exam, I marked the questions I was unsure of for review. At the end of the exam, I had about 20 questions for review, which made me feel slightly confident that I might pass the exam.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that you don't leave any questions unanswered as there is no negative marking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is also very important to know the basics, the exam will test you on the basics as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DO NOT attempt to answer the questions based on key words alone, ensure you read all the answers as well.&lt;br&gt;
For example: Whenever we see cost, we tend to think of 'Reserved' but that may not always be the case for some scenarios.&lt;br&gt;
You will notice this when you do the live practice exams.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If English is your second language, you can request for ESL+30 mins before booking the exam from &lt;a href="https://www.certmetrics.com/amazon/" rel="noopener noreferrer"&gt;certmetrics&lt;/a&gt; &amp;gt; Request Exam Accomodations and wait for the approval. It might take a couple of days for the approval to come through.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;h6&gt;
  
  
  5. More AWS Labs
&lt;/h6&gt;

&lt;p&gt;&lt;a href="https://start.me/p/1kjb2D/new-page" rel="noopener noreferrer"&gt;AWS Labs/Workshops&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;This is a list of labs which you can use for further practice, using your own AWS account. This is optional as some of these labs are quite advanced.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>certification</category>
    </item>
    <item>
      <title>Auto Scale EC2 using SQS</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sat, 14 Jan 2023 21:00:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/auto-scale-ec2-using-sqs-306e</link>
      <guid>https://forem.com/aws-builders/auto-scale-ec2-using-sqs-306e</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Create an EC2 Instance Role&lt;/li&gt;
&lt;li&gt;Create a Key pair&lt;/li&gt;
&lt;li&gt;Create a Security Group&lt;/li&gt;
&lt;li&gt;Create an S3 Bucket&lt;/li&gt;
&lt;li&gt;Create an SQS queue&lt;/li&gt;
&lt;li&gt;Create a Cloud9 instance&lt;/li&gt;
&lt;li&gt;Create CloudWatch Alarms&lt;/li&gt;
&lt;li&gt;Create a Launch Template&lt;/li&gt;
&lt;li&gt;Create an Auto Scaling Group&lt;/li&gt;
&lt;li&gt;Verification and Monitoring&lt;/li&gt;
&lt;li&gt;Clean Up&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Referrals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this blog we are going to set up auto scaling of EC2 instances using the SQS ApproximateNumberOfMessagesVisible metric.&lt;/p&gt;

&lt;p&gt;AWS Auto Scaling monitors your applications and automatically adjusts capacity to maintain steady, predictable performance at the lowest possible cost. Using AWS Auto Scaling, it’s easy to set up application scaling for multiple resources across multiple services in minutes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Benefits
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Set up Scaling quickly.&lt;/li&gt;
&lt;li&gt;Make SMART scaling decisions.&lt;/li&gt;
&lt;li&gt;Automatically maintain performance.&lt;/li&gt;
&lt;li&gt;Pay only for what you need.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Let's get started with the demo.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1. Create an EC2 Instance Role
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to IAM &amp;gt; Roles &amp;gt; Click on &lt;strong&gt;Create role&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;EC2&lt;/strong&gt; under Common use case and Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;AmazonS3ReadOnlyAccess&lt;/strong&gt; and &lt;strong&gt;AmazonSQSFullAccess&lt;/strong&gt; and Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter Role name as &lt;strong&gt;EC2InstanceRoleForSQS&lt;/strong&gt; and Click &lt;strong&gt;Create role&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you may create a custom policy for SQS with the required permissions instead of using the managed policy &lt;strong&gt;AmazonSQSFullAccess&lt;/strong&gt; to provide the least amount of privileges.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;AmazonSQSFullAccess&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"sqs:*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;AmazonS3ReadOnlyAccess&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:Get*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:List*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3-object-lambda:Get*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3-object-lambda:List*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Trusted entities&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ec2.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2. Create a key pair
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Key Pairs (under Network &amp;amp; Security).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create key pair&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter Name as &lt;code&gt;auto-scale&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to the folder where the key pair is downloaded and run.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;chmod &lt;/span&gt;400 &amp;lt;key_pair_name&amp;gt;.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcj672rfyzguxznfuwi2t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcj672rfyzguxznfuwi2t.png" alt="Auto_Scale_Keypair" width="800" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Auto_Scale_Keypair&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3. Create a Security Group
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;We are going to create a Security Group for SSH.&lt;/li&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Security Groups &amp;gt; Create a new security group for your ALB, and set the following values:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;MyIPSSH-SG&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add an Inbound rule to allow &lt;code&gt;SSH (TCP 22)&lt;/code&gt; traffic from &lt;code&gt;My IP&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create security group&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbr62zaedgkg28yx8u12g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbr62zaedgkg28yx8u12g.png" alt="MyIPSSH-SG" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MyIPSSH-SG&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4. Create an S3 Bucket
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Click &lt;strong&gt;Create Bucket&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter the Bucket name as &lt;code&gt;autoscalescripts&lt;/code&gt;, add some random numbers to make the bucket name unique.&lt;/li&gt;
&lt;li&gt;Leave the rest of the settings as default and click &lt;strong&gt;Create Bucket&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Download &lt;code&gt;sendMessages.sh&lt;/code&gt; and &lt;code&gt;receiveMessages.sh&lt;/code&gt; from the &lt;a href="https://github.com/kasukur/auto-scale-ec2-using-sqs" rel="noopener noreferrer"&gt;github&lt;/a&gt; and upload them to the S3 bucket.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5. Create an SQS queue
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Simple Queue Service&lt;/strong&gt; and click &lt;strong&gt;Create queue&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Name&lt;/strong&gt; as &lt;code&gt;MyMessages&lt;/code&gt;, leave the rest as defaults and click &lt;strong&gt;Create queue&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2840jonlzd6rcvmtlhjr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2840jonlzd6rcvmtlhjr.png" alt="SQS_1" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0hc7eqa4g80wskip1i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0hc7eqa4g80wskip1i8.png" alt="SQS_2" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsrlwh25smnutkqh6nw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsrlwh25smnutkqh6nw4.png" alt="SQS_3" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cxuzg9jeq12ab6vi42x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cxuzg9jeq12ab6vi42x.png" alt="SQS_4" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_4&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6. Create a Cloud9 instance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Cloud9&lt;/strong&gt; &amp;gt; &lt;strong&gt;Create Environment&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Name&lt;/strong&gt; as &lt;code&gt;awscli&lt;/code&gt; and click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Open&lt;/strong&gt; under &lt;strong&gt;AWS Cloud9&lt;/strong&gt; &amp;gt; &lt;strong&gt;Environments&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When Cloud9 is ready, Click File &amp;gt; Upload Local Files... and then upload &lt;code&gt;sendMessages.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let's check the AWS CLI version.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
aws-cli/1.19.112 Python/2.7.18 Linux/4.14.301-224.520.amzn2.x86_64 botocore/1.20.112
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The script uses &lt;code&gt;jq&lt;/code&gt;, so we need to install &lt;code&gt;jq&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a Terminal and execute &lt;code&gt;sudo yum install jq -y&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute &lt;code&gt;chmod +x sendMessages.sh&lt;/code&gt; to provide the execute permissions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now run the script to send &lt;strong&gt;2000&lt;/strong&gt; messages to &lt;code&gt;MyMessages&lt;/code&gt; queue.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Alternatively you could use AWS CLI on your personal computer to send the messages.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7. Create CloudWatch Alarms
&lt;/h3&gt;

&lt;p&gt;We are going to create a ScaleOut Alarm to launch new instances when the &lt;strong&gt;ApproximateNumberOfMessagesVisible&lt;/strong&gt; is greater than &lt;strong&gt;500&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to CloudWatch &amp;gt; Alarms &amp;gt; Click &lt;strong&gt;Create alarm&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Select Metric&lt;/strong&gt;, search for &lt;strong&gt;SQS&lt;/strong&gt;, select &lt;strong&gt;SQS &amp;gt; Queue Metrics&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;MyMessages &amp;gt; ApproximateNumberOfMessagesVisible&lt;/strong&gt; and Click &lt;strong&gt;Select Metric&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Change &lt;strong&gt;Statistic&lt;/strong&gt; to &lt;strong&gt;Sum&lt;/strong&gt;, &lt;strong&gt;Period&lt;/strong&gt; to &lt;strong&gt;1 minute&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;Threshold type: &lt;strong&gt;Static&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Whenever ApproximateNumberOfMessagesVisible is...: &lt;strong&gt;Greater&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Define the threshold value: &lt;strong&gt;500&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Remove&lt;/strong&gt; under &lt;strong&gt;Notification&lt;/strong&gt; and Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter Alarm name as &lt;strong&gt;ScaleOut&lt;/strong&gt; and Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Alarm&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Similar to ScaleOut, we also need to create a ScaleIn Alarm to launch new instances when the &lt;strong&gt;ApproximateNumberOfMessagesVisible&lt;/strong&gt; is lesser than &lt;strong&gt;300&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select &lt;strong&gt;ScaleOut&lt;/strong&gt; from CloudWatch &amp;gt; Alarms, Click on &lt;strong&gt;Actions&lt;/strong&gt; and &lt;strong&gt;Copy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Change the following:

&lt;ul&gt;
&lt;li&gt;Whenever ApproximateNumberOfMessagesVisible is...: &lt;strong&gt;Lower&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Define the threshold value: &lt;strong&gt;300&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Remove&lt;/strong&gt; under &lt;strong&gt;Notification&lt;/strong&gt; and Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter Alarm name as &lt;strong&gt;ScaleIn&lt;/strong&gt; and Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Alarm&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 It is important to not have the same value for scale-in and scale-out thresholds. We should leave a gap between them to prevent oscillation.&lt;br&gt;
For example: let's say we have 3 instances, and the CPU goes to 60%, which triggers the +1 step scaling policy. If the load stays constant, it will now be distributed to all 4 instances and the average CPU will drop to around 45% and the scale-in alarm will go off. This will then keep happening in a loop until the load goes up or down sufficiently for one of the alarms to stay in the alarm state and the ASG to reache the min or max.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pt9c5atzk7rk9yg9bbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pt9c5atzk7rk9yg9bbo.png" alt="ScaleOut_CreateAlarm1" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5u55wcnn7n4rl9uxdig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5u55wcnn7n4rl9uxdig.png" alt="ScaleOut_CreateAlarm2" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fes5938dpg564pac6jefl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fes5938dpg564pac6jefl.png" alt="ScaleOut_CreateAlarm3" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finxbaifgkcyyy0d6ara4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finxbaifgkcyyy0d6ara4.png" alt="ScaleOut_CreateAlarm4" width="800" height="873"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk98eiuqaeibjpax72gmq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk98eiuqaeibjpax72gmq.png" alt="ScaleOut_CreateAlarm5" width="800" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcacp6l6siopwcwgbgds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcacp6l6siopwcwgbgds.png" alt="Image description" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm6&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwue82oizjtbp6t6hx1x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwue82oizjtbp6t6hx1x.png" alt="ScaleOut_CreateAlarm7" width="800" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm7&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0iozatxchop2oyfbfbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0iozatxchop2oyfbfbk.png" alt="ScaleOut_CreateAlarm7.1" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_CreateAlarm7.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46ribyq66ddw5msbj1a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46ribyq66ddw5msbj1a3.png" alt="ScaleIn_CreateAlarm1" width="800" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_CreateAlarm1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffon9gl7kgyjmi05weo9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffon9gl7kgyjmi05weo9k.png" alt="ScaleIn_CreateAlarm2" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_CreateAlarm2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15s0i1jkkbouohwxogt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15s0i1jkkbouohwxogt5.png" alt="ScaleIn_CreateAlarm3" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_CreateAlarm3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb93zwazzvilpgs4twq8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb93zwazzvilpgs4twq8s.png" alt="ScaleIn_CreateAlarm4" width="800" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_CreateAlarm4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrrxkco7eygw9d5am5i6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrrxkco7eygw9d5am5i6.png" alt="ScaleIn_CreateAlarm4.1" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_CreateAlarm4.1&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 8. Create a Launch Template
&lt;/h3&gt;

&lt;p&gt;We can use a Launch Template or Launch Configurations. Launch Template is preferred over Launch Configurations as we can have different versions of the template. Also we can't modify a Launch Configuration after we have created it.&lt;/p&gt;

&lt;p&gt;Create a Launch Template that will be used by the Auto Scaling group. The Launch Template defines what the instances are and how they are created.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Instances &amp;gt; Launch Templates.&lt;/li&gt;
&lt;li&gt;Create a new template, and name it &lt;code&gt;AutoScale-SQS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;AMI&lt;/code&gt;, and pick the &lt;code&gt;Amazon Linux&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the instance type as &lt;code&gt;t2.micro&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;key pair&lt;/code&gt; you created earlier.&lt;/li&gt;
&lt;li&gt;Select the &lt;code&gt;MyIPSSH-SG&lt;/code&gt; security group you created earlier.&lt;/li&gt;
&lt;li&gt;Expand Advanced Details, and select &lt;code&gt;EC2InstanceRoleForSQS&lt;/code&gt; Role under &lt;strong&gt;IAM instance profile&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Paste the following script under &lt;strong&gt;User data&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;Note: These are commands to install jq, AWS CLI, copy scripts from the S3 bucket and to execute receiveMessages.sh.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click Create Launch Template.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;View Launch templates&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;User data&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Please update the bucket name in the script.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# install jq&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;jq &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="c"&gt;# Update aws cli version&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/ec2-user
curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
unzip awscliv2.zip
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install &lt;span class="nt"&gt;--bin-dir&lt;/span&gt; /usr/local/bin &lt;span class="nt"&gt;--install-dir&lt;/span&gt; /usr/local/aws-cli &lt;span class="nt"&gt;--update&lt;/span&gt;
which aws
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /usr/local/bin/aws
aws &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# copy sendMessages.sh and receiveMessages.sh from S3&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp &lt;/span&gt;s3://sqssri/ &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt; &lt;span class="s2"&gt;"*"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt; &lt;span class="s2"&gt;"*.sh"&lt;/span&gt;
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /home/ec2-user/&lt;span class="k"&gt;*&lt;/span&gt;.sh
&lt;span class="nb"&gt;nohup&lt;/span&gt; ./receiveMessages.sh &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 As Launch Templates with User data are slow, it is recommended to create an AMI with the required software to improve the speed of instance initialisation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xbrn9ucrk4ppmti5prl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xbrn9ucrk4ppmti5prl.png" alt="LaunchTemplate1" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LaunchTemplate1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjgeub5zdtzcro7p2g8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjgeub5zdtzcro7p2g8v.png" alt="LaunchTemplate1.1" width="800" height="935"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LaunchTemplate1.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fye8vy4fvzxxjk6ujkhx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fye8vy4fvzxxjk6ujkhx7.png" alt="LaunchTemplate1.2" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LaunchTemplate1.2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq1oz6djdp5hundl6ceq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq1oz6djdp5hundl6ceq.png" alt="LaunchTemplate1.3" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LaunchTemplate1.3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2k1m4xq1xa827tyi67r3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2k1m4xq1xa827tyi67r3.png" alt="LaunchTemplate1.4" width="800" height="703"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LaunchTemplate1.4&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 9. Create an Auto Scaling Group
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Auto Scaling &amp;gt; Auto Scaling Groups&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Auto Scaling group&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Call the group &lt;code&gt;ASG-SQS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select Launch Template, and choose the template named &lt;code&gt;AutoScale-SQS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We are using &lt;code&gt;default VPC&lt;/code&gt;, which will be selected, so select &lt;code&gt;us-east-1a&lt;/code&gt; as subnet.&lt;/li&gt;
&lt;li&gt;Click Next.&lt;/li&gt;
&lt;li&gt;Leave the default for Health checks, which is &lt;code&gt;EC2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Leave the default for Configure advanced options and Click Next.&lt;/li&gt;
&lt;li&gt;For Group Size, enter the following values:

&lt;ul&gt;
&lt;li&gt;Desired Capacity: &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Minimum Capacity: &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Maximum Capacity: &lt;code&gt;4&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;We will not be adding Scaling policies here, so leave the default &lt;code&gt;None&lt;/code&gt; and Click Next.&lt;/li&gt;
&lt;li&gt;Click Next at &lt;code&gt;Add Notifications&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click Next at &lt;code&gt;Add tags&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click Create &lt;code&gt;Auto Scaling Group&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Auto Scaling &amp;gt; click &lt;code&gt;ASG-SQS&lt;/code&gt; and then click &lt;code&gt;Automatic scaling&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We are going to add two dynamic scaling policies, one for scale out and another one for scale in. Click &lt;strong&gt;Create dynamic scaling policy&lt;/strong&gt; and enter the following values and then Click &lt;strong&gt;Create&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Policy type: &lt;code&gt;Simple Scaling&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scaling policy name: &lt;code&gt;ScaleOut&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CloudWatch alarm: &lt;code&gt;ScaleOut&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Take the action: &lt;code&gt;Add&lt;/code&gt; with &lt;code&gt;1&lt;/code&gt; capacity units&lt;/li&gt;
&lt;li&gt;And then wait &lt;code&gt;60&lt;/code&gt; seconds before allowing another scaling activity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create dynamic scaling policy&lt;/strong&gt; and enter the following values and then Click &lt;strong&gt;Create&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Policy type: &lt;code&gt;Simple Scaling&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scaling policy name: &lt;code&gt;ScaleIn&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CloudWatch alarm: &lt;code&gt;ScaleIn&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Take the action: &lt;code&gt;Remove&lt;/code&gt; with &lt;code&gt;1&lt;/code&gt; capacity units&lt;/li&gt;
&lt;li&gt;And then wait &lt;code&gt;120&lt;/code&gt; seconds before allowing another scaling activity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 It is best practice to scale up fast and scale down slow. Hence we used 60 seconds to scale out and 120 seconds to scale in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkzh595bvg4q44v9x4c3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkzh595bvg4q44v9x4c3.png" alt="ASG1" width="800" height="837"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltpxo3028i289y907b3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltpxo3028i289y907b3g.png" alt="ASG2" width="800" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj75emf9kpsq8ajqt6lup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj75emf9kpsq8ajqt6lup.png" alt="ASG3" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhead3g2ex0o8v7wufxhg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhead3g2ex0o8v7wufxhg.png" alt="ASG4" width="800" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG4&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;ASG5&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;ASG6&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2nczeve56mfsg5x3nm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2nczeve56mfsg5x3nm8.png" alt="ASG7" width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG7&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo2i142vkuqlyd9j50el.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo2i142vkuqlyd9j50el.png" alt="ASG7.1" width="800" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG7.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yrbf6c9s39z6q1us0uo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yrbf6c9s39z6q1us0uo.png" alt="ASG7.2" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG7.2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94zljs854lutt51eu7vr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94zljs854lutt51eu7vr.png" alt="ASG8" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG8&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrmcytl7g9d0veax50x9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrmcytl7g9d0veax50x9.png" alt="ASG8.1_ScaleOut" width="800" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG8.1_ScaleOut&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fluk13ce7usne6sj96nxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fluk13ce7usne6sj96nxx.png" alt="ASG8.2_ScaleIn" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG8.2_ScaleIn&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswwi96gnopgfor4qtgsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswwi96gnopgfor4qtgsf.png" alt="ASG8.3_Dynamic_Scaling" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG8.3_Dynamic_Scaling&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 10. Verification and Monitoring
&lt;/h3&gt;

&lt;p&gt;We have populated the queue with 2000 messages and have an auto scaling group launch with a maximum of 4 instances. We will now be verifying it using Cloud Watch Alarms and Auto Scaling group's Activity.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to CloudWatch &amp;gt; Alarms &amp;gt; ScaleOut, the state of ScaleOut Alarm status will be &lt;code&gt;In alarm&lt;/code&gt; and the ScaleIn Alarm status will be &lt;code&gt;OK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After a period of 10 mins or so, you will notice 4 EC2 instances launched under EC2 &amp;gt; Auto Scaling groups &amp;gt; ASG-SQS &amp;gt; Activity.&lt;/li&gt;
&lt;li&gt;Monitor the messages in &lt;code&gt;MyMessages&lt;/code&gt; queue, the number of messages will reduce as they are processed by the EC2 instances.&lt;/li&gt;
&lt;li&gt;Navigate to CloudWatch &amp;gt; Alarms &amp;gt; ScaleIn, the state of ScaleIn Alarm status will be &lt;code&gt;In alarm&lt;/code&gt; and the ScaleOut Alarm status will be &lt;code&gt;OK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You will notice 3 EC2 instances terminated under EC2 &amp;gt; Auto Scaling groups &amp;gt; ASG-SQS &amp;gt; Activity when the messages are less than &lt;strong&gt;300&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How to verify that the SQS messages are being processed
&lt;/h4&gt;

&lt;p&gt;Log on to the EC2 Instance and then switch to the root user.&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="o"&gt;[&lt;/span&gt;ec2-user@ip-172-31-47-21 ~]&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute the following command, which will show the log file name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps xf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@ip-172-31-47-21 ~]# &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/cloud-init-output.log
Sleep &lt;span class="k"&gt;for &lt;/span&gt;1 second...
Sleep &lt;span class="k"&gt;for &lt;/span&gt;1 second...
Sleep &lt;span class="k"&gt;for &lt;/span&gt;1 second...
Sleep &lt;span class="k"&gt;for &lt;/span&gt;1 second...
^C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdto7k32ruxcj43mroww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdto7k32ruxcj43mroww.png" alt="Messages_in_the_queue" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Messages_in_the_queue&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0d81ihvzv12obsxlmwz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0d81ihvzv12obsxlmwz9.png" alt="ScaleOut_Alarm" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_Alarm&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegncwgp70ou8qpnr11hh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegncwgp70ou8qpnr11hh.png" alt="ScaleOut_Activity" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleOut_Activity&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qgq4iooufewhoz5t9wr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qgq4iooufewhoz5t9wr.png" alt="Processing_Messages" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Processing_Messages&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6e3aspvrglespoihu5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6e3aspvrglespoihu5a.png" alt="ScaleIn_Alarm" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_Alarm&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4bwqzluwjoisbjyeaio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4bwqzluwjoisbjyeaio.png" alt="ScaleIn_Activity" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ScaleIn_Activity&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxfm2pjbazi7ene2j651.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxfm2pjbazi7ene2j651.png" alt="Queue_is_Empty" width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Queue_is_Empty&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;👉 Auto Scaling Group Tip: When you do not want to have instances running or for Disaster Recovery purposes or to save costs, you may set the following inputs to &lt;strong&gt;Zero&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desired Capacity: &lt;code&gt;0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Minimum Capacity: &lt;code&gt;0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Maximum Capacity: &lt;code&gt;0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5u8aclozbbqtnp7whyg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5u8aclozbbqtnp7whyg6.png" alt="ASG_Tip" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ASG_Tip&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean Up
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Terminate &lt;code&gt;Cloud9&lt;/code&gt; EC2 instance.&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;ASG-SQS&lt;/code&gt; under &lt;code&gt;Auto Scaling groups&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;AutoScale-SQS&lt;/code&gt; under &lt;code&gt;Launch Templates&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;auto-scale&lt;/code&gt; under &lt;code&gt;Key Pairs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete Security Group &lt;code&gt;MyIPSSH-SG&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;EC2InstanceRoleForSQS&lt;/code&gt; Role under IAM.&lt;/li&gt;
&lt;li&gt;Delete S3 bucket &lt;code&gt;autoscalescripts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete SQS queue &lt;code&gt;MyMessages&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;👉 It is important to not have the same value for scale-in and scale-out thresholds. We should leave a gap between them to prevent oscillation.&lt;br&gt;
👉 The best practice is to scale up fast, and scale down slow.&lt;br&gt;
👉 Launching an EC2 instance might be slow if we have to install software, configure..etc during the scale out. One way to speed up the process is by creating an AMI with all the required software and then use that AMI in the Launch template.&lt;/p&gt;

&lt;p&gt;Hope you learnt something new from the above demo.&lt;/p&gt;

&lt;p&gt;See you next time 👋&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referrals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-using-sqs-queue.html" rel="noopener noreferrer"&gt;Scaling based on Amazon SQS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>community</category>
      <category>discuss</category>
    </item>
    <item>
      <title>AWS Simple Queue Service (SQS) 101 with a demo using AWS CLI</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sat, 07 Jan 2023 22:00:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/aws-simple-queue-service-sqs-101-with-a-demo-using-aws-cli-32dc</link>
      <guid>https://forem.com/aws-builders/aws-simple-queue-service-sqs-101-with-a-demo-using-aws-cli-32dc</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Standard vs FIFO Queue&lt;/li&gt;
&lt;li&gt;Queue Configuration&lt;/li&gt;
&lt;li&gt;Create a SQS queue&lt;/li&gt;
&lt;li&gt;Create a Cloud9 instance&lt;/li&gt;
&lt;li&gt;Challenge&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Referrals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this blog we are going to create a SQS queue using the AWS Console and then interact with it using &lt;code&gt;AWS CLI&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is SQS?
&lt;/h3&gt;

&lt;p&gt;Amazon Simple Queue Service (SQS) lets you send, store, and receive messages between software components at any volume, without losing messages or requiring other services to be available.&lt;/p&gt;

&lt;p&gt;Some of the use cases of SQS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increase application reliability and scale.&lt;/li&gt;
&lt;li&gt;Decouple microservices and process event-driven applications.&lt;/li&gt;
&lt;li&gt;Ensure work is completed cost-effectively and on time.&lt;/li&gt;
&lt;li&gt;Maintain message ordering with deduplication&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Standard vs FIFO Queue
&lt;/h4&gt;

&lt;p&gt;SQS offers two types of queues – Standard &amp;amp; FIFO queues&lt;br&gt;
Some of the major differences between the standard and the FIFO queues are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/aws-builders/sagemaker-and-amazon-stack-2jaa"&gt;https://dev.to/aws-builders/sagemaker-and-amazon-stack-2jaa&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  Message Order
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Standard queues provide best-effort ordering which ensures that messages are generally delivered in the same order as they are sent. Occasionally (because of the highly-distributed architecture that allows high throughput), more than one copy of a message might be delivered out of order.&lt;/li&gt;
&lt;li&gt;FIFO queues offer first-in-first-out delivery and exactly-once processing: the order in which messages are sent and received is strictly preserved.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Delivery
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Standard queues guarantees that a message is delivered at least once and duplicates can be introduced into the queue.&lt;/li&gt;
&lt;li&gt;FIFO queues ensure a message is delivered exactly once and remains available until a consumer processes and deletes it. The duplicates are not introduced into the queue.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Transactions Per Second (TPS)
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Standard queues allow nearly-unlimited number of transactions per second.&lt;/li&gt;
&lt;li&gt;FIFO queues are limited to 300 transactions per second per API action. However It can be increased to 3000 by using batching.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Queue Configuration
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The following is from AWS Console&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Visibility timeout:&lt;/em&gt;&lt;/strong&gt; Should be between 0 seconds and 12 hours (default: 30 seconds).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visibility timeout sets the length of time that a message received from a queue (by one consumer) will not be visible to the other message consumers.&lt;/li&gt;
&lt;li&gt;The visibility timeout begins when Amazon SQS returns a message. If the consumer fails to process and delete the message before the visibility timeout expires, the message becomes visible to other consumers. If a message must be received only once, your consumer must delete it within the duration of the visibility timeout.&lt;/li&gt;
&lt;li&gt;The default visibility timeout setting is 30 seconds. This setting applies to all messages in the queue. Typically, you should set the visibility timeout to the maximum time that it takes your application to process and delete a message from the queue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Message retention period:&lt;/em&gt;&lt;/strong&gt; Should be between 1 minute and 14 days (default: 4 days).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The message retention period is the amount of time that Amazon SQS retains a message that does not get deleted. Amazon SQS automatically deletes messages that have been in a queue for more than the maximum message retention period. The default retention period is 4 days. The retention period has a range of 60 seconds to 1,209,600 seconds (14 days).&lt;/li&gt;
&lt;li&gt;The expiration of a message is always based on its original enqueue timestamp. When a message is moved to a dead-letter queue, the enqueue timestamp remains unchanged. For example, if a message spends 1 day in the original queue before being moved to a dead-letter queue, and the retention period of the dead-letter queue is set to 4 days, the message is deleted from the dead-letter queue after 3 days. For this reason, we recommend that you always set the retention period of a dead-letter queue to be longer than the retention period of the original queue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Delivery delay:&lt;/em&gt;&lt;/strong&gt;  Should be between 0 seconds and 15 minutes (default: 0 seconds).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your consumers need additional time to process messages, you can delay each new message coming to the queue. The delivery delay is the amount of time to delay the first delivery of each message added to the queue. Any messages that you send to the queue remain invisible to consumers for the duration of the delay period. The default (minimum) delay for a queue is 0 seconds. The maximum is 15 minutes.&lt;/li&gt;
&lt;li&gt;For standard queues, the per-queue delay setting is not retroactive; changing the setting doesn't affect the delay of messages already in the queue.&lt;/li&gt;
&lt;li&gt;For FIFO queues, the per-queue delay setting is retroactive; changing the setting affects the delay of messages already in the queue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Maximum message size:&lt;/em&gt;&lt;/strong&gt; Should be between 1 KB and 256 KB (default: 256 KB).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can set the maximum message size for your queue. The smallest supported message size is 1 byte (1 character). The largest size is 262,144 bytes (256 KB). To send messages larger than 256 KB, you can use the Amazon SQS Extended Client Library for Java (&lt;a href="https://github.com/awslabs/amazon-sqs-java-extended-client-lib" rel="noopener noreferrer"&gt;https://github.com/awslabs/amazon-sqs-java-extended-client-lib&lt;/a&gt;). This library allows you to send an Amazon SQS message that contains a reference to a message payload in Amazon S3. The maximum payload size is 2 GB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Receive message wait time:&lt;/em&gt;&lt;/strong&gt; Should be between 0 and 20 seconds (default: 0 seconds).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The receive message wait time is the maximum amount of time that polling will wait for messages to become available to receive. The minimum value is zero seconds and the maximum value is 20 seconds.&lt;/li&gt;
&lt;li&gt;Long polling helps reduce the cost of using Amazon SQS by eliminating the number of empty responses (when there are no messages available for a ReceiveMessage request) and false empty responses (when messages are available but aren't included in a response). If a receive request collects the maximum number of messages, it returns immediately. It does not wait for the polling to time out.&lt;/li&gt;
&lt;li&gt;If you set the receive message wait time to zero, the receive requests use short polling.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Let's get started with the demo.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a SQS queue
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Simple Queue Service&lt;/strong&gt; and click &lt;strong&gt;Create queue&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Name&lt;/strong&gt; as &lt;code&gt;MyMessages&lt;/code&gt;, leave the rest as defaults and click &lt;strong&gt;Create queue&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2840jonlzd6rcvmtlhjr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2840jonlzd6rcvmtlhjr.png" alt="&amp;gt; SQS_4" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0hc7eqa4g80wskip1i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0hc7eqa4g80wskip1i8.png" alt="SQS_2" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsrlwh25smnutkqh6nw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsrlwh25smnutkqh6nw4.png" alt="SQS_3" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cxuzg9jeq12ab6vi42x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cxuzg9jeq12ab6vi42x.png" alt="SQS_4" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQS_4&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Cloud9
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Cloud9&lt;/strong&gt; &amp;gt; &lt;strong&gt;Create Environment&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Name&lt;/strong&gt; as &lt;code&gt;SQS&lt;/code&gt; and click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Open&lt;/strong&gt; under &lt;strong&gt;AWS Cloud9&lt;/strong&gt; &amp;gt; &lt;strong&gt;Environments&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's check aws cli version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
aws-cli/1.19.112 Python/2.7.18 Linux/4.14.301-224.520.amzn2.x86_64 botocore/1.20.112
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;jq is not installed by default on Cloud9.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;jq
bash: jq: &lt;span class="nb"&gt;command &lt;/span&gt;not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install jq by executing the following command.&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="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;jq &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to check if jq is installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;rpm &lt;span class="nt"&gt;-qa&lt;/span&gt;|grep jq
jq-1.5-1.amzn2.0.2.x86_64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;jq -help&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;jq
jq - commandline JSON processor &lt;span class="o"&gt;[&lt;/span&gt;version 1.5]
Usage: jq &lt;span class="o"&gt;[&lt;/span&gt;options] &amp;lt;jq filter&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;file...]

        jq is a tool &lt;span class="k"&gt;for &lt;/span&gt;processing JSON inputs, applying the
        given filter to its JSON text inputs and producing the
        filter&lt;span class="s1"&gt;'s results as JSON on standard output.
        The simplest filter is ., which is the identity filter,
        copying jq'&lt;/span&gt;s input to its output unmodified &lt;span class="o"&gt;(&lt;/span&gt;except &lt;span class="k"&gt;for
        &lt;/span&gt;formatting&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
        For more advanced filters see the jq&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt; manpage &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"man jq"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        and/or https://stedolan.github.io/jq

        Some of the options include:
         &lt;span class="nt"&gt;-c&lt;/span&gt;             compact instead of pretty-printed output&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-n&lt;/span&gt;             use &lt;span class="sb"&gt;`&lt;/span&gt;null&lt;span class="sb"&gt;`&lt;/span&gt; as the single input value&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-e&lt;/span&gt;             &lt;span class="nb"&gt;set &lt;/span&gt;the &lt;span class="nb"&gt;exit &lt;/span&gt;status code based on the output&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-s&lt;/span&gt;             &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;slurp&lt;span class="o"&gt;)&lt;/span&gt; all inputs into an array&lt;span class="p"&gt;;&lt;/span&gt; apply filter to it&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-r&lt;/span&gt;             output raw strings, not JSON texts&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-R&lt;/span&gt;             &lt;span class="nb"&gt;read &lt;/span&gt;raw strings, not JSON texts&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-C&lt;/span&gt;             colorize JSON&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nt"&gt;-M&lt;/span&gt;             monochrome &lt;span class="o"&gt;(&lt;/span&gt;don&lt;span class="s1"&gt;'t colorize JSON);
         -S             sort keys of objects on output;
         --tab  use tabs for indentation;
         --arg a v      set variable $a to value &amp;lt;v&amp;gt;;
         --argjson a v  set variable $a to JSON value &amp;lt;v&amp;gt;;
         --slurpfile a f        set variable $a to an array of JSON texts read from &amp;lt;f&amp;gt;;
        See the manpage for more options.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send a SQS message using AWS CLI&lt;/p&gt;

&lt;p&gt;In order to send a message to SQS, we need &lt;code&gt;queue-url&lt;/code&gt;.&lt;br&gt;
We could either hard code the &lt;code&gt;queue-url&lt;/code&gt; or retreive the &lt;code&gt;queue-url&lt;/code&gt; and then pass it to &lt;code&gt;send-message&lt;/code&gt;, &lt;code&gt;receive-message&lt;/code&gt; or &lt;code&gt;delete-message&lt;/code&gt;&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="c"&gt;# queueurl is required to send or receive messages from SQS&lt;/span&gt;

&lt;span class="c"&gt;# Note: AWS CLI and boto3 need to use legacy endpoint&lt;/span&gt;
&lt;span class="c"&gt;# If we use the AWS CLI or SDK for Python, we need to use the legacy endpoints from https://docs.aws.amazon.com/general/latest/gr/sqs-service.html.&lt;/span&gt;
&lt;span class="c"&gt;# Otherwise, you will get the following error&lt;/span&gt;
&lt;span class="c"&gt;# botocore.exceptions.ClientError: An error occurred (InvalidAddress) when calling the ReceiveMessage operation: The address https://eu-central-1.queue.amazonaws.com/ is not valid for this endpoint.&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;queueurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sqs get-queue-url &lt;span class="nt"&gt;--queue-name&lt;/span&gt; &lt;span class="s2"&gt;"MyMessages"&lt;/span&gt;|jq &lt;span class="s2"&gt;".QueueUrl"&lt;/span&gt;|sed &lt;span class="s2"&gt;"s/sqs.us-east-1.amazonaws.com/queue.amazonaws.com/g"&lt;/span&gt;|sed &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"queueurl:"&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;aws sqs send-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt; &lt;span class="nt"&gt;--message-body&lt;/span&gt; Message &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"MD5OfMessageBody"&lt;/span&gt;: &lt;span class="s2"&gt;"4c2a8fe7eaf24721cc7a9f0175115bd4"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"MessageId"&lt;/span&gt;: &lt;span class="s2"&gt;"614ec45a-82b8-4788-aed6-6f3d80051780"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;aws sqs receive-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"Messages"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Body"&lt;/span&gt;: &lt;span class="s2"&gt;"Message"&lt;/span&gt;, 
            &lt;span class="s2"&gt;"ReceiptHandle"&lt;/span&gt;: &lt;span class="s2"&gt;"AQEBxxUZvU5S1OP2VFBIY5bpg267ZQvSkX3n7jfV505VumHa2JCHo5BR/trRSCKOlhcLSyvJzBUBhq9TPHlQ4F4nQu839HruurRMMYCaaZBiiEdFnADm3EwEi8+Hj9YsmmGf0YL4ftlTyMHnJFjL9l06e7qZZyV8lWKv+q/mnEU8v69AumtvcS7OhmgAtUzQUqG+4/enJgt3WrN1eJiJRlmiUbDpV3VCGr7wQbU5C+GAmYjVNs+vNrMSzOceKFs3XQH6vwhNnnp1d3dJZzn+JEjpfx8g6INrq1LYShgg6cTUVygc2jXuQNBoSHP4Jx6szscdLm2P4gUD515UJ948nX/Zlsu90GZtfyGY5S4wzgl9oYpJcPLRV7z6ISnte0WKuK9cHPCEzmyGeERS1yC7YKXRNA=="&lt;/span&gt;, 
            &lt;span class="s2"&gt;"MD5OfBody"&lt;/span&gt;: &lt;span class="s2"&gt;"4c2a8fe7eaf24721cc7a9f0175115bd4"&lt;/span&gt;, 
            &lt;span class="s2"&gt;"MessageId"&lt;/span&gt;: &lt;span class="s2"&gt;"614ec45a-82b8-4788-aed6-6f3d80051780"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 If you run the command again with in the Visibility timeout of 30 secs, SQS will not send the message again.&lt;br&gt;
However if the message is not processed and deleted by the consumer, the message becomes visible to other consumers. If a message must be received only once, the consumer must delete it within the duration of the visibility timeout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;aws sqs receive-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;
Sri:~/environment &lt;span class="nv"&gt;$ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in order to delete the message, we need to retreive the &lt;code&gt;receipt-handle&lt;/code&gt; and then pass the &lt;code&gt;--receipt-handle&lt;/code&gt; to &lt;code&gt;sqs delete-message&lt;/code&gt;&lt;br&gt;
Since the output message is a JSON message and we only need &lt;code&gt;receipt-handle&lt;/code&gt;, we can use &lt;strong&gt;jq&lt;/strong&gt;, which is like sed for JSON data - you can use it to slice, filter, map and transform structured data in the same way that you would with sed, awk, grep and other linux tools.&lt;/p&gt;

&lt;p&gt;What does &lt;code&gt;get-queue-url&lt;/code&gt; do?&lt;br&gt;
It retreives &lt;code&gt;QueueUrl&lt;/code&gt; and then replaces the endpoint with a legacy endpoint and also removes double quotes from the &lt;code&gt;QueueUrl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following code snippet retrieves and deletes the message.&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;queueurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sqs get-queue-url &lt;span class="nt"&gt;--queue-name&lt;/span&gt; &lt;span class="s2"&gt;"MyMessages"&lt;/span&gt;|jq &lt;span class="s2"&gt;".QueueUrl"&lt;/span&gt;|sed &lt;span class="s2"&gt;"s/sqs.us-east-1.amazonaws.com/queue.amazonaws.com/g"&lt;/span&gt;|sed &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"queueurl:"&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;

&lt;span class="c"&gt;# receiptHandle is required to delete the message from SQS after the message is retreived&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;receiptHandle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sqs receive-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;|jq .Messages[0].ReceiptHandle|sed &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"receiptHandle:"&lt;/span&gt; &lt;span class="nv"&gt;$receiptHandle&lt;/span&gt;

&lt;span class="c"&gt;#echo -e "aws sqs delete-message --queue-url $queueurl --receipt-handle $receiptHandle --region us-east-1"&lt;/span&gt;
aws sqs delete-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt; &lt;span class="nt"&gt;--receipt-handle&lt;/span&gt; &lt;span class="nv"&gt;$receiptHandle&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's send a 100 messages to the SQS queue, retrieve them and then delete the messages using bash scripts.&lt;br&gt;
Open up two terminal windows on Cloud9 and use one to execute &lt;code&gt;./sendMessages.sh&lt;/code&gt; and the other for &lt;code&gt;./receiveMessages.sh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sendMessages.sh&lt;/em&gt;&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# queueurl is required to send or receive messages from SQS&lt;/span&gt;

&lt;span class="c"&gt;# Note: AWS CLI and boto3 need to use legacy endpoint&lt;/span&gt;
&lt;span class="c"&gt;# If we use the AWS CLI or SDK for Python, we need to use the legacy endpoints from https://docs.aws.amazon.com/general/latest/gr/sqs-service.html.&lt;/span&gt;
&lt;span class="c"&gt;# Otherwise, you will get the following error&lt;/span&gt;
&lt;span class="c"&gt;# botocore.exceptions.ClientError: An error occurred (InvalidAddress) when calling the ReceiveMessage operation: The address https://eu-central-1.queue.amazonaws.com/ is not valid for this endpoint.&lt;/span&gt;

&lt;span class="nv"&gt;queueurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sqs get-queue-url &lt;span class="nt"&gt;--queue-name&lt;/span&gt; &lt;span class="s2"&gt;"MyMessages"&lt;/span&gt;|jq &lt;span class="s2"&gt;".QueueUrl"&lt;/span&gt;|sed &lt;span class="s2"&gt;"s/sqs.us-east-1.amazonaws.com/queue.amazonaws.com/g"&lt;/span&gt;|sed &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"queueurl:"&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"aws sqs send-message --queue-url &lt;/span&gt;&lt;span class="nv"&gt;$queueurl&lt;/span&gt;&lt;span class="s2"&gt; --message-body Message --region us-east-1"&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;1..100&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;aws sqs send-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt; &lt;span class="nt"&gt;--message-body&lt;/span&gt; &lt;span class="s2"&gt;"Message-&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;receiveMessages.sh&lt;/em&gt;&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="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# queueurl is required to send or receive messages from SQS&lt;/span&gt;

&lt;span class="c"&gt;# Note: AWS CLI and boto3 need to use legacy endpoint&lt;/span&gt;
&lt;span class="c"&gt;# If we use the AWS CLI or SDK for Python, we need to use the legacy endpoints from https://docs.aws.amazon.com/general/latest/gr/sqs-service.html.&lt;/span&gt;
&lt;span class="c"&gt;# Otherwise, you will get the following error&lt;/span&gt;
&lt;span class="c"&gt;# botocore.exceptions.ClientError: An error occurred (InvalidAddress) when calling the ReceiveMessage operation: The address https://eu-central-1.queue.amazonaws.com/ is not valid for this endpoint.&lt;/span&gt;

&lt;span class="nv"&gt;queueurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sqs get-queue-url &lt;span class="nt"&gt;--queue-name&lt;/span&gt; &lt;span class="s2"&gt;"MyMessages"&lt;/span&gt;|jq &lt;span class="s2"&gt;".QueueUrl"&lt;/span&gt;|sed &lt;span class="s2"&gt;"s/sqs.us-east-1.amazonaws.com/queue.amazonaws.com/g"&lt;/span&gt;|sed &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"queueurl:"&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;1..100&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c"&gt;# receiptHandle is required to delete the message from SQS after the message is retreived&lt;/span&gt;
        &lt;span class="nv"&gt;receiptHandle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sqs receive-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt;|jq .Messages[0].ReceiptHandle|sed &lt;span class="s1"&gt;'s/"//g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;#echo "receiptHandle:" $receiptHandle&lt;/span&gt;

        &lt;span class="c"&gt;#echo -e "aws sqs delete-message --queue-url $queueurl --receipt-handle $receiptHandle --region us-east-1"&lt;/span&gt;
        aws sqs delete-message &lt;span class="nt"&gt;--queue-url&lt;/span&gt; &lt;span class="nv"&gt;$queueurl&lt;/span&gt; &lt;span class="nt"&gt;--receipt-handle&lt;/span&gt; &lt;span class="nv"&gt;$receiptHandle&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Sleep for 1 second..."&lt;/span&gt;
        &lt;span class="nb"&gt;sleep &lt;/span&gt;1
&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge
&lt;/h3&gt;

&lt;p&gt;There are some improvements which we can make to the above. I will leave this as a challenge for now.&lt;br&gt;
Please let me know in the comments if you have managed to solve it.&lt;br&gt;
I will provide an update in a comment at some point.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We can use &lt;code&gt;--max-number-of-messages (integer)&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The maximum number of messages to return. Amazon SQS never returns more messages than this value (however, fewer messages might be returned). Valid values: 1 to 10. Default: 1.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;jq query in the command also need to be updated to retrieve an array of &lt;code&gt;--receipt-handle&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bash script also need to store the returned array and loop through the array to delete all the messages returned by &lt;code&gt;--max-number-of-messages&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Clean Up
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Delete the &lt;code&gt;MyMessages&lt;/code&gt; Queue.&lt;/li&gt;
&lt;li&gt;Terminate &lt;code&gt;Cloud9&lt;/code&gt; EC2 instance.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We learned about &lt;code&gt;SQS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We also learned about &lt;code&gt;bash scripting&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See you next time 👋&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referrals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sqs/index.html" rel="noopener noreferrer"&gt;Amazon SQS API Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/74926354/botot3-with-sqs-the-address-queueurl-is-not-valid-for-this-endpoint" rel="noopener noreferrer"&gt;botot3 with sqs: the address 'QueueUrl' is not valid for this endpoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/general/latest/gr/sqs-service.html" rel="noopener noreferrer"&gt;Amazon Simple Queue Service endpoints and quotas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>How to set up Jenkins and a Pipeline on AWS</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sat, 31 Dec 2022 23:00:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/how-to-set-up-jenkins-and-a-pipeline-on-aws-2pak</link>
      <guid>https://forem.com/aws-builders/how-to-set-up-jenkins-and-a-pipeline-on-aws-2pak</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Create an IAM User&lt;/li&gt;
&lt;li&gt;Create a Key pair&lt;/li&gt;
&lt;li&gt;Create a Security Group&lt;/li&gt;
&lt;li&gt;Create an EC2 instance&lt;/li&gt;
&lt;li&gt;Install and Configure Jenkins&lt;/li&gt;
&lt;li&gt;Create a Pipeline&lt;/li&gt;
&lt;li&gt;Clean Up&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Referrals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this blog we are going to set up Jenkins on an EC2 instance and then set up a pipeline to copy a file from S3.&lt;br&gt;
We are going to start something very basic and enhance it as we move along.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Jenkins?
&lt;/h3&gt;

&lt;p&gt;Jenkins offers a simple way to set up a continuous integration or continuous delivery (CI/CD) environment for almost any combination of languages and source code repositories using pipelines, as well as automating other routine development tasks. While Jenkins doesn’t eliminate the need to create scripts for individual steps, it does give you a faster and more robust way to integrate your entire chain of build, test, and deployment tools than you can easily build yourself.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Jenkins Pipeline?
&lt;/h3&gt;

&lt;p&gt;Jenkins Pipeline is a suite of plugins which supports implementing and integrating continuous delivery pipelines into Jenkins.&lt;/p&gt;

&lt;p&gt;Pipeline provides an extensible set of tools for modeling simple-to-complex delivery pipelines &lt;code&gt;as code&lt;/code&gt; via the &lt;a href="https://www.jenkins.io/doc/book/pipeline/syntax" rel="noopener noreferrer"&gt;Pipeline domain-specific language (DSL) syntax&lt;/a&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Let's get started with the demo.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 1. Create an IAM User
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to IAM &amp;gt; Users &amp;gt; Click on &lt;strong&gt;Add users&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter User Name as JenkinsUser&lt;/li&gt;
&lt;li&gt;Select Access key - Programmatic access and Click &lt;strong&gt;Next: Permissions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click Attach existing policies directly and then &lt;strong&gt;Create policy&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In the Create policy window, Click on &lt;strong&gt;JSON&lt;/strong&gt; and add the following &lt;em&gt;JenkinsEC2Policy&lt;/em&gt; and save the policy as &lt;strong&gt;JenkinsEC2Policy&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select AmazonS3ReadOnlyAccess and  JenkinsEC2Policy under &lt;strong&gt;Attach existing policies directly&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next:Tags&lt;/strong&gt;, &lt;strong&gt;Next:Review&lt;/strong&gt; and then &lt;strong&gt;Create user&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the credentials &lt;strong&gt;.csv&lt;/strong&gt; file as we will need this during Jenkins configuration at Step 6. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;JenkinsEC2Policy&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stmt1312295543082"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeSpotInstanceRequests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:CancelSpotInstanceRequests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:GetConsoleOutput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:RequestSpotInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:RunInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:StartInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:StopInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:TerminateInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:CreateTags"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DeleteTags"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeInstanceTypes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeKeyPairs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeRegions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeImages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeAvailabilityZones"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeSecurityGroups"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeSubnets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"iam:ListInstanceProfilesForRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"iam:PassRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ec2:GetPasswordData"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga6tlhu1j86dq60kmvv0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga6tlhu1j86dq60kmvv0.png" alt="IAM_JenkinsUser1" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IAM_JenkinsUser1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8ayag4dtjl9yxj45gg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8ayag4dtjl9yxj45gg7.png" alt="IAM_JenkinsUser2" width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IAM_JenkinsUser2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvvvukxtn6q70ve32af9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvvvukxtn6q70ve32af9.png" alt="IAM_JenkinsUser3" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IAM_JenkinsUser3&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2. Create a key pair
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Key Pairs (under Network &amp;amp; Security).&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Create key pair&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to the folder where the key pair is downloaded and run.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;chmod &lt;/span&gt;400 &amp;lt;key_pair_name&amp;gt;.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvv4s38p2f973r366acce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvv4s38p2f973r366acce.png" alt="Jenkins_Keypair" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Keypair&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3. Create a Security Group
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;We are going to create a Security Group for SSH and Jenkins web access.&lt;/li&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Security Groups &amp;gt; Create a new security group for your ALB, and set the following values:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;JenkinsSG&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add an Inbound rule to allow &lt;code&gt;SSH (TCP 22)&lt;/code&gt; traffic from &lt;code&gt;My IP&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add another Inbound rule to allow &lt;code&gt;Custom (TCP 8080)&lt;/code&gt; traffic from &lt;code&gt;My IP&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyd59lgalp2vw509nhhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyd59lgalp2vw509nhhm.png" alt="Jenkins_SG" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_SG&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4. Create an EC2 instance
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; EC2 Dashboard &amp;gt; Click on &lt;strong&gt;Launch instance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Launch an instance with the following values as shown in the screenshots.&lt;/li&gt;
&lt;li&gt;When the instance state is Running, select the instance and click on Connect and then copy the connections details.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Connect to the instance.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"Jenkins-Keypair.pem"&lt;/span&gt; ec2-user@ec2-54-211-70-130.compute-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqrb3o7w58bcsmhsj5o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqrb3o7w58bcsmhsj5o0.png" alt="Jenkins_EC1" width="800" height="849"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_EC1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvoh8taye0u2m7cupxf9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvoh8taye0u2m7cupxf9w.png" alt="Jenkins_EC2" width="800" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_EC2&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5. Install and Configure Jenkins
&lt;/h4&gt;




&lt;h5&gt;
  
  
  Install Jenkins
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ensure that the software packages are up to date on the instance by executing the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo yum update –y
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the Jenkins repo using the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Import a key file from Jenkins-CI to enable installation from the package:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

[ec2-user ~]$ sudo yum upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Java:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo amazon-linux-extras install java-openjdk11 -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Jenkins:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo yum install jenkins -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable Jenkins service to auto start at boot:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo systemctl enable jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start Jenkins as a service:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo systemctl start jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can check the status of the Jenkins service using the command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo systemctl status jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Just in case we ever need to restart Jenkins during this setup/configuration.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user ~]$ sudo systemctl restart jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;




&lt;h5&gt;
  
  
  Configure Jenkins
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;Copy the &lt;strong&gt;Public IPv4 DNS&lt;/strong&gt; of EC2 instance and paste the URL as following in the browser
For Example:  &lt;a href="http://ec2-54-211-70-130.compute-1.amazonaws.com:8080" rel="noopener noreferrer"&gt;http://ec2-54-211-70-130.compute-1.amazonaws.com:8080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter the initialAdminPassword from &lt;code&gt;/var/lib/jenkins/secrets/initialAdminPassword&lt;/code&gt; and Click &lt;strong&gt;Continue&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user@ip-172-31-89-157 ~]$ sudo cat /var/lib/jenkins/secrets/initialAdminPassword
    671x0x5x3xxx46xxxxxx099x1xf0149x
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select Install suggested plugins.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the installation is complete, Create First Admin User will open. Enter your information, and then select &lt;strong&gt;Save&lt;/strong&gt; and &lt;strong&gt;Continue&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Dashboard&lt;/strong&gt;, select &lt;strong&gt;Manage Jenkins&lt;/strong&gt;, and then select &lt;strong&gt;Manage Plugins&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Available plugins&lt;/strong&gt;, Search and Select &lt;strong&gt;Amazon EC2&lt;/strong&gt; and then &lt;em&gt;**Install without restart&lt;/em&gt;*&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the installation is complete, Navigate back to &lt;strong&gt;Dashboard&lt;/strong&gt;, select &lt;strong&gt;Manage Jenkins&lt;/strong&gt;, select &lt;strong&gt;Manage nodes and clouds&lt;/strong&gt; and then click on &lt;strong&gt;Configure Clouds&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Add a new cloud&lt;/strong&gt;, and select &lt;strong&gt;Amazon EC2&lt;/strong&gt;. A new pop up window opens with more fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click Add under Amazon EC2 Credentials and Select &lt;strong&gt;Jenkins&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From the &lt;strong&gt;Jenkins Credentials Provider: Jenkins&lt;/strong&gt;, select &lt;strong&gt;AWS Credentials&lt;/strong&gt; as the Kind.&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Access Key ID&lt;/strong&gt;, &lt;strong&gt;Secret Access Key&lt;/strong&gt; from the key pair and Click &lt;strong&gt;Add&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll down to Region and select your Region.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click Add under &lt;strong&gt;EC2 Key Pair's Private Key&lt;/strong&gt; and Select &lt;strong&gt;Jenkins&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From the &lt;strong&gt;Jenkins Credentials Provider: Jenkins&lt;/strong&gt;, select &lt;code&gt;SSH Username with private key&lt;/code&gt; as the Kind and set the Username to &lt;code&gt;ec2-user&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Enter Directly&lt;/code&gt; under &lt;strong&gt;Private Key&lt;/strong&gt;, then select Add.&lt;/li&gt;
&lt;li&gt;Open the private key pair you created in the creating a key pair step and paste in the contents from &lt;code&gt;-----BEGIN RSA PRIVATE KEY-----&lt;/code&gt; to &lt;code&gt;-----END RSA PRIVATE KEY-----&lt;/code&gt;. Select &lt;strong&gt;Add&lt;/strong&gt; when completed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll down to &lt;strong&gt;Test Connection&lt;/strong&gt; and ensure it states &lt;code&gt;Success&lt;/code&gt; and then Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft07lvv80n4ojez5dbexg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft07lvv80n4ojez5dbexg.png" alt="Jenkins_Configure1" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcy8tzfxlohsgh547fl7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcy8tzfxlohsgh547fl7k.png" alt="Jenkins_Configure2" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbtt6p7u5zqbn2yo5xww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbtt6p7u5zqbn2yo5xww.png" alt="Jenkins_Configure3" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfwtd3drjvixrcz2gfq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfwtd3drjvixrcz2gfq0.png" alt="Jenkins_Configure4" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz56xkuvt3j8rjexotux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcz56xkuvt3j8rjexotux.png" alt="Jenkins_Configure5" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futg05l3slf9ehvy709i1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futg05l3slf9ehvy709i1.png" alt="Jenkins_Configure6" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure6&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiirlukkodtzj843zkbtu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiirlukkodtzj843zkbtu.png" alt="Jenkins_Configure7" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure7&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lijcvyowwk1x6mmkrxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lijcvyowwk1x6mmkrxk.png" alt="Jenkins_Configure8" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure8&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjoqh28y1ujnjsrbnju0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjoqh28y1ujnjsrbnju0.png" alt="Jenkins_Configure9" width="596" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure9&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcdie7hgad701yxct5ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcdie7hgad701yxct5ry.png" alt="Jenkins_Configure10" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure10&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekadyu6on2j1er4orw46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekadyu6on2j1er4orw46.png" alt="Jenkins_Configure10.1" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure10.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpaxchqzq9aeez6tv63c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpaxchqzq9aeez6tv63c.png" alt="Jenkins_Configure10.2" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure10.2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe93se75zqsxrwan4zzgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe93se75zqsxrwan4zzgp.png" alt="Jenkins_Configure11" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure11&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41ta102qob85j999xaf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41ta102qob85j999xaf3.png" alt="Jenkins_Configure11.1" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure11.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fly7937rs78c1pw9fhgmy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fly7937rs78c1pw9fhgmy.png" alt="Jenkins_Configure11.2" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure11.2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz98zpohy6nheunwc8kjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz98zpohy6nheunwc8kjx.png" alt="Jenkins_Configure12" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Configure12&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 6. Create a Pipeline
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Dashboard&lt;/strong&gt; &amp;gt; &lt;strong&gt;Manage Jenkins&lt;/strong&gt; and copy the &lt;strong&gt;ID&lt;/strong&gt; of &lt;strong&gt;IAM User&lt;/strong&gt; created in Step 1, which we need to replace &lt;code&gt;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&lt;/code&gt; with the &lt;strong&gt;ID&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Dashboard&lt;/strong&gt; &amp;gt; &lt;strong&gt;Manage Jenkins&lt;/strong&gt; &amp;gt; &lt;strong&gt;Plugin Manager&lt;/strong&gt; &amp;gt; Click on &lt;strong&gt;Available plugins&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;AWS Steps&lt;/strong&gt; and &lt;strong&gt;Install without restart&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Dashboard&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Job&lt;/strong&gt; &amp;gt; Enter &lt;code&gt;download-a-file-from-s3&lt;/code&gt; &amp;gt; Select &lt;strong&gt;Pipeline&lt;/strong&gt; and Click &lt;strong&gt;OK&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Scroll down to &lt;strong&gt;Pipeline&lt;/strong&gt;, add the following &lt;code&gt;Pipeline script&lt;/code&gt; and Click &lt;strong&gt;Save&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create an S3 bucket and copy some files to the bucket.&lt;/li&gt;
&lt;li&gt;Replace the &lt;code&gt;s3bucket&lt;/code&gt; with your bucket name and &lt;code&gt;filename&lt;/code&gt; with one of the files in your S3 bucket.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Dashboard&lt;/strong&gt; &amp;gt; &lt;strong&gt;download-a-file-from-s3&lt;/strong&gt; and Click on &lt;strong&gt;Build Now&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navigate to the latest &lt;strong&gt;Build History&lt;/strong&gt; link and check out the &lt;strong&gt;Console Output&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; 
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'S3download'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
        &lt;span class="o"&gt;{&lt;/span&gt;      
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;withAWS&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;region:&lt;/span&gt;&lt;span class="s1"&gt;'us-east-1'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;credentials:&lt;/span&gt;&lt;span class="s1"&gt;'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;
                &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;s3Download&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;file:&lt;/span&gt; &lt;span class="s2"&gt;"filename"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;bucket:&lt;/span&gt; &lt;span class="s1"&gt;'s3bucket'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffr298gqzb3rppfo0gx3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffr298gqzb3rppfo0gx3m.png" alt="Jenkins_Pipeline1" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Pipeline1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18iubvi3jnsvrtqa20es.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18iubvi3jnsvrtqa20es.png" alt="Jenkins_Pipeline2" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Pipeline2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8xax56wosfjrma4tfr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8xax56wosfjrma4tfr5.png" alt="Jenkins_Pipeline3" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Pipeline3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft516tiu5jkr7arapavwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft516tiu5jkr7arapavwx.png" alt="Jenkins_Pipeline4" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Pipeline4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following is the console log, which shows the pipeline has been successful. ✅&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Started by user Sri
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/download-a-file-from-s3
[Pipeline] {
[Pipeline] stage
[Pipeline] { (S3download)
[Pipeline] withAWS
Constructing AWS CredentialsSetting AWS region us-east-1 
[Pipeline] {
[Pipeline] s3Download
Downloading s3://s3bucket/ to file:/var/lib/jenkins/workspace/download-a-file-from-s3/receiveMessages.sh 
Finished: Downloading from s3bucket/
Download complete
[Pipeline] }
[Pipeline] // withAWS
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file that was copied from S3 to the EC2 instance. ✅&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user@ip-172-31-89-157 ~]$ ls -lrt /var/lib/jenkins/workspace/download-a-file-from-s3/
total 0
drwxr-xr-x 2 jenkins jenkins 55 Dec 31 03:45 receiveMessages.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run the build again, this time the build has failed with the following error ❓&lt;br&gt;
The error message suggests to use &lt;code&gt;set force=true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Started by user Sri
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/download-a-file-from-s3
[Pipeline] {
[Pipeline] stage
[Pipeline] { (S3download)
[Pipeline] withAWS
Constructing AWS CredentialsSetting AWS region us-east-1 
[Pipeline] {
[Pipeline] s3Download
Downloading s3://s3bucket/ to file:/var/lib/jenkins/workspace/download-a-file-from-s3/receiveMessages.sh/ 
Download failed due to existing target file; set force=true to overwrite target file
[Pipeline] }
[Pipeline] // withAWS
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
java.lang.RuntimeException: Target exists: file:/var/lib/jenkins/workspace/download-a-file-from-s3/receiveMessages.sh/
    at de.taimos.pipeline.aws.S3DownloadStep$Execution.run(S3DownloadStep.java:146)
    at de.taimos.pipeline.aws.S3DownloadStep$Execution.run(S3DownloadStep.java:113)
    at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:829)
Finished: FAILURE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we need to add &lt;code&gt;force:true&lt;/code&gt; as per the &lt;a href="https://plugins.jenkins.io/pipeline-aws/#plugin-content-s3download" rel="noopener noreferrer"&gt;Pipeline: AWS Steps documentation&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; 
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'S3download'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
        &lt;span class="o"&gt;{&lt;/span&gt;      
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;withAWS&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;region:&lt;/span&gt;&lt;span class="s1"&gt;'us-east-1'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;credentials:&lt;/span&gt;&lt;span class="s1"&gt;'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;
                &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;s3Download&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;file:&lt;/span&gt; &lt;span class="s2"&gt;"filename"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;bucket:&lt;/span&gt; &lt;span class="s1"&gt;'s3bucket'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;force:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build succeeded after adding &lt;code&gt;force:true&lt;/code&gt; and now we can run the build multiple times.&lt;/p&gt;

&lt;h5&gt;
  
  
  Now let's parameterise the destination foldername.
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Dashboard &amp;gt; download-a-file-from-s3 and click on &lt;strong&gt;Configure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;This project is parameterised&lt;/strong&gt; and then Add &lt;strong&gt;String&lt;/strong&gt; parameter&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Name&lt;/strong&gt; as &lt;code&gt;foldername&lt;/code&gt;, &lt;strong&gt;Default Valu&lt;/strong&gt; as &lt;code&gt;foldername&lt;/code&gt; and &lt;strong&gt;Save&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Build with Parameters&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to the latest &lt;strong&gt;Build History&lt;/strong&gt; link and check out the &lt;strong&gt;Console Output&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; 
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'S3download'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
        &lt;span class="o"&gt;{&lt;/span&gt;      
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;withAWS&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;region:&lt;/span&gt;&lt;span class="s1"&gt;'us-east-1'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;credentials:&lt;/span&gt;&lt;span class="s1"&gt;'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;
                &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"${foldername}"&lt;/span&gt; 
                    &lt;span class="n"&gt;s3Download&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;file:&lt;/span&gt; &lt;span class="s2"&gt;"${foldername}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;bucket:&lt;/span&gt; &lt;span class="s1"&gt;'s3bucket'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;force:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xyk8yztvoehas13a3r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xyk8yztvoehas13a3r7.png" alt="Jenkins_Pipeline_Parameter" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Pipeline_Parameter&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg9btgp61wxrp4u2e5lq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg9btgp61wxrp4u2e5lq.png" alt="Jenkins_Pipeline_Build-with-Parameters" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jenkins_Pipeline_Build-with-Parameters&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following is the console log, which shows the pipeline has been successful. ✅&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Started by user Sri
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/download-a-file-from-s3
[Pipeline] {
[Pipeline] stage
[Pipeline] { (S3download)
[Pipeline] withAWS
Constructing AWS CredentialsSetting AWS region us-east-1 
[Pipeline] {
[Pipeline] echo
s3files
[Pipeline] s3Download
Downloading s3://s3bucket/ to file:/var/lib/jenkins/workspace/download-a-file-from-s3/s3files 
Finished: Downloading from sqssri/
Download complete
[Pipeline] }
[Pipeline] // withAWS
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The files were copied to &lt;strong&gt;s3files&lt;/strong&gt; directory on the EC2 instance. ✅&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ec2-user@ip-172-31-89-157 ~]$ ls -lrt /var/lib/jenkins/workspace/download-a-file-from-s3/s3files 
total 8
-rw-r--r-- 1 jenkins jenkins 952 Dec 31 03:40 receiveMessages.sh
-rw-r--r-- 1 jenkins jenkins 646 Dec 31 03:40 sendMessages.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Clean Up
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Delete the &lt;code&gt;EC2&lt;/code&gt; instance.&lt;/li&gt;
&lt;li&gt;Delete the &lt;code&gt;JenkinsUser&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete the &lt;code&gt;key pair&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete the Security Group &lt;code&gt;JenkinsSG&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We learned how to install and configure Jenkins.&lt;/li&gt;
&lt;li&gt;We also learned about setting up the pipeline.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referrals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jenkins.io/doc/#jenkins-user-documentation" rel="noopener noreferrer"&gt;Jenkins User Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://plugins.jenkins.io/pipeline-aws/#plugin-content-s3download" rel="noopener noreferrer"&gt;Pipeline: AWS Steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>writing</category>
    </item>
    <item>
      <title>Elastic Beanstalk Demo: Auto Scaling with a shared load balancer</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sun, 25 Dec 2022 12:42:41 +0000</pubDate>
      <link>https://forem.com/aws-builders/elastic-beanstalk-demo-auto-scaling-with-a-shared-load-balancer-5n4</link>
      <guid>https://forem.com/aws-builders/elastic-beanstalk-demo-auto-scaling-with-a-shared-load-balancer-5n4</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Create a Security Group&lt;/li&gt;
&lt;li&gt;Create an Application Load Balancer&lt;/li&gt;
&lt;li&gt;Create Elastic Beanstalk Admin App&lt;/li&gt;
&lt;li&gt;Create Elastic Beanstalk Forum App&lt;/li&gt;
&lt;li&gt;Auto Scaling Verification&lt;/li&gt;
&lt;li&gt;Clean Up&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Referrals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;One of the users of the AWS Certified Global Community had this query which caught my attention and made me want to check it out and see If I could help solve their problem. While doing this, I actually learned about shared load balancer with Elastic Beanstalk application and found it quite interesting, so I would like to share my learning with you.&lt;/p&gt;

&lt;p&gt;With Elastic Beanstalk, you can quickly deploy and manage applications in the AWS Cloud without having to learn about the infrastructure that runs those applications. Elastic Beanstalk reduces management complexity without restricting choice or control. You simply upload your application, and Elastic Beanstalk automatically handles the details of capacity provisioning, load balancing, scaling, and application health monitoring. However, it becomes a bit difficult when we need to customise configurations such as Application Load Balancer, Listeners...etc&lt;/p&gt;

&lt;p&gt;The user wanted to deploy two Elastic Beanstalk applications, let's say one for an &lt;strong&gt;Admin&lt;/strong&gt; application and another one for &lt;strong&gt;Forum&lt;/strong&gt; application. The problem the user was facing was particularly during auto-scaling - there seemed to be two instances created instead of one when she terminated one instance.&lt;/p&gt;

&lt;p&gt;I'd like to share the demo below to show how to configure two different elastic Beanstalk applications using a shared load balancer and verify auto-scaling.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: We can only have a maximum of &lt;strong&gt;5&lt;/strong&gt; Target Groups per Action per Application Load Balancer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Let's get started with the demo.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1. Create a Security Group
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We are going to create a Security Group for Elastic Beanstalk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navigate to EC2 &amp;gt; Security Groups &amp;gt; Create a new security group for your ALB, and set the following values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;EBSSG&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add two Inbound rules to allow &lt;code&gt;HTTP&lt;/code&gt; traffic from &lt;code&gt;0.0.0.0/0&lt;/code&gt; (IPV4) and &lt;code&gt;::/0&lt;/code&gt; (IPV6)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;EBS Security Group&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ow00nvk1llzwfa3u5ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ow00nvk1llzwfa3u5ng.png" alt="EBS-ALB-SG"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Step 2. Create an Application Load Balancer
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to EC2 &amp;gt; Load Balancers.&lt;/li&gt;
&lt;li&gt;Click Create Load Balancer.&lt;/li&gt;
&lt;li&gt;Click the Create button under the Application Load Balancer and set the following values:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;SharedALB&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scheme: &lt;code&gt;internet-facing&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;IP address type: &lt;code&gt;ipv4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Load Balancer Protocol: &lt;code&gt;HTTP&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Port: &lt;code&gt;80&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Leave the default &lt;code&gt;VPC&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;us-east-1a&lt;/code&gt; and &lt;code&gt;us-east-1b&lt;/code&gt; AZs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click Next: Configure Security Settings. 

&lt;ul&gt;
&lt;li&gt;Note: Ignore the warning as we are not using HTTPS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;EBSALB&lt;/code&gt; and Click Next&lt;/li&gt;
&lt;li&gt;Configure Routing, enter the following values and then Click Next:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;EBS-TG&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Target type: &lt;code&gt;Instance&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Protocol: &lt;code&gt;HTTP&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Port: &lt;code&gt;80&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Path: &lt;code&gt;/index.html&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click Next: Register Targets.&lt;/li&gt;
&lt;li&gt;Click Next: Review.&lt;/li&gt;
&lt;li&gt;Click Create&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wait until the Application Load Balancer &lt;code&gt;SharedALB&lt;/code&gt; is Active.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Shared Application Load Balancer&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frruj98wd3fxifag1ni37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frruj98wd3fxifag1ni37.png" alt="Shared_ALB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Configure Security Options&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymp205xhhv8dku2refev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymp205xhhv8dku2refev.png" alt="EBS-Admin2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Configure Security Groups&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0b75en00vzk8cly5f2kp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0b75en00vzk8cly5f2kp.png" alt="EBS-Admin3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Configure Routing&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dept3yz5bifvhu6dv32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dept3yz5bifvhu6dv32.png" alt="EBS-Admin4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Register Targets&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0og2wte1ux6q9g3o6iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0og2wte1ux6q9g3o6iw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Review&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzunhyvwm94xct1v6912a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzunhyvwm94xct1v6912a.png" alt="EBS-Admin6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Application Load Balancer is Active&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkbdrfldc0964t31c9rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkbdrfldc0964t31c9rv.png" alt="ALB_Active"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Initial Listener Rules&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fg5rpvlppp07cqztsm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fg5rpvlppp07cqztsm7.png" alt="Initial_Listener_Rules"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3. Create Elastic Beanstalk Admin App
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Elastic Beanstalk &amp;gt; Environments.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Create a new environment&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Web server environment&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enter the following values:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;Admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Platform: &lt;code&gt;Node.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Upload your code&lt;/code&gt; and upload &lt;a href="https://github.com/kasukur/elasticbeanstalk-demo/blob/main/nodejs_admin.zip" rel="noopener noreferrer"&gt;nodejs_admin.zip&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Configure more options&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Note: Step 6, 7 and 8 should be done in the same order.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;High availability&lt;/code&gt; under &lt;code&gt;Presets&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Edit&lt;/code&gt; next to &lt;code&gt;Network&lt;/code&gt; and select same two &lt;code&gt;Availability Zones&lt;/code&gt; for &lt;code&gt;Load Balancer&lt;/code&gt;, &lt;code&gt;Instance settings&lt;/code&gt; and &lt;code&gt;Database settings&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Edit&lt;/code&gt; next to &lt;code&gt;Load Balancer&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Load balancer type: &lt;code&gt;Application Load Balancer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Type: &lt;code&gt;Shared&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Load balancer ARN: Select the ARN of &lt;code&gt;SharedALB&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;default&lt;/code&gt; under Processes and click &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Edit&lt;/code&gt; &amp;gt; enter Path as &lt;code&gt;/admin.html&lt;/code&gt; and click &lt;code&gt;Save&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Add Rule&lt;/code&gt; under &lt;code&gt;Rules&lt;/code&gt;, Enter &lt;code&gt;Name&lt;/code&gt; as &lt;code&gt;admin&lt;/code&gt;, &lt;code&gt;PathPattern&lt;/code&gt; as &lt;code&gt;/*&lt;/code&gt;, &lt;code&gt;Process&lt;/code&gt; as &lt;code&gt;default&lt;/code&gt; and click &lt;code&gt;Add&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Save&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Create Environment&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Wait for the environment to be create and then click on the application URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you need to make any changes to the code and create a zip on a Mac OS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /nodejs_admin
zip ../nodejs_admin &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; .[^.]&lt;span class="k"&gt;*&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;EBS Admin 1&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6732crlvx8mlh13k5a31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6732crlvx8mlh13k5a31.png" alt="EBS_Admin1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin 2.1&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsmjlbadqkl839fo8mrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsmjlbadqkl839fo8mrd.png" alt="EBS_Admin2.1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin 2.2&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1lwmhzcfsv88utykmh4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1lwmhzcfsv88utykmh4.png" alt="EBS_Admin2.2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin 3.1&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9d67h2hvq6x7czo3wwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9d67h2hvq6x7czo3wwa.png" alt="EBS_Admin3.1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS_Admin 3.2&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0ogdh9zck0hzti8o61l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0ogdh9zck0hzti8o61l.png" alt="EBS_Admin3.2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS_Admin 3.3&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0lrjkntsat52ccmo9kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0lrjkntsat52ccmo9kj.png" alt="EBS_Admin3.3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin 4.1&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlspioc97hzlb5pgef75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlspioc97hzlb5pgef75.png" alt="EBS_Admin4.1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin 4.2&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux9s752o75et8g7g3qu3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux9s752o75et8g7g3qu3.png" alt="EBS_Admin4.2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;you might notice this error if you do not select the shared load balancer&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfowpm7zjbu1h2afrq7l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfowpm7zjbu1h2afrq7l.png" alt="Caution_Error"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4. Create Elastic Beanstalk Forum App
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Elastic Beanstalk &amp;gt; Environments.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Create a new environment&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Web server environment&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enter the following values:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;Forum&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Platform: &lt;code&gt;Node.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Upload your code&lt;/code&gt; and upload &lt;a href="https://github.com/kasukur/elasticbeanstalk-demo/blob/main/nodejs_forum.zip" rel="noopener noreferrer"&gt;nodejs_forum.zip&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Configure more options&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Note: Step 6, 7 and 8 should be done in the same order.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;High availability&lt;/code&gt; under &lt;code&gt;Presets&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Edit&lt;/code&gt; next to &lt;code&gt;Network&lt;/code&gt; and select same two &lt;code&gt;Availability Zones&lt;/code&gt; for &lt;code&gt;Load Balancer&lt;/code&gt;, &lt;code&gt;Instance settings&lt;/code&gt; and &lt;code&gt;Database settings&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Edit&lt;/code&gt; next to &lt;code&gt;Load Balancer&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Load balancer type: &lt;code&gt;Application Load Balancer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Type: &lt;code&gt;Shared&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Load balancer ARN: Select the ARN of &lt;code&gt;SharedALB&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;default&lt;/code&gt; under Processes and click &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Edit&lt;/code&gt; &amp;gt; enter Path as &lt;code&gt;/forum.html&lt;/code&gt; and click &lt;code&gt;Save&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Add Rule&lt;/code&gt; under &lt;code&gt;Rules&lt;/code&gt;, Enter &lt;code&gt;Name&lt;/code&gt; as &lt;code&gt;admin&lt;/code&gt;, &lt;code&gt;PathPattern&lt;/code&gt; as &lt;code&gt;/*&lt;/code&gt;, &lt;code&gt;Process&lt;/code&gt; as &lt;code&gt;default&lt;/code&gt; and click &lt;code&gt;Add&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Save&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Create Environment&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Wait for the environment to be create and then click on the application URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you need to make any changes to the code and create a zip on a Mac OS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /nodejs_forum
zip ../nodejs_forum &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; .[^.]&lt;span class="k"&gt;*&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;EBS Forum 4.3&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcdqha83enxj22ty7ov1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcdqha83enxj22ty7ov1.png" alt="EBS_Forum4.3"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5. Auto Scaling Verification
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;EC2&lt;/code&gt; &amp;gt; &lt;code&gt;Instances&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Admin-env instance&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Instance State&lt;/code&gt; and &lt;code&gt;Terminate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Wait for a few minutes, the auto scaling group will launch a new instance for Admin application, which can be checked under &lt;code&gt;Auto Scaling Groups&lt;/code&gt; &amp;gt; &lt;code&gt;Activity&lt;/code&gt;
Note: There should only be one instance launched but not two.&lt;/li&gt;
&lt;li&gt;Similarly &lt;code&gt;Terminate&lt;/code&gt; the &lt;code&gt;Forum-env&lt;/code&gt; and there should new instance created in a few minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;EBS Environments&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcagtajdm2vj85gftnarp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcagtajdm2vj85gftnarp.png" alt="EBS-Envs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin Application&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4trpqxzq3rd3t8s15lzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4trpqxzq3rd3t8s15lzv.png" alt="EBS-Admin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin Application&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2klp6jc2ddse395t0nza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2klp6jc2ddse395t0nza.png" alt="EBS-Forum"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Application Load Balancer Listener Rules&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51mpd425gomme4bg6pes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51mpd425gomme4bg6pes.png" alt="ALB-Listener-Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EC2 Instances&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga2384u4i4pq3otoau3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga2384u4i4pq3otoau3b.png" alt="EC2_Instances"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Admin Auto Scaling Activity&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46dt2dhh2rmr4plkgi5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46dt2dhh2rmr4plkgi5g.png" alt="EBS-Admin-AS-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Forum Auto Scaling Activity&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy135lt2z9amox1513eze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy135lt2z9amox1513eze.png" alt="EBS-Admin-AS-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EC2 Instances: Only one new Admin instance&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7mtg181ord9j2v869sf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7mtg181ord9j2v869sf.png" alt="EBS-Admin-AS-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EC2 Instances: Forum Instance terminated manually and new instance created by Auto Scaling&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63qeuqr53n9dhcjoqmwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63qeuqr53n9dhcjoqmwx.png" alt="EBS-Admin-AS-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EBS Forum Auto Scaling Activity&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5yegdqkobwgv4umcfyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5yegdqkobwgv4umcfyn.png" alt="EBS-Admin-AS-5"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean Up
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Select each environment under &lt;code&gt;Elastic Beanstalk&lt;/code&gt; &amp;gt; &lt;code&gt;Environments&lt;/code&gt;, Select &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Terminate Environment&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select each application under &lt;code&gt;Elastic Beanstalk&lt;/code&gt; &amp;gt; &lt;code&gt;Applications&lt;/code&gt;, Select &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Delete Application&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;SharedALB&lt;/code&gt; under &lt;code&gt;Load Balancers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete Security Group &lt;code&gt;EBSSG&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After both environments are terminated, Empty and Delete S3 bucket prefixed with &lt;code&gt;elasticbeanstalk-us-east-1-...&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We learned how to deploy and configure different settings using Elastic Beanstalk.&lt;/li&gt;
&lt;li&gt;We also learned about shared application load balancer, which can save costs.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referrals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-alb-shared.html" rel="noopener noreferrer"&gt;Configuring a shared Application Load Balancer using the Elastic Beanstalk console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The application code is from &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/samples/nodejs.zip" rel="noopener noreferrer"&gt;Tutorials and samples&lt;/a&gt; and I have added admin.html and forum.html.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>elasticbeanstalk</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>AWS Community Builders – Christmas and New year 2023</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Mon, 19 Dec 2022 13:00:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/aws-community-builders-christmas-and-new-year-2023-oil</link>
      <guid>https://forem.com/aws-builders/aws-community-builders-christmas-and-new-year-2023-oil</guid>
      <description>&lt;h2&gt;
  
  
  What surprises you most about the community builders program?
&lt;/h2&gt;

&lt;p&gt;I always knew that it was an honour to be selected to the Community Builders program, but what really surprised me were the many benefits of being a part of this program such as access to learning resources, support and most importantly, networking and learning from other community builders.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s your background and your experience with AWS?
&lt;/h2&gt;

&lt;p&gt;About two years ago, there was a cloud project at work that I really wanted to be a part of, however I didn't have any cloud skills and therefore couldn't be considered for this role. As AWS was a pioneer as a cloud provider, I decided that I wanted to learn as much I could about AWS.&lt;/p&gt;

&lt;p&gt;I started my journey with AWS Certified Cloud Practitioner. On completing this certification, I felt encouraged to try my hand at other certifications. I decided to pursue all the Associate certifications and then continue on to the Solution Architect Professional.&lt;/p&gt;

&lt;p&gt;Since I have started my journey, I have grown significantly in my AWS skills. I feel very happy that I have been able to mentor people in the community who are just starting out in the cloud and are looking for support, like I was two years ago. On the work front, I made a presentation to my team about how they could get certified. I am also part of the Cloud Champion Network in my company.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the biggest benefit you see from the program?
&lt;/h2&gt;

&lt;p&gt;The biggest benefit is having access to the Slack channel and to builders worldwide.&lt;br&gt;
The best part about having access to other builders is the promptness in replying to questions we post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the next swag item that you would like to get?
&lt;/h2&gt;

&lt;p&gt;I would love to request an AWS Skill Builder subscription-based access, if possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you eating for dinner today? Share the recipe!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kale salad&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chop up kale and massage it with some salt, lime and apple cider vinegar.&lt;/li&gt;
&lt;li&gt;Add some dried cranberries.&lt;/li&gt;
&lt;li&gt;Slice a green apple and add it to the salad and enjoy! 🥗&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Is there anything else you would like to say about the community builders program in 2022?
&lt;/h2&gt;

&lt;p&gt;It is a one of a kind program and I absolutely love being part of this program.&lt;/p&gt;

</description>
      <category>cbchristmas2022</category>
    </item>
    <item>
      <title>Challenge: Display EC2 instances from all regions using Python and Boto3</title>
      <dc:creator>Sri</dc:creator>
      <pubDate>Sun, 18 Dec 2022 01:38:37 +0000</pubDate>
      <link>https://forem.com/aws-builders/challenge-display-ec2-instances-from-all-regions-using-python-and-boto3-409</link>
      <guid>https://forem.com/aws-builders/challenge-display-ec2-instances-from-all-regions-using-python-and-boto3-409</guid>
      <description>&lt;p&gt;This was an idea from the AWS Certified Global Community to create challenges by breaking a certain part of code, so the users can learn by fixing the code.&lt;/p&gt;

&lt;p&gt;I have written this second challenge for the AWS Certified Global Community and have also used it to mentor some of my mentees.&lt;br&gt;
I thought that it might be a good idea to share this with the broader community as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boto3&lt;/strong&gt; is the name of the Python SDK for AWS. It allows you to directly create, update, and delete AWS resources from your Python scripts.&lt;/p&gt;

&lt;p&gt;I agree that we have &lt;strong&gt;EC2 Global View&lt;/strong&gt;, which shows what we are trying to achieve. However this is more of a programming challenge on how to code using Python and Boto3.&lt;/p&gt;

&lt;p&gt;Let's start the challenge!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pre-Requisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda with Python 3.9&lt;/li&gt;
&lt;li&gt;Lambda Execution role with access to EC2 and CloudWatch access (IAM)&lt;/li&gt;
&lt;li&gt;It is preferable to have at least one EC2 instance in any of the regions (not mandatory though)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Step 1. Create an IAM Policy:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You could either let Lambda create an execution role and add the &lt;strong&gt;AmazonEC2ReadOnlyAccess&lt;/strong&gt; policy or you could create the following IAM policy and a role.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Replace [Region], [LambdaFunctionName] and [AccountID] in the Policy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;IAM Policy with the following access:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWSLambdaBasicExecution&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogGroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:logs:[Region]:[AccountID]:*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:PutLogEvents"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AmazonEC2ReadOnlyAccess&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ec2:Describe*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"elasticloadbalancing:Describe*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"cloudwatch:ListMetrics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"cloudwatch:GetMetricStatistics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"cloudwatch:Describe*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"autoscaling:Describe*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Step 2. Create a role for Lambda and attach the policy created in Step 1&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Trusted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;entities:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lambda.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Step 3. Broken Code:&lt;/strong&gt; Create a Lambda function with the following code and execute the function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Please increase the Lambda Function &lt;strong&gt;Timeout&lt;/strong&gt; under &lt;strong&gt;General Configuration&lt;/strong&gt; from &lt;strong&gt;3 sec&lt;/strong&gt; to &lt;strong&gt;2 min&lt;/strong&gt; or more as required.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;ec2list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# Get list of regions
&lt;/span&gt;    &lt;span class="n"&gt;ec2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'ec2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;regions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;describe_regions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Regions'&lt;/span&gt;&lt;span class="p"&gt;,[]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Iterate over regions
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;regions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"* Checking region  --   %s "&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'RegionName'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'RegionName'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'ec2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;describe_instances&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Instances"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Instances"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  ---- Instance %s in %s"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'InstanceId'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'RegionName'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
                &lt;span class="n"&gt;ec2list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'InstanceId'&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="s"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ec2list&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;blockquote&gt;
&lt;p&gt;Note: &lt;strong&gt;DO NOT&lt;/strong&gt; forget to deploy the Lambda function every time you make a change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;First Error:&lt;/strong&gt; We get the following error when we execute the code❓&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Response&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errorMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name 'boto3' is not defined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errorType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NameError"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6926f216-e0e8-4f25-bb16-761ada972e3f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stackTrace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"  File &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/var/task/lambda_function.py&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, line 8, in lambda_handler&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    ec2 = boto3.client('ec2')&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hint 1:&lt;/strong&gt;&lt;br&gt;
The first one is easy to solve by executing the code in Lambda, the hint appears in the error message.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Second Error:&lt;/strong&gt; We get the following error after fixing the first one❓&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Response&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errorMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'Instances'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errorType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KeyError"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"c78a6211-1d73-4d72-b83a-4c51bfd4e181"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stackTrace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"  File &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/var/task/lambda_function.py&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, line 21, in lambda_handler&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    for reservation in response[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Instances&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hint 2:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please refer to the Response Syntax of describe_instances(**kwargs) at &lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html?highlight=describe_instances#EC2.Client.describe_instances"&gt;Boto3 Documentation&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 4. Final Code:&lt;/strong&gt; ✅&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;ec2list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# Get list of regions
&lt;/span&gt;    &lt;span class="n"&gt;ec2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'ec2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;regions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;describe_regions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Regions'&lt;/span&gt;&lt;span class="p"&gt;,[]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Iterate over regions
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;regions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"* Checking region  --   %s "&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'RegionName'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'RegionName'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'ec2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;describe_instances&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Reservations"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Instances"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  ---- Instance %s in %s"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'InstanceId'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'RegionName'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
                &lt;span class="n"&gt;ec2list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'InstanceId'&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="s"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ec2list&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"I-[instanceid]"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;START&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RequestId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;f&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;381-51e2-43&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;9-8490&lt;/span&gt;&lt;span class="err"&gt;-a&lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;6394&lt;/span&gt;&lt;span class="err"&gt;dd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Version:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$LATEST&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;eu-north&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ap-south&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;eu-west&lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;eu-west&lt;/span&gt;&lt;span class="mi"&gt;-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;eu-west&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ap-northeast&lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ap-northeast&lt;/span&gt;&lt;span class="mi"&gt;-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ap-northeast&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;sa-east&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ca-central&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ap-southeast&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;ap-southeast&lt;/span&gt;&lt;span class="mi"&gt;-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;eu-central&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;us-east&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;----&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Instance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;instanceid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;us-east&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;us-east&lt;/span&gt;&lt;span class="mi"&gt;-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;us-west&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;region&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;--&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;us-west&lt;/span&gt;&lt;span class="mi"&gt;-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RequestId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;f&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;381-51e2-43&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;9-8490&lt;/span&gt;&lt;span class="err"&gt;-a&lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;6394&lt;/span&gt;&lt;span class="err"&gt;dd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;REPORT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;RequestId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;f&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;381-51e2-43&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;9-8490&lt;/span&gt;&lt;span class="err"&gt;-a&lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="mi"&gt;6394&lt;/span&gt;&lt;span class="err"&gt;dd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Duration:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15667.85&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Billed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Duration:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15668&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ms&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Memory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Size:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Memory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Used:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;MB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Duration:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;246.67&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The actual instance id is replaced with [instanceid] in the output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what have I done to break the code&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I removed &lt;code&gt;import boto3&lt;/code&gt; at &lt;code&gt;line no 2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Replaced &lt;code&gt;response["Reservations"]:&lt;/code&gt; with &lt;code&gt;response["Instances"]:&lt;/code&gt; at &lt;code&gt;line no 21&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope you liked the challenge! Please let me know your thoughts in the comments section.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: Please do check out the reference link as you will learn something about global services too with Boto3. 👇&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See you next time 👋&lt;/p&gt;




&lt;h3&gt;
  
  
  References:
&lt;/h3&gt;

&lt;p&gt;I learnt this from stackoverflow when I asked a question about &lt;a href="https://stackoverflow.com/questions/72837445/retrieve-list-of-buckets-from-all-regions-using-boto3"&gt;Retrieve list of buckets from all regions using boto3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you have also learnt something about retrieving S3 buckets from all regions using Boto3. &lt;/p&gt;




</description>
      <category>aws</category>
      <category>boto3</category>
      <category>ec2</category>
      <category>lambda</category>
    </item>
  </channel>
</rss>
