<?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: steve jones</title>
    <description>The latest articles on Forem by steve jones (@jones80_jones).</description>
    <link>https://forem.com/jones80_jones</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%2F317528%2F498401bc-9cb6-4bf5-8902-08eeb3285c1d.jpeg</url>
      <title>Forem: steve jones</title>
      <link>https://forem.com/jones80_jones</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jones80_jones"/>
    <language>en</language>
    <item>
      <title>🕹️ AWS-Powered Tetris: Building a Retro Game with Amazon Q and Amplify</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Sun, 15 Jun 2025 14:19:29 +0000</pubDate>
      <link>https://forem.com/aws-builders/aws-powered-tetris-building-a-retro-game-with-amazon-q-and-amplify-4pe6</link>
      <guid>https://forem.com/aws-builders/aws-powered-tetris-building-a-retro-game-with-amazon-q-and-amplify-4pe6</guid>
      <description>&lt;p&gt;There's something magical about the games we grew up with. The simple mechanics, the blocky graphics, and the maddeningly catchy music are etched into our collective memory. So when AWS announced the &lt;a href="https://community.aws/content/2y6egGcPAGQs8EwtQUM9KAONojz/build-games-challenge-build-classics-with-amazon-q-developer-cli" rel="noopener noreferrer"&gt;&lt;strong&gt;Build Games Challenge&lt;/strong&gt;&lt;/a&gt;, a global event to recreate these classics using modern AI tools, I knew I had to jump in.&lt;/p&gt;

&lt;p&gt;The mission was clear: build a retro-inspired game using the Amazon Q Developer CLI and document the journey. My choice? The undisputed king of puzzle games: &lt;strong&gt;Tetris&lt;/strong&gt;. But this wouldn't be just any clone. My vision was a full-stack, cloud-powered version with a real-time leaderboard, secure user authentication, and a slick, modern frontend.&lt;/p&gt;

&lt;p&gt;This is the story of how I brought a Soviet-era classic into the serverless age, with an AI coding assistant as my partner.&lt;/p&gt;

&lt;p&gt;If you want to just look at the code or play the game head over here:-&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sjramblings/amazonq-game-builder-challenge" rel="noopener noreferrer"&gt;https://github.com/sjramblings/amazonq-game-builder-challenge&lt;/a&gt;&lt;br&gt;
&lt;a href="https://tetrics.sjramblings.io/" rel="noopener noreferrer"&gt;https://tetrics.sjramblings.io/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Developer's Toolkit
&lt;/h2&gt;

&lt;p&gt;To bring this vision to life, I assembled a powerful trio of technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Q Developer CLI:&lt;/strong&gt; My AI pair programmer. This isn't just autocomplete; it's a generative AI assistant in the terminal that can generate code, refactor applications, and—as I discovered—even interpret images to debug UI issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Amplify:&lt;/strong&gt; The powerful backbone for the entire application. Amplify is a set of tools and services that makes building and deploying full-stack web and mobile apps on AWS incredibly efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phaser.js:&lt;/strong&gt; A popular and lightweight HTML5 game framework, perfect for the 2D game logic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Effective Prompting: How to Talk to Your AI
&lt;/h2&gt;

&lt;p&gt;Before diving into the code, it's worth sharing what I learned about &lt;em&gt;communicating&lt;/em&gt; with Amazon Q. A good prompt is the difference between a helpful suggestion and a game-changing solution.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be Specific and Provide Context:&lt;/strong&gt; My initial prompt wasn't just "build Tetris." It specified the tools (Phaser, AWS Amplify Sandbox), the goal (scoreboard, authentication), and the technology (DynamoDB, Cognito). This context is crucial.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Iterate and Refine:&lt;/strong&gt; Don't expect a perfect solution on the first try. Treat it like a conversation. When Q's first solution for the UI layout wasn't quite right, I didn't start over. I refined the prompt, saying "That's closer, but now it's not resizing..."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Its Own Language:&lt;/strong&gt; When I encountered a build error, I didn't try to describe it. I fed the entire raw error log directly to Q. It understands its own ecosystem's errors better than I can paraphrase them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Show, Don't Just Tell (Multi-modality):&lt;/strong&gt; The most powerful technique was using screenshots. Describing a visual bug is hard. Showing it is instant and unambiguous.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Chapter 1: The Foundation - From Zero to Live in Minutes
&lt;/h2&gt;

&lt;p&gt;Every great journey starts with a single step. For me, that meant scaffolding a basic project from a public &lt;a href="https://github.com/phaserjs/template-react" rel="noopener noreferrer"&gt;Phaser + React template&lt;/a&gt;. With the code cloned, it was time to bring in AWS.&lt;/p&gt;

&lt;p&gt;This is where Amplify's magic first shines. Instead of wrestling with infrastructure, the process was pure &lt;strong&gt;development automation&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I connected my GitHub repository to the Amplify console.&lt;/li&gt;
&lt;li&gt;Amplify instantly detected the Next.js framework and configured the optimal build settings.&lt;/li&gt;
&lt;li&gt;I clicked "Save and deploy."&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%2F3ouc2iajn6tnt6koftmj.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%2F3ouc2iajn6tnt6koftmj.png" alt="Amplify Deployment" width="800" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In just a few minutes, I had a live, globally accessible URL running my base template. This seamless CI/CD workflow gave me the confidence to iterate quickly.&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%2Fx4j42dzih5fuv4nixafo.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%2Fx4j42dzih5fuv4nixafo.png" alt="Amplify Public URL" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With my production pipeline set, I moved to local development. Here, I leveraged one of Amplify Gen 2's killer features: the Sandbox. By running a single command, I spun up a fully-featured, isolated cloud backend on my local machine.&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%2Fkohhrt2it59r9r876r80.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%2Fkohhrt2it59r9r876r80.png" alt="Amplify Sandbox" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This meant I could build and test new features, like my database and authentication, in a safe, disposable environment without affecting my live URL. It’s the perfect blend of local speed and cloud power.&lt;/p&gt;
&lt;h2&gt;
  
  
  Chapter 2: The Art of Conversation - Coding with an AI Partner
&lt;/h2&gt;

&lt;p&gt;With the foundation laid, it was time to build the game itself. I fired up the Amazon Q CLI with &lt;code&gt;q chat&lt;/code&gt; and began the conversation.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Initial Prompt: Setting the Stage
&lt;/h3&gt;

&lt;p&gt;A good prompt is the difference between a helpful suggestion and a game-changing solution. I learned to be specific and provide rich context.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My Prompt to Q: "I'm creating a game using the Phaser game engine. I'm working locally within an AWS Amplify Sandbox... Can you assess this repo and create a Tetris game with a scoreboard that logs users' scores into an appropriate AWS Amplify construct, such as DynamoDB? Enable Cognito for authentication so that we can track user scores."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Q didn't just spit out a monolithic code block. It acted like a seasoned developer, analysing my repo, modifying the Amplify data schema for a &lt;code&gt;Score&lt;/code&gt; table, and then generating the core game logic, React components, and AWS integration code. In a remarkably short time, Q had scaffolded a complete, playable application.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Reality of Development: Iterative Debugging
&lt;/h3&gt;

&lt;p&gt;But as any developer knows, the first draft is never the final one. The app was functional but needed refinement. This is where the iterative, conversational nature of Q truly shined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 1: Taming the UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initially, the app was a mess—the login form, game, and controls were all displayed at once.&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%2F3vrqhpuixj2aant89bkz.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%2F3vrqhpuixj2aant89bkz.png" alt="App with bad formatting" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Q's solution was a clean refactoring of my root React component, introducing state variables to conditionally render components—a foundational pattern that saved me from manually structuring the entire UI flow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AI-generated logic to control the UI flow&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsAuthenticated&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowAuth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;// ... later in the return statement&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showAuth&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AuthComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;showAuth&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PhaserGame&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenge 2: When an AI Can See&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The game canvas was stuck in the corner.&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%2Fvg3xumdum2zj3orq9xi3.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%2Fvg3xumdum2zj3orq9xi3.png" alt="Canvas Issue" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Describing a visual bug in text is difficult and imprecise. So, I used Q's most impressive feature: multi-modality.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My Prompt to Q: "I've taken a screenshot of the issue here /Screenshot-issue.png. Can you assess this and make the necessary updates?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Q &lt;em&gt;analysed the image&lt;/em&gt; and came back with a perfect diagnosis:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I can see the issue! The game canvas is not filling the screen properly... it's showing as a small rectangle in the upper left area. The RESIZE mode isn't working as expected."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It then generated the correct Phaser configuration to fix it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AI-generated Phaser scale manager configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Phaser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Phaser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Dynamically resizes to fill container&lt;/span&gt;
    &lt;span class="na"&gt;autoCenter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Phaser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Scale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CENTER_BOTH&lt;/span&gt; &lt;span class="c1"&gt;// Keeps it centered&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ... other scene and physics config&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However I had limited success with these changes. In the end I actually pasted the contents of a &lt;a href="https://medium.com/@tajammalmaqbool11/full-screen-size-and-responsive-game-in-phaser-3-e563c2d60eab" rel="noopener noreferrer"&gt;medium blog post&lt;/a&gt; into Q to provide guidance and it nailed it in a single shot! Impressive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 3: Conquering the Backend Beast&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final boss of bugs was a cryptic backend error: authenticated users couldn't save their scores. I fed the raw, intimidating error log to Q. It expertly diagnosed a conflict in my Amplify authorization rules, identifying that &lt;code&gt;allow.publicApiKey()&lt;/code&gt; and &lt;code&gt;allow.guest()&lt;/code&gt; were creating duplicate public access pathways. Q guided me to a clean solution using &lt;code&gt;identityPool&lt;/code&gt; as the default authorization mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// After (AI-suggested fix)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="cm"&gt;/*...*/&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authorizationModes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;defaultAuthorizationMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;identityPool&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The key change!&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fix, for a complex backend issue, was the ultimate proof of Q's capability. It saved me what could have been hours of documentation-diving and frustration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Final Touch: An AWS-Inspired Masterpiece
&lt;/h2&gt;

&lt;p&gt;With the game fully functional, it was time for a creative flourish. I asked Q to theme the game around AWS services. This was development automation at its most fun*&lt;em&gt;.&lt;/em&gt;* &lt;/p&gt;

&lt;p&gt;Q created a new "AWS TETRICS" mode, theming each piece after a service icon and color scheme: the &lt;strong&gt;I-piece&lt;/strong&gt; became an orange AWS Lambda function, the &lt;strong&gt;O-piece&lt;/strong&gt; a green Amazon S3 block, and so on. The result is a game that is not only fun but a visual celebration of the AWS ecosystem.&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%2Fi1p7bcf4yin4oyh54jl3.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%2Fi1p7bcf4yin4oyh54jl3.png" alt="App Screen 1" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtpeyohs4ga7gu638ftu.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%2Frtpeyohs4ga7gu638ftu.png" alt="App Screen 2" width="800" height="1033"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmkt92gshlehjotx2spt.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%2Frmkt92gshlehjotx2spt.png" alt="App Screen 3" width="800" height="1051"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwgur6lbs7sidzylzdcn.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%2Fvwgur6lbs7sidzylzdcn.png" alt="App Screen 4" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: A New Era of Development
&lt;/h2&gt;

&lt;p&gt;This challenge was full of fun. AWS Amplify provided the rock-solid, scalable foundation that allowed me to focus on building, not managing infrastructure. The seamless CI/CD and powerful Sandbox environment created a development workflow that was both fast and safe.&lt;/p&gt;

&lt;p&gt;But the star of the show was the Amazon Q Developer CLI. It was more than an assistant; it was a true collaborator. It can architect solutions, automate tedious tasks, and debug complex problems across the full stack—even by examining a picture. The future of development is here, and it lives in the command line.&lt;/p&gt;

&lt;p&gt;I hope this helps someone else. Cheers&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>buildgameschallenge</category>
      <category>amazonqdevcli</category>
    </item>
    <item>
      <title>Unlock the Hidden Power of VPC Sharing in AWS</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Mon, 22 May 2023 19:40:13 +0000</pubDate>
      <link>https://forem.com/aws-builders/unlock-the-hidden-power-of-vpc-sharing-in-aws-2oji</link>
      <guid>https://forem.com/aws-builders/unlock-the-hidden-power-of-vpc-sharing-in-aws-2oji</guid>
      <description>&lt;p&gt;As rightly stated &lt;a href="https://awsteele.com/blog/2022/01/02/shared-vpcs-are-underrated.html"&gt;here&lt;/a&gt; by Aidan Steele (AWS Hero), VPC Sharing appears to be the forgotten superpower.&lt;/p&gt;

&lt;p&gt;While I think it is probably more suited for the hybrid Enterprise, this article will show why we use it, its benefits, and what could still do with some work on the AWS side.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is VPC Sharing?
&lt;/h2&gt;

&lt;p&gt;VPC sharing is a feature that lets multiple accounts use a single Virtual Private Cloud (VPC). It's like a big, virtual playground where different accounts can deploy their applications and resources, while still keeping everything neatly separated.&lt;/p&gt;

&lt;p&gt;The cool thing is, you can have one account (the owner) manage the VPC, while others (participants) just get to enjoy the benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Why
&lt;/h2&gt;

&lt;p&gt;Everyone is all in on the multi-account strategy; however, especially in typical enterprises, not everyone is responsible for looking after networking.&lt;/p&gt;

&lt;p&gt;When I use the word networking, I'm talking VPC, Endpoints, IGW, Direct Connect, Managing IP CIDRS etc.&lt;/p&gt;

&lt;p&gt;Quite often internal application teams want to own, run &amp;amp; build within a space that is already provided and, of course, that is all doable with multiple accounts, VPCs all plumbed in through a Transit Gateway, however, VPC sharing does provide another angle for this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple Example
&lt;/h3&gt;

&lt;p&gt;Two application teams running workloads that need to communicate and be accessed from on-premise. A typical multi-account setup would look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N4DvQbMj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681303846288/6IS-dJ66V.png%3Fauto%3Dcompress%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N4DvQbMj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681303846288/6IS-dJ66V.png%3Fauto%3Dcompress%2520align%3D%2522center%2522" alt="Multi Account VPCs" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few key points about this design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Transfer Costs:&lt;/strong&gt; For anything that goes over the TGW we are going to get charged. We would probably be putting VPC Endpoints in each VPC so again more cost and duplication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational Overheads:&lt;/strong&gt; Some good security practices are going to require each application team to ensure that VPC Flowlogs are enabled, and monitored, that routes are propagated correctly and that we implement appropriate NACLs and security groups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a shared VPC
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SPixUGsL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681303864973/RoJC6Pi4O.png%3Fauto%3Dcompress%2520align%3D%2522center%2522" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SPixUGsL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1681303864973/RoJC6Pi4O.png%3Fauto%3Dcompress%2520align%3D%2522center%2522" alt="Shared VPC Multi Account" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few key points about this design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Transfer Costs:&lt;/strong&gt; As we are now within the same VPC, communication between App1 &amp;amp; 2 is only going to incur VPC data charges. If they happen to be in the same Availability Zone we get it for free.  &lt;/p&gt;

&lt;p&gt;As above, for anything that goes over the TGW we are going to get charged. We would probably be putting VPC Endpoints in the VPC but again only one set as they can be accessed by both our applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational Overheads:&lt;/strong&gt; Each application team is still responsible for their Security Groups however the VPC owner can now ensure that VPC Flowlogs are enabled and monitored, that routes are propagated correctly and implement appropriate NACLs for both applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The benefits
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Simplified management:&lt;/strong&gt; One VPC owner handles the overall VPC configuration, reducing the complexity of managing multiple VPCs across accounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource efficiency:&lt;/strong&gt; Share a single VPC across accounts, minimizing duplicate resources and enabling better resource utilization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost savings:&lt;/strong&gt; Consolidate resources and minimize network infrastructure expenses, leading to lower overall costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced security:&lt;/strong&gt; Maintain account-level isolation while sharing a common VPC, ensuring a secure and controlled environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved collaboration:&lt;/strong&gt; Facilitate seamless cooperation among teams or projects by enabling easy access to shared resources within the VPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  What still needs work
&lt;/h2&gt;

&lt;p&gt;So there are a few points that AWS still needs to address&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not all services support it:&lt;/strong&gt; This is a small list with the top offender being FSx for NetApp however anything that wants to control route table entries is going to trip you up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network Access Control Lists:&lt;/strong&gt; The VPC Owner will need to configure these on behalf of the participants or delegate access via an assumed role. Annoying but doable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Hub Checks:&lt;/strong&gt; It would seem that the VPC and Security Hub team don't have a good relationship as checks like FlowLogs are enabled and use of the EC2 API Private Endpoint will show as non-compliant for all participant accounts if you have the SecurityHub Best Practises enabled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I hope this post has shown you another way to share resources and work together in a secure and organized way using VPC Sharing. It's a great solution for teams or projects that want to collaborate without the headache of managing multiple VPCs!&lt;/p&gt;

&lt;p&gt;I hope this helps someone else!&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>aws</category>
      <category>vpc</category>
    </item>
    <item>
      <title>Route 53 Resolver Magic</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Mon, 22 May 2023 19:36:39 +0000</pubDate>
      <link>https://forem.com/aws-builders/route-53-resolver-magic-2f28</link>
      <guid>https://forem.com/aws-builders/route-53-resolver-magic-2f28</guid>
      <description>&lt;p&gt;This post covers some core concepts of Route 53 Resolvers and how they can help establish inbound and outbound name resoltion with your on-premise and AWS resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Route 53 resolvers are a feature of Route 53 that allows you to route DNS queries between your VPC and your on-premises network.&lt;/p&gt;

&lt;p&gt;This feature lets you resolve domain names hosted within your VPCs and across your hybrid cloud environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Route 53 Resolvers are associated with a region as they are hosted in a VPC, unlike most of the Route 53 service, which is global.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Resolver Types
&lt;/h2&gt;

&lt;p&gt;There are two main types of Route 53 resolvers: inbound and outbound. Both work by forwarding DNS queries to the appropriate DNS servers.&lt;/p&gt;

&lt;p&gt;When your device sends a DNS query for a domain name, the resolver will check its cache to see if it already has the IP address for that domain name. If it doesn't, the resolver will forward the query to the appropriate DNS servers to get the IP address.&lt;/p&gt;

&lt;p&gt;Once the resolver has the IP address, it will return it to your device, which can then use it to connect to the resource associated with that domain name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inbound
&lt;/h3&gt;

&lt;p&gt;Inbound resolvers enable the resolution of private hosted zones associated with a VPC.&lt;/p&gt;

&lt;p&gt;When you create a VPC, you can configure it to use a private hosted zone in Route 53, enabling the resolution of names to IP addresses specific to your VPC.&lt;/p&gt;

&lt;p&gt;You can then set up inbound resolvers within your VPC to help your resources find other resources by resolving their domain names to IP addresses.&lt;/p&gt;

&lt;p&gt;Inbound resolvers are also helpful for resolving domain names to IP addresses for resources outside your VPC, such as on-premise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rSPRKLpk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680648813247/3a549127-3673-4ac5-871c-45cec38338f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rSPRKLpk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680648813247/3a549127-3673-4ac5-871c-45cec38338f4.png" alt="Inbound Resolver Flow" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Outbound
&lt;/h3&gt;

&lt;p&gt;Outbound resolvers enable the resolution of domain names outside of your VPC.&lt;/p&gt;

&lt;p&gt;When you set up an outbound resolver, you can specify the IP addresses of the DNS servers you want to use for resolution. This can be useful if you want to use a specific DNS service for resolving domain names, such as a third-party or internal DNS provider.&lt;/p&gt;

&lt;p&gt;They can help you connect to resources on the internet, such as public domain names and other AWS services that are outside of your VPC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qj9eMqtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680648832081/31839f7b-7eff-4d90-a737-fde48efa9b85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qj9eMqtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680648832081/31839f7b-7eff-4d90-a737-fde48efa9b85.png" alt="Outbound Resolver Flow" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The above shows an on-premise DNS server; however, this could be an external DNS server on the public internet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Rules
&lt;/h2&gt;

&lt;p&gt;A resolver rule is a set of criteria the Route 53 resolver uses to determine how to route DNS queries, and they are only applicable to the outbound resolver.&lt;/p&gt;

&lt;p&gt;Expanding on the example above to resolve onpremise.net for instances inside the VPC, we would configure a forwarding rule for onpremise.net and point it to the internal DNS server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kExJPQBc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680650495997/4735652e-398d-40d7-8112-92568a568919.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kExJPQBc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680650495997/4735652e-398d-40d7-8112-92568a568919.png" alt="Outbound Rules" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resource Access Manager (RAM)
&lt;/h2&gt;

&lt;p&gt;RAM allows you to share your resolver rules and endpoints with other accounts in your organization. This method will enable you to define your rules once but use them across many VPCs.&lt;/p&gt;

&lt;p&gt;This can be particularly useful when you have a central team responsible for managing DNS and want to ensure consistent DNS resolution across your organization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wte2SSN8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680678160497/6e59cdf8-b43a-4a43-a291-e9b67eb3be52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wte2SSN8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1680678160497/6e59cdf8-b43a-4a43-a291-e9b67eb3be52.png" alt="RAM VPC Rule Sharing" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: The traffic between the resolvers in each VPC and the outbound resolver goes over the AWS Global Network. There is no requirement for the VPC CIDR ranges to be able to route to the outbound resolver endpoints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;p&gt;Here are a few things to consider for your architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Resolver Rules Wisely
&lt;/h3&gt;

&lt;p&gt;Create forwarding rules to route DNS queries for specific domains or subdomains to specific DNS resolvers. This allows you to control traffic flow and improve the efficiency of DNS resolution. Be sure to prioritize the most critical domains and establish a hierarchy of rules to minimize latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Endpoint Placement
&lt;/h3&gt;

&lt;p&gt;Place Resolver Endpoints Strategically to manage DNS query traffic between your VPCs and on-premises networks. Place these endpoints in subnets with low latency and high network throughput to ensure fast and reliable query resolution. As shown above RAM can also assist with sharing those endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restrict if required
&lt;/h3&gt;

&lt;p&gt;Resolvers need protection just like any other endpoint in your network. Configure the necessary Security Groups and Network Access Control Lists (ACLs) to protect your resolver endpoints. Limit access to only necessary IP ranges and ports, ensuring that only authorized users and applications can interact with your DNS infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;

&lt;p&gt;Enable DNS Query Logging Enable logging of DNS queries to track and analyze traffic patterns, identify potential security threats, and debug any issues related to DNS resolution. Route 53 Resolver can send query logs to Amazon CloudWatch Logs, enabling you to create custom metrics and alarms for monitoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring
&lt;/h3&gt;

&lt;p&gt;Monitor key performance metrics, such as query latency, query volume, and resolver endpoint health, to identify potential bottlenecks and capacity constraints. As your application and infrastructure grow, scale your Route 53 Resolver setup by adding additional resolver endpoints, rules, and VPC peering connections as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Every hybrid network AWS setup is going to need some sort of name resolution and I hope you now have a good understanding of the capabilities of Route 53 Resolver.&lt;/p&gt;

&lt;p&gt;Hope this helps someone else.&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>route53</category>
      <category>aws</category>
    </item>
    <item>
      <title>AWS Prefix Lists for the Organization</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Tue, 07 Mar 2023 03:03:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/aws-prefix-lists-for-the-organization-1k6j</link>
      <guid>https://forem.com/aws-builders/aws-prefix-lists-for-the-organization-1k6j</guid>
      <description>&lt;p&gt;AWS Managed Prefix lists are a really powerful way of abstracting the details of CIDR Blocks into something meaningful for the humble cloud engineer.&lt;/p&gt;

&lt;p&gt;Much like DNS does for IP addresses to hostnames, we can create a managed prefix for any service that has several CIDR blocks associated with it.&lt;/p&gt;

&lt;p&gt;I've talked about this before &lt;a href="https://sjramblings.io/aws_managed_prefixes/"&gt;here&lt;/a&gt;, but with more and more stuff needing to talk to services hosted on the internet and with our implementation of AWS Network Firewall, it is time for a re-visit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The challenge
&lt;/h2&gt;

&lt;p&gt;Most people are familiar with the AWS Public IP Address Ranges source ip-ranges.json, doco linked &lt;a href="https://aws.amazon.com/blogs/aws/aws-ip-ranges-json/"&gt;here&lt;/a&gt;, released in 2014. Can you believe it!&lt;/p&gt;

&lt;p&gt;It provides all the Public IP ranges for all services across all regions. A very handy thing to have, and with it being hosted in a JSON file, we can automatically parse it with any automation.&lt;/p&gt;

&lt;p&gt;But why don't AWS do this for us? I can't answer that today; however, a good example of such automation exists in the AWS samples GitHub &lt;a href="https://github.com/aws-samples/update-aws-ip-ranges"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The AWS Samples repo does all the heavy lifting with Lambda and creates the following:-&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3uY6OWja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/flpj2v82spken7uv8kry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3uY6OWja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/flpj2v82spken7uv8kry.png" alt="AWS-Samples Workflow" width="880" height="705"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But I'm feeling hacky and need some &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/sharing-managed-prefix-lists.html#sharing-share"&gt;Organization-level&lt;/a&gt; sharing, &lt;a href="https://awslabs.github.io/aws-lambda-powertools-python"&gt;Lambda PowerTools&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html"&gt;AppConfig&lt;/a&gt; and deployment through &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html"&gt;SAM CLI&lt;/a&gt;.&lt;br&gt;
Let's get into it!&lt;/p&gt;
&lt;h2&gt;
  
  
  Some Enhancements
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Lambda PowerTools
&lt;/h3&gt;

&lt;p&gt;As the &lt;a href="https://awslabs.github.io/aws-lambda-powertools-python"&gt;homepage&lt;/a&gt; displays, Lambda PowerTools is a suite of utilities for AWS Lambda functions to ease adopting best practices such as tracing, structured logging, custom metrics, idempotency, batching, &lt;a href="https://awslabs.github.io/aws-lambda-powertools-python/2.9.1/#features"&gt;and more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the reasons for implementing this is to make the Cloudwatch logs nicer to parse. It also removes a few lines of code in Lambda without requiring major logging structure changes.&lt;/p&gt;

&lt;p&gt;As I've rebuilt this into SAM Cli, this is just an addition to the &lt;code&gt;requirements.txt&lt;/code&gt; file to include &lt;code&gt;aws-lambda-powertools&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  AppConfig
&lt;/h3&gt;

&lt;p&gt;If you look at the original AWS example, it requires a services.json to be defined to configure what regions and services to create the WAF IPsets and VPC Prefixes. It will look something like the following:-&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;"Services"&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;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CODEBUILD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Regions"&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;"ap-southeast-2"&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;"PrefixList"&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;"Enable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Summarize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;"WafIPSet"&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;"Enable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Summarize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Scopes"&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;"REGIONAL"&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;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;This is in JSON format, so perfect for AppConfig.&lt;br&gt;
As we have configured Lambda PowerTools, AppConfig is easily added as a Lambda Layer.&lt;/p&gt;

&lt;p&gt;I've made several updates to the &lt;code&gt;template.yaml&lt;/code&gt; file to define our AppConfig hosted configuration and deployment methods, adding environment variables and our Lambda layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parameters:
  AppConfigAppName:
    Type: String
    Description: AppConfig Application Name
    Default: aws-ip-ranges
  AppConfigAppEnvironmentName:
    Type: String
    Description: AppConfig Application Environment Name
    Default: dev
  AppConfigName:
    Type: String
    Description: AppConfig Name
    Default: services
  AppConfigLayerArn:
    Type: String
    Description: Retrieve AWS AppConfig Lambda extension arn from `https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-integration-lambda-extensions-versions.html#appconfig-integration-lambda-extensions-enabling-x86-64`
    Default: arn:aws:lambda:ap-southeast-2:080788657173:layer:AWS-AppConfig-Extension:91
  AwsOrgArn:
    Type: String
    Description: The ARN of the AWS Organization used to share Prefix Lists
    Default: notset

Resources:
  SAMConfigApplication:
    Type: AWS::AppConfig::Application
    Properties:
      Name: !Ref AppConfigAppName

  Environment:
    Type: AWS::AppConfig::Environment
    Properties:
      Name: !Ref AppConfigAppEnvironmentName
      ApplicationId: !Ref SAMConfigApplication

  SAMConfigConfigurationProfile:
    Type: AWS::AppConfig::ConfigurationProfile
    Properties:
      ApplicationId: !Ref SAMConfigApplication
      Name: !Ref AppConfigName
      Type: 'AWS.Freeform'
      LocationUri: 'hosted'

  SAMConfigDeploymentStrategy:
    Type: AWS::AppConfig::DeploymentStrategy
    Properties:
      Name: "SAMConfigDeploymentStrategy"
      Description: "A deployment strategy to deploy the config immediately"
      DeploymentDurationInMinutes: 0
      FinalBakeTimeInMinutes: 0
      GrowthFactor: 100
      GrowthType: LINEAR
      ReplicateTo: NONE

  BasicHostedConfigurationVersion:
    Type: AWS::AppConfig::HostedConfigurationVersion
    Properties:
      ApplicationId: !Ref SAMConfigApplication
      ConfigurationProfileId: !Ref SAMConfigConfigurationProfile
      Description: 'AWS Service configuration for update-aws-ip-ranges'
      ContentType: 'application/json'
      Content: |
        {
          "Services": [
            {
              "Name": "CODEBUILD",
              "Regions": [
                "ap-southeast-2"
              ],
              "PrefixList": {
                "Enable": true,
                "Summarize": true
              },
              "WafIPSet": {
                "Enable": true,
                "Summarize": true,
                "Scopes": [
                  "REGIONAL"
                ]
              }
            }
          ]
        }
  AppConfigDeployment:
    Type: AWS::AppConfig::Deployment
    Properties:
      ApplicationId: !Ref SAMConfigApplication
      ConfigurationProfileId: !Ref SAMConfigConfigurationProfile
      ConfigurationVersion: !Ref BasicHostedConfigurationVersion
      DeploymentStrategyId: !Ref SAMConfigDeploymentStrategy
      EnvironmentId: !Ref Environment

  LambdaUpdateIPRanges:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: src/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Environment:
        Variables:
          APP_CONFIG_APP_NAME: !Ref AppConfigAppName
          APP_CONFIG_APP_ENV_NAME: !Ref AppConfigAppEnvironmentName
          APP_CONFIG_NAME: !Ref AppConfigName
          AWS_ORG_ARN: !Ref AwsOrgArn
          LOG_LEVEL: INFO
      Layers:
        - !Ref AppConfigLayerArn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to pull in the config, we add the following function and a few adjustments in the handler code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def get_service_config():
    try:
        appconfig = f"http://localhost:2772/applications/{APP_CONFIG_APP_NAME}/environments/{APP_CONFIG_APP_ENV_NAME}/configurations/{APP_CONFIG_NAME}"
        with request.urlopen(appconfig) as response:  # nosec B310
            config = response.read()
        return config
    except Exception as error:
        logger.error("Error retrieving AppConfig configuration. Exiting")
        logger.exception(error)
        raise error

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Organization-level sharing
&lt;/h3&gt;

&lt;p&gt;To enable all the users in our organization to benefit from our automation, we need to share the VPC Prefixes via Resource Access Manager (RAM).&lt;/p&gt;

&lt;p&gt;We define an additional function to create the RAM share on creating the VPC Prefix List.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_prefix_ram&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;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix_list_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix_list_arn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;"""Create the VPC Prefix List RAM Share"""&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;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"create_prefix_ram start"&lt;/span&gt;&lt;span class="p"&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;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Parameter client: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="si"&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Parameter prefix_list_name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix_list_name&lt;/span&gt;&lt;span class="si"&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Parameter prefix_list_arn: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix_list_arn&lt;/span&gt;&lt;span class="si"&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'Creating RAM Share "&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix_list_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;" with Arn "&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix_list_arn&lt;/span&gt;&lt;span class="si"&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="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_resource_share&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;prefix_list_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;resourceArns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;prefix_list_arn&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;principals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AWS_ORG_ARN&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;allowExternalPrincipals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prefix_list_name&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ManagedBy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MANAGED_BY&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"CreatedAt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"UpdatedAt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Not yet"&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="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'Created VPC Prefix List RAM Share"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix_list_name&lt;/span&gt;&lt;span class="si"&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Response: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="si"&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Function return: None"&lt;/span&gt;&lt;span class="p"&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;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"create_prefix_ram end"&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;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code is available at &lt;a href="https://github.com/sjramblings/update-aws-ip-ranges"&gt;https://github.com/sjramblings/update-aws-ip-ranges&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The End Result
&lt;/h2&gt;

&lt;p&gt;With our updates, this is now our enhanced Lambda workflow&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yTkFJClD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wt41rs0ie4uoymntszx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yTkFJClD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wt41rs0ie4uoymntszx4.png" alt="New Enhanced Workflow" width="880" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update to &lt;code&gt;arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged&lt;/code&gt; will trigger the function&lt;/li&gt;
&lt;li&gt;Lambda will execute under the IAM Role, retrieve its service config from AppConfig and write output to Cloudwatch&lt;/li&gt;
&lt;li&gt;For enabled services, it will create/update the VPC Prefixes &amp;amp; WAF IPSets&lt;/li&gt;
&lt;li&gt;VPC Prefixes will be shared with the Organization ID via RAM&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A few screenshot of the results:-&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9lmijn-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwtq1t4vdcigieut29v5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9lmijn-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwtq1t4vdcigieut29v5.png" alt="Resulting VPC Prefix List for CodeBuild&amp;lt;br&amp;gt;
" width="880" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6BHIOM20--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eoj0u3o8e4pk5as2ro9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6BHIOM20--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eoj0u3o8e4pk5as2ro9v.png" alt="RAM Prefix Share&amp;lt;br&amp;gt;
" width="880" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The wonderful contributors to AWS-Samples had done a great job in getting us started. However, I needed to take it a bit further, adding the VPC Prefix Sharing and a few other tweaks.&lt;/p&gt;

&lt;p&gt;As noted above, all code is available at &lt;a href="https://github.com/sjramblings/update-aws-ip-ranges"&gt;https://github.com/sjramblings/update-aws-ip-ranges&lt;/a&gt;. I will also raise Pull Requests to backport some of this into the AWS Samples repo.&lt;/p&gt;

&lt;p&gt;I hope this helps someone else!&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>vpc</category>
      <category>automation</category>
    </item>
    <item>
      <title>Build a Terraform Community Org on GitHub Enterprise</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Wed, 16 Jun 2021 11:20:41 +0000</pubDate>
      <link>https://forem.com/jones80_jones/build-a-terraform-community-org-on-github-enterprise-5api</link>
      <guid>https://forem.com/jones80_jones/build-a-terraform-community-org-on-github-enterprise-5api</guid>
      <description>&lt;p&gt;&lt;a href="https://sjramblings.io/posts/community/"&gt;https://sjramblings.io/posts/community/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>github</category>
      <category>terraform</category>
    </item>
    <item>
      <title>AWS Gp3 cost savings</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Tue, 08 Dec 2020 17:56:41 +0000</pubDate>
      <link>https://forem.com/jones80_jones/aws-gp3-cost-savings-11db</link>
      <guid>https://forem.com/jones80_jones/aws-gp3-cost-savings-11db</guid>
      <description>&lt;p&gt;&lt;a href="https://sjramblings.io/posts/aws_gp3/"&gt;https://sjramblings.io/posts/aws_gp3/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>gp3</category>
      <category>finops</category>
    </item>
    <item>
      <title>AWS Managed Prefixes</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Wed, 11 Nov 2020 12:23:09 +0000</pubDate>
      <link>https://forem.com/jones80_jones/aws-managed-prefixes-44oi</link>
      <guid>https://forem.com/jones80_jones/aws-managed-prefixes-44oi</guid>
      <description>&lt;p&gt;&lt;a href="https://sjramblings.io/posts/aws_managed_prefixes/"&gt;https://sjramblings.io/posts/aws_managed_prefixes/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudformation</category>
    </item>
    <item>
      <title>Prowler on AWS</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Wed, 04 Nov 2020 11:59:41 +0000</pubDate>
      <link>https://forem.com/jones80_jones/prowler-on-aws-4j8n</link>
      <guid>https://forem.com/jones80_jones/prowler-on-aws-4j8n</guid>
      <description>&lt;p&gt;&lt;a href="https://sjramblings.io/posts/prowler_on_aws/"&gt;https://sjramblings.io/posts/prowler_on_aws/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>prowler</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>Terraform in AWS bootstrap</title>
      <dc:creator>steve jones</dc:creator>
      <pubDate>Tue, 14 Jan 2020 20:57:42 +0000</pubDate>
      <link>https://forem.com/jones80_jones/terraform-in-aws-bootstrap-3d9m</link>
      <guid>https://forem.com/jones80_jones/terraform-in-aws-bootstrap-3d9m</guid>
      <description>&lt;p&gt;&lt;a href="https://sjramblings.io/posts/bootstrap_terraform_on_aws/"&gt;https://sjramblings.io/posts/bootstrap_terraform_on_aws/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>iac</category>
    </item>
  </channel>
</rss>
