<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Geovane Oliveira</title>
    <description>The latest articles on DEV Community by Geovane Oliveira (@geovane_oliveira).</description>
    <link>https://dev.to/geovane_oliveira</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%2F3664142%2Fc04c0578-8cd5-4fb0-bb23-051242fcc2a7.png</url>
      <title>DEV Community: Geovane Oliveira</title>
      <link>https://dev.to/geovane_oliveira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/geovane_oliveira"/>
    <language>en</language>
    <item>
      <title>How I passed the AWS Security Specialty and how you can too</title>
      <dc:creator>Geovane Oliveira</dc:creator>
      <pubDate>Mon, 01 Jun 2026 03:30:54 +0000</pubDate>
      <link>https://dev.to/geovane_oliveira/how-i-passed-the-aws-security-specialty-and-how-you-can-too-9e9</link>
      <guid>https://dev.to/geovane_oliveira/how-i-passed-the-aws-security-specialty-and-how-you-can-too-9e9</guid>
      <description>

&lt;h3&gt;
  
  
  Introduction to AWS certifications
&lt;/h3&gt;

&lt;p&gt;First things first, lets understand what the AWS Security Specialty certification is and where it fits in the AWS certification ecosystem.&lt;/p&gt;

&lt;p&gt;AWS certifications are divided into levels, each one targeting a different stage of your journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Practitioner&lt;/li&gt;
&lt;li&gt;  Associate&lt;/li&gt;
&lt;li&gt;  Professional&lt;/li&gt;
&lt;li&gt;  Specialty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practitioner level is where most people start.&lt;br&gt;
It focuses on foundational cloud concepts and basic AWS knowledge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As of today, there are two certifications at this level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  AWS Cloud Practitioner&lt;/li&gt;
&lt;li&gt;  AWS AI Practitioner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Cloud Practitioner covers core concepts like IAM, security, availability, pricing, and general cloud architecture.&lt;/p&gt;

&lt;p&gt;The AI Practitioner follows a similar structure, but focused on AI concepts and AWS AI services.&lt;/p&gt;




&lt;p&gt;The associate level is where things start to get more practical.&lt;/p&gt;

&lt;p&gt;At this level, you are expected to understand how to design and build solutions using AWS services.&lt;br&gt;
Some well-known certifications here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solutions Architect Associate&lt;/li&gt;
&lt;li&gt;Developer Associate&lt;/li&gt;
&lt;li&gt;CloudOps Engineer Associate (formerly SysOps Administrator)&lt;/li&gt;
&lt;li&gt;Data Engineer Associate&lt;/li&gt;
&lt;li&gt;Machine Learning Engineer Associate&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The professional level goes much deeper.&lt;/p&gt;

&lt;p&gt;Here, you are expected to design complex architectures, handle trade offs, and make decisions based on real world constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The main certifications are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solutions Architect Professional&lt;/li&gt;
&lt;li&gt;DevOps Engineer Professional&lt;/li&gt;
&lt;li&gt;Generative AI Developer Professional&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Finally, we have the specialty certifications.&lt;/p&gt;

&lt;p&gt;These are focused on specific domains and require deep knowledge in a particular area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples include:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Security Specialty&lt;/li&gt;
&lt;li&gt;  Machine Learning Specialty (Retired)&lt;/li&gt;
&lt;li&gt;  Advanced Networking Specialty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this is exactly where things start to get serious.&lt;/p&gt;

&lt;p&gt;At this level, AWS is no longer testing if you understand the services.&lt;br&gt;
It's testing if you can actually apply them in complex, real world scenarios.&lt;/p&gt;




&lt;h3&gt;
  
  
  What it is and who this certification is for
&lt;/h3&gt;

&lt;p&gt;The AWS Security Specialty is one of the most difficult certifications in your AWS journey.&lt;/p&gt;

&lt;p&gt;This exam expects that you already know the basics and are comfortable with complex and long detailed scenarios that you often come across when designing and securing AWS workloads.&lt;/p&gt;

&lt;p&gt;So the exam will not ask you what GuardDuty is or what WAF is.&lt;br&gt;
Instead, it will present you with a detailed scenario, and you, as a security engineer, will have to find the solution that best fits the situation.&lt;/p&gt;

&lt;p&gt;Just like in the real world, a single service will not solve your need.&lt;br&gt;
It's a combination of services and configurations tailored to your scenario.&lt;/p&gt;

&lt;p&gt;Because of that, you need to have a solutions architect mindset with an additional layer SysOps and of course deep security expertise.&lt;/p&gt;

&lt;p&gt;Without this knowledge, you won't be able to come up with a solution.&lt;/p&gt;

&lt;p&gt;It's highly recommended that you have already passed the Solutions Architect certification before attempting the Security Specialty.&lt;br&gt;
Although this is not a hard prerequisite, it is strongly recommended.&lt;/p&gt;

&lt;p&gt;The AWS Security Specialty is intended for experienced security professionals who work mainly securing AWS environments.&lt;/p&gt;

&lt;p&gt;AWS recommends that you have at least 3 to 5 years of hands on experience with AWS security, plus strong knowledge of vendor neutral security principles that can be applied to any cloud provider or application. That's where certifications like CompTIA Security+ and CCSP comes in to give you a solid and agnostic knowledge.&lt;/p&gt;

&lt;p&gt;This is a Specialty level certification, which means you are expected to have deep knowledge of security and securing AWS workloads at an enterprise level.&lt;/p&gt;

&lt;p&gt;The questions are scenario based, usually long, with long and very similar answer options. But only one answer will satisfy the scenario, which my result in you flagging a lot of questions to review later on.&lt;/p&gt;

&lt;p&gt;Be prepared for a mental endurance test that will chalenge not only your technical knowledge, but also your ability to maintain focus for up to 3 hours of long scenario based questions (or 3h30 if you are not a native english speaker and apply for the ESL extra time). &lt;/p&gt;




&lt;h3&gt;
  
  
  How to prepare for the exam
&lt;/h3&gt;

&lt;p&gt;Before you try the Security Specialty, you need to have both security foundational and advanced knowledge and AWS foundational and advanced knowledge.&lt;/p&gt;

&lt;p&gt;For security knowledge, there are many ways you can achieve it.&lt;/p&gt;

&lt;p&gt;I highly recommend that you study for CompTIA Security+, which will give you very solid, vendor neutral security knowledge that you can apply in any environment or application.&lt;/p&gt;

&lt;p&gt;You will learn concepts like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  least privilege&lt;/li&gt;
&lt;li&gt;  cryptography&lt;/li&gt;
&lt;li&gt;  authentication and authorization&lt;/li&gt;
&lt;li&gt;  defense in depth&lt;/li&gt;
&lt;li&gt;  Threat vectors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also many foundational, intermediate, and advanced courses available on AWS Skill Builder.&lt;/p&gt;

&lt;p&gt;Some of them are paid, but most are free, and you can also earn badges to show on your LinkedIn profile.&lt;/p&gt;

&lt;p&gt;But remember, this does not replace the necessary hands on experience.&lt;/p&gt;

&lt;p&gt;Many courses offer guided labs, but the best way to learn is by actually building something, applying the security concepts, breaking things, fixing things, and testing different approaches.&lt;/p&gt;

&lt;p&gt;You should also build your portfolio, which will help you gain experience, increase your confidence, and improve your attractiveness for job opportunities.&lt;/p&gt;

&lt;p&gt;Here's a list of courses and materials I do recommend for your security journey:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://skillbuilder.aws/learn/S2N5PM41ZK/aws-security-fundamentals-second-edition/E71QQGTCRZ" rel="noopener noreferrer"&gt;&lt;strong&gt;- AWS Security Fundamentals&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.udemy.com/share/1084Uy3@JEBW0Y8-WQ01ZRX8XRVs38nDI8SCJuYpP290NQfYklCkxm9yv7OiHKdR-QyoXFKBKQ==/" rel="noopener noreferrer"&gt;&lt;strong&gt;- Ultimate AWS Certified Security Specialty SCS-C03 By Stephane Mareek&lt;/strong&gt; (&lt;strong&gt;This is a must have course&lt;/strong&gt;)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://skillbuilder.aws/learning-plan/2D57DTTB9T/exam-prep-plan-security--specialty-scsc03--english/7X8SS2CA3U" rel="noopener noreferrer"&gt;&lt;strong&gt;- AWS Skill Builder Exam Prep Plan Security - Specialty (SCS-C03)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extras:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.coursera.org/learn/foundations-of-cybersecurity" rel="noopener noreferrer"&gt;&lt;strong&gt;- Foundations of Cybersecurity by Google&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=KiEptGbnEBc&amp;amp;list=PLG49S3nxzAnl4QDVqK-hOnoqcSKEIDDuv" rel="noopener noreferrer"&gt;&lt;strong&gt;- CompTIA SY0-701 Security+ Free Training Course - Professor Messer&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  My journey to AWS Security Specialty
&lt;/h3&gt;

&lt;p&gt;As a cloud security engineer, I already have extensive knowledge about cybersecurity and solutions architecture, which helped me a lot in my journey to the Security Specialty. But that doesn't mean it was easy.&lt;/p&gt;

&lt;p&gt;It does help, but the exam explores many AWS services that you might not have much familiarity with in your daily work. That's why you really need to practice in the AWS console and also take as many practice exams as you can.&lt;/p&gt;

&lt;p&gt;My first attempt was back in August 2024, after studying for more than six months. I almost passed on my first try. I scored 718 points, which is very close to the passing score.&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%2Fucmlugdhjwx3ld7xozel.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%2Fucmlugdhjwx3ld7xozel.png" alt="AWS Security Specialty First Try" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I became really frustrated because I missed it by just a few questions, and I knew how much effort and time I had put into my preparation. I knew I had the necessary knowledge, but it wasn't enough.&lt;/p&gt;

&lt;p&gt;After the exam, I tried to remember some of the questions I was unsure about and started researching the AWS documentation to check if my understanding was correct.&lt;/p&gt;

&lt;p&gt;Then I outlined what wasn't clear yet so I could better prepare for a second attempt.&lt;/p&gt;

&lt;p&gt;I identified some services and details that weren't clear in my head, like S3 retention modes and some tricky details about SCP in AWS Organizations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And one important lesson:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not underestimate any service. Even the ones you think might not appear in your exam will show up. You need to understand the details of everything outlined in the exam guide.&lt;/p&gt;




&lt;h3&gt;
  
  
  My second attempt
&lt;/h3&gt;

&lt;p&gt;My second attempt was almost two years later, in February 2026, after studying for about a month and a half.&lt;/p&gt;

&lt;p&gt;During this time, I:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Reviewed Stephane Maarek's course&lt;/li&gt;
&lt;li&gt;  Completed Tutorials Dojo practice exams&lt;/li&gt;
&lt;li&gt;  Reviewed my previous notes&lt;/li&gt;
&lt;li&gt;  Added new notes for topics that were still unclear&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once I started consistently scoring above 800 in practice exams, I knew I was ready. At that point, I realized that waiting longer would only make me more anxious.&lt;/p&gt;

&lt;p&gt;During the exam, I felt that it was slightly less complicated than my first attempt. In many questions, I felt very confident about my answers, but I stayed calm and focused.&lt;/p&gt;

&lt;p&gt;I finished the exam with about 20 minutes left (with ESL extra time). I reviewed the questions I wasn't so sure about, but I kept my original answers.&lt;/p&gt;

&lt;p&gt;In my first attempt, I realized that I probably lost points because I changed answers that were already correct when I was reviewing, so watch out for that.&lt;/p&gt;

&lt;p&gt;So this time, I trusted my reasoning. I finished the exam knowing that I had done my best.&lt;/p&gt;

&lt;p&gt;The final result arrived one day later.&lt;/p&gt;

&lt;p&gt;I passed with a score of 804.&lt;br&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%2Fl0p3dkyspyug4lzn0fk2.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%2Fl0p3dkyspyug4lzn0fk2.png" alt="AWS Security Specialty Second Try" width="800" height="777"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How I studied for the Security Specialty and how the exam felt
&lt;/h3&gt;

&lt;p&gt;When preparing for an AWS exam, I always start with Stephane Maarek's courses. They are my go to recommendation for anyone studying for AWS certifications.&lt;/p&gt;

&lt;p&gt;Neal Davis courses are also a great option, but I see them more as a complement to gain deeper understanding.&lt;/p&gt;

&lt;p&gt;Another must have resource is Tutorials Dojo. Their practice exams are very well crafted, with detailed explanations that help you identify and close knowledge gaps.&lt;/p&gt;

&lt;p&gt;Once you consistently score above the passing score, you know you are ready to take the exam.&lt;/p&gt;

&lt;p&gt;AWS Skill Builder is also a good complementary resource. It provides practice exams created by AWS, which are closer to the real exam experience.&lt;/p&gt;

&lt;p&gt;One thing that helped me a lot was creating mental acronyms and references to remember concepts and details. Because even if you are an experienced security professional, it's almost impossible to remember every detail of every AWS service in depth. And for this exam, you need depth.&lt;/p&gt;

&lt;p&gt;Not only in security services, but also in services like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  CloudWatch&lt;/li&gt;
&lt;li&gt;  Lambda&lt;/li&gt;
&lt;li&gt;  S3&lt;/li&gt;
&lt;li&gt;  EC2&lt;/li&gt;
&lt;li&gt;  KMS&lt;/li&gt;
&lt;li&gt;  Organizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This level of depth is what separates a passing score from a failing score.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Mental models and tricks I used during the exam&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before anything, one important clarification:

During the exam, you are not allowed to consult anything.
No notes, no documentation, no external resources.
**Everything you need must already be inside your head.**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These mental models and shortcuts are not something you will create during the exam. They are something you need to study, practice and internalize beforehand. If you rely on memorizing during the exam, you’re already too late.&lt;/p&gt;

&lt;p&gt;These are some of my personal notes and mental shortcuts that helped me recall concepts quickly during the exam. &lt;em&gt;&lt;strong&gt;You should create your's and use this as an starting point of what you should expect&lt;/strong&gt;&lt;/em&gt;. And remember, if you only take notes but doesnt understand what they mean and how every service and configuration works in AWS, then you are studying the wrong way, and this is a recipe for failing any exam you take.&lt;/p&gt;




&lt;h3&gt;
  
  
  Security Group vs NACL
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Security Group = "Security with memory" (stateful)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a security guard at a private party:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Entry: You show your invitation and get in&lt;/li&gt;
&lt;li&gt;  Exit: The guard remembers you and lets you leave&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If inbound is allowed, outbound response is automatically allowed.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;NACL = "Security with amnesia" (stateless)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a guard that forgets everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Entry works normally&lt;/li&gt;
&lt;li&gt;  Exit requires a new check&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You must explicitly allow outbound traffic.&lt;/p&gt;

&lt;p&gt;NACL works at subnet level.&lt;/p&gt;




&lt;h3&gt;
  
  
  Inspector vs Detective vs Audit Manager
&lt;/h3&gt;

&lt;p&gt;Inspector = Find vulnerabilities before attackers&lt;br&gt;
Detective = Understand what happened after an event&lt;br&gt;
Audit Manager = Build compliance reports continuously&lt;/p&gt;




&lt;h3&gt;
  
  
  Endpoint types
&lt;/h3&gt;

&lt;p&gt;Gateway Endpoint = S3 and DynamoDB&lt;br&gt;
Interface Endpoint = almost everything else&lt;/p&gt;




&lt;h3&gt;
  
  
  Audit tools comparison
&lt;/h3&gt;

&lt;p&gt;Audit Manager = compliance evidence&lt;br&gt;
Config = configuration tracking&lt;br&gt;
Inspector = vulnerabilities&lt;br&gt;
Detective = investigation&lt;/p&gt;




&lt;h3&gt;
  
  
  KMS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Cannot delete immediately&lt;/li&gt;
&lt;li&gt;  Minimum 7 days&lt;/li&gt;
&lt;li&gt;  Default 30 days&lt;/li&gt;
&lt;li&gt;  Keys are regional&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Remediation patterns
&lt;/h3&gt;

&lt;p&gt;Config → EventBridge → Lambda&lt;br&gt;
Trusted Advisor → EventBridge → Lambda&lt;br&gt;
GuardDuty → EventBridge → Step Functions&lt;br&gt;
Security Hub → EventBridge → Step Functions&lt;br&gt;
Config → SSM Document&lt;/p&gt;




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

&lt;p&gt;Governance = flexible&lt;br&gt;
Compliance = cannot be disabled&lt;br&gt;
Legal Hold = independent&lt;/p&gt;

&lt;p&gt;Versioning must be enabled&lt;/p&gt;




&lt;h3&gt;
  
  
  SCP
&lt;/h3&gt;

&lt;p&gt;Management Account is not restricted&lt;/p&gt;

&lt;p&gt;Management Account = SCP immune&lt;/p&gt;




&lt;h3&gt;
  
  
  Secrets
&lt;/h3&gt;

&lt;p&gt;Parameter Store = simple&lt;br&gt;
Secrets Manager = advanced&lt;br&gt;
ACM = certificates&lt;/p&gt;




&lt;h3&gt;
  
  
  Security Hub
&lt;/h3&gt;

&lt;p&gt;Needs AWS Config&lt;br&gt;
Organizations only for multi account&lt;/p&gt;




&lt;h3&gt;
  
  
  Networking
&lt;/h3&gt;

&lt;p&gt;NAT Gateway = outbound only&lt;br&gt;
Internet Gateway = inbound and outbound&lt;/p&gt;




&lt;h3&gt;
  
  
  IAM Access Analyzer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Finds external access&lt;/li&gt;
&lt;li&gt;Works on resource policies&lt;/li&gt;
&lt;li&gt;Regional&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Load balancers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ALB&lt;/strong&gt; = Layer 7&lt;br&gt;
&lt;strong&gt;NLB&lt;/strong&gt; = Layer 4&lt;br&gt;
&lt;strong&gt;GWLB&lt;/strong&gt; = inspection&lt;/p&gt;




&lt;h3&gt;
  
  
  Endpoints summary
&lt;/h3&gt;

&lt;p&gt;Gateway Endpoint&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  S3 and Dynamo&lt;/li&gt;
&lt;li&gt;  Free&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interface Endpoint&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Most services&lt;/li&gt;
&lt;li&gt;  Paid&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This certification was one of the most challenging steps in my AWS journey. Not only because of the difficulty, but because it forced me to think differently.&lt;/p&gt;

&lt;p&gt;It's not about memorizing services. It's about understanding how to combine them to solve real problems.&lt;/p&gt;

&lt;p&gt;And more importantly, it's about making decisions under pressure, with incomplete information, just like in real world scenarios.&lt;/p&gt;

&lt;p&gt;Failing my first attempt was frustrating, but it was also necessary. It showed me that knowing is not the same as being ready.&lt;/p&gt;

&lt;p&gt;The second attempt was different. Not because the exam was easier, but because my mindset was.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are preparing for this exam, focus on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  understanding the "why" behind each service&lt;/li&gt;
&lt;li&gt;  practicing real scenarios&lt;/li&gt;
&lt;li&gt;  identifying your weak points early&lt;/li&gt;
&lt;li&gt;  and building confidence through repetition&lt;/li&gt;
&lt;li&gt;  And make sure to practice with hands on in AWS, not just theory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;And one important thing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You won't pass this exam by luck. And you definitely won't pass it by just watching courses.&lt;/p&gt;

&lt;p&gt;You need real hands on practice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Build things in AWS.&lt;/li&gt;
&lt;li&gt;  Break them.&lt;/li&gt;
&lt;li&gt;  Fix them.&lt;/li&gt;
&lt;li&gt;  Test different approaches.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's where the concepts actually become clear.&lt;br&gt;
You pass when your reasoning becomes natural.&lt;/p&gt;

&lt;p&gt;When you stop thinking "which service is this" and start thinking "what problem am I solving". That's when everything clicks.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>awscommunitybuilder</category>
    </item>
    <item>
      <title>Protecting an EC2 hosted web application with AWS WAF in practice</title>
      <dc:creator>Geovane Oliveira</dc:creator>
      <pubDate>Thu, 08 Jan 2026 00:29:40 +0000</pubDate>
      <link>https://dev.to/geovane_oliveira/protecting-an-ec2-hosted-web-application-with-aws-waf-in-practice-3mb</link>
      <guid>https://dev.to/geovane_oliveira/protecting-an-ec2-hosted-web-application-with-aws-waf-in-practice-3mb</guid>
      <description>&lt;p&gt;Web applications on EC2 are everywhere. And honestly, a lot of them are just sitting there exposed to the internet with nothing more than a Security Group between them and every bot, scanner, and attacker out there.&lt;/p&gt;

&lt;p&gt;This article walks through building a straightforward architecture to answer one specific question: How do you protect a web application on EC2 from common web attacks without touching the application code?&lt;/p&gt;

&lt;p&gt;We'll use AWS WAF for Layer 7 protection, Security Groups for network control, and AWS Certificate Manager for encrypted transport, all at minimal cost and complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding network layers before adding security controls
&lt;/h2&gt;

&lt;p&gt;Before jumping into AWS services, let's get clear on how network communication actually works. The OSI model helps here, but we'll keep it practical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3 – Network layer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Deals with IP addresses. This is about knowing where traffic is coming from and where it's headed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 4 – Transport layer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Deals with ports and protocols. This controls how connections get established, think TCP on port 80 or 443.&lt;/p&gt;

&lt;p&gt;Together, these two layers answer questions like: Who's sending this traffic? Which port are they using? Should this connection even be allowed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 7 – Application layer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is where HTTP and HTTPS live. It understands URLs, headers, query strings, request bodies and the actual content of what's being sent.&lt;/p&gt;

&lt;p&gt;Layer 7 answers a different kind of question: What is the user actually trying to do?&lt;/p&gt;

&lt;p&gt;Here's the thing: most web attacks happen at Layer 7, not at the network level. Understanding this distinction is critical.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Security Group is and how it works
&lt;/h2&gt;

&lt;p&gt;Security Groups are probably the first security control you run into in AWS. They're virtual firewalls that control network level access to things like EC2 instances and load balancers.&lt;/p&gt;

&lt;p&gt;A Security Group evaluates traffic based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source IP address&lt;/li&gt;
&lt;li&gt;Destination port
&lt;/li&gt;
&lt;li&gt;Protocol&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the OSI perspective, Security Groups operate at Layer 3 (Network) and Layer 4 (Transport).&lt;/p&gt;

&lt;p&gt;Key characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stateful&lt;/strong&gt; – if traffic is allowed in, the response is automatically allowed out&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allow only&lt;/strong&gt; – you can't write deny rules, only allow rules&lt;/li&gt;
&lt;li&gt;Everything else is denied by default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow inbound TCP traffic on port 80 from anywhere (0.0.0.0/0)&lt;/li&gt;
&lt;li&gt;Allow SSH on port 22 only from your office IP&lt;/li&gt;
&lt;li&gt;Deny everything else (implicit)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security Groups are essential. They're your first line of defense.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Security Groups cannot protect against
&lt;/h2&gt;

&lt;p&gt;But here's the limitation: Security Groups don't understand HTTP or HTTPS content at all.&lt;/p&gt;

&lt;p&gt;They can't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inspect URLs&lt;/li&gt;
&lt;li&gt;Analyze query strings&lt;/li&gt;
&lt;li&gt;Detect SQL injection attempts&lt;/li&gt;
&lt;li&gt;Catch Cross Site Scripting (XSS)&lt;/li&gt;
&lt;li&gt;Identify malicious payloads in request bodies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a Security Group's perspective, if port 80 is open and the source IP is allowed, the request gets through no matter what's actually inside that request.&lt;/p&gt;

&lt;p&gt;This is a fundamental limitation when you're trying to protect web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why application layer protection is required
&lt;/h2&gt;

&lt;p&gt;Web attacks are application layer problems. That means you need Layer 7 inspection.&lt;/p&gt;

&lt;p&gt;This is where AWS WAF comes in.&lt;/p&gt;

&lt;p&gt;AWS WAF is a fully managed Web Application Firewall that inspects HTTP and HTTPS requests before they ever reach your application. It looks at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL paths&lt;/li&gt;
&lt;li&gt;Headers&lt;/li&gt;
&lt;li&gt;Query strings&lt;/li&gt;
&lt;li&gt;Request bodies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on rules you define (or use AWS Managed Rules), it can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow requests&lt;/li&gt;
&lt;li&gt;Block requests&lt;/li&gt;
&lt;li&gt;Count requests for monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best part? No agents on your EC2 instances. No changes to your application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an Application Load Balancer is part of the design:
&lt;/h2&gt;

&lt;p&gt;AWS WAF can't attach directly to an EC2 instance. It needs to be associated with one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Load Balancer&lt;/li&gt;
&lt;li&gt;API Gateway&lt;/li&gt;
&lt;li&gt;CloudFront&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this architecture, the Application Load Balancer serves as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The public entry point&lt;/li&gt;
&lt;li&gt;The integration point for AWS WAF&lt;/li&gt;
&lt;li&gt;The boundary between the internet and your compute layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if you are only running a single EC2 instance, this design mirrors what you would see in production environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture overview
&lt;/h2&gt;

&lt;p&gt;The architecture below shows the scenario we are going to discuss in this article.&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%2Fd8aslhi8in6l1yt8wgmg.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%2Fd8aslhi8in6l1yt8wgmg.png" alt="AWS WAF Architecture Diagram" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: Conceptual architecture for protecting an EC2-hosted web application using AWS WAF attached to an internet-facing Application Load Balancer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The flow works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Internet traffic hits the Application Load Balancer&lt;/li&gt;
&lt;li&gt;AWS WAF inspects HTTP requests at Layer 7&lt;/li&gt;
&lt;li&gt;Allowed requests get forwarded to the EC2 instance&lt;/li&gt;
&lt;li&gt;Security Groups restrict network level access between components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Architecture components:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon EC2&lt;/strong&gt; – Runs a simple Nginx web application in a public subnet&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application Load Balancer&lt;/strong&gt; – Exposes the application to the internet and routes traffic to EC2&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS WAF&lt;/strong&gt; – Inspects and filters HTTP requests before they reach the application&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Certificate Manager&lt;/strong&gt; – Provides free SSL/TLS certificates for HTTPS encryption&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Systems Manager Session Manager&lt;/strong&gt; – Provides secure, SSH free access to EC2 instances via IAM&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto Scaling Group&lt;/strong&gt; – Maintains a single EC2 instance (and makes it easy to scale later if needed)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Groups&lt;/strong&gt; – Enforce strict Layer 3 and Layer 4 access rules&lt;/p&gt;

&lt;p&gt;Each component protects a specific layer. There's no redundancy or overlap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the infrastructure
&lt;/h2&gt;

&lt;p&gt;Let's walk through the key configuration steps. I'll focus on the security specific settings that matter most.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Creating the Application Load Balancer
&lt;/h3&gt;

&lt;p&gt;First, we need to set up the ALB that will serve as our public entry point.&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%2Fi218h3bviujo2wl5ntg9.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%2Fi218h3bviujo2wl5ntg9.png" alt="ALB Configuration in AWS Console" width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: Application Load Balancer basic configuration&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Key settings to configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scheme&lt;/strong&gt;: Internet facing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP address type&lt;/strong&gt;: IPv4&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listeners&lt;/strong&gt;: HTTP (port 80) and HTTPS (port 443)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability Zones&lt;/strong&gt;: Select at least two for high availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ALB needs to be in a public subnet since it's receiving traffic directly from the internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configuring Security Groups
&lt;/h3&gt;

&lt;p&gt;Security Groups control network level access. We need two distinct groups here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ALB Security Group:&lt;/strong&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%2Fnxdzu5v4r2vtnoua74qo.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%2Fnxdzu5v4r2vtnoua74qo.png" alt="ALB Security Group Rules" width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3: Security Group rules for the Application Load Balancer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inbound rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow HTTP (port 80) from 0.0.0.0/0&lt;/li&gt;
&lt;li&gt;Allow HTTPS (port 443) from 0.0.0.0/0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;EC2 Security Group:&lt;/strong&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%2Fu2os2c35r7h3591b4kfg.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%2Fu2os2c35r7h3591b4kfg.png" alt="EC2 Security Group Rules" width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4: Security Group rules for the EC2 instance&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inbound rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow HTTP (port 80) &lt;strong&gt;only&lt;/strong&gt; from the ALB Security Group&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Unlike traditional setups, we're not opening SSH port 22. Access to the instance for management purposes is handled through AWS Systems Manager Session Manager, which uses IAM authentication and doesn't require any inbound ports to be open.&lt;/p&gt;

&lt;p&gt;This is crucial: the EC2 instance never accepts traffic directly from the internet. Only the ALB can reach it on port 80, and administrative access is through SSM Session Manager only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Creating the AWS WAF Web ACL
&lt;/h3&gt;

&lt;p&gt;Now we add the Layer 7 protection. This is where AWS WAF comes 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%2F3cd3706i4dbh7vmhsiu1.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%2F3cd3706i4dbh7vmhsiu1.png" alt="AWS WAF Web ACL Configuration" width="800" height="667"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5: Creating a Web ACL in AWS WAF&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When creating the Web ACL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a descriptive name (e.g., &lt;code&gt;ec2-app-protection-waf&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Application Load Balancer&lt;/strong&gt; as the resource type&lt;/li&gt;
&lt;li&gt;Associate it with the ALB you created earlier&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Adding AWS Managed Rules
&lt;/h3&gt;

&lt;p&gt;Instead of writing custom rules from scratch, we'll use AWS Managed Rule Groups. These are maintained by AWS and updated automatically.&lt;/p&gt;

&lt;p&gt;Recommended rule groups to enable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core rule set (CRS)&lt;/strong&gt; – Protects against common attacks like OWASP Top 10&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Known bad inputs&lt;/strong&gt; – Blocks requests with patterns associated with exploit attempts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL database&lt;/strong&gt; – Prevents SQL injection attacks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux operating system&lt;/strong&gt; – Blocks requests targeting common Linux vulnerabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each rule group adds a layer of protection. Start with these four since they cover the most common attack vectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Associating WAF with the ALB
&lt;/h3&gt;

&lt;p&gt;Once the Web ACL is configured, associate it with your Application Load Balancer.&lt;/p&gt;

&lt;p&gt;The association happens in one of two ways, depending on where you started the configuration. If you created the Web ACL from the WAF console, you selected the ALB during the initial setup under (Associated AWS resources). If you're adding WAF to an existing ALB, you will find the option in the Load Balancer console under the (Integrated services) tab.&lt;/p&gt;

&lt;p&gt;From the Load Balancer perspective, you will see a section labeled (AWS WAF) where you can attach a Web ACL. Click "Edit" and select your newly created Web ACL from the dropdown. The attachment is immediate there is no downtime, no need to restart anything.&lt;/p&gt;

&lt;p&gt;Once associated, you will see the Web ACL name displaied in the ALB's integrated services section. You can verify the reverse connection by going back to the WAF console, selecting your Web ACL, and checking the (Associated AWS resources) tab. Your ALB should be listed there.&lt;/p&gt;

&lt;p&gt;This is the critical connection point. Every HTTP request hitting your ALB will now pass through AWS WAF inspection before reaching your EC2 instance. The WAF evaluates each request against your rule groups in order of priority, and either allows it through, blocks it with a 403 response, or counts it for monitoring purposes depending on how you've configured each rule.&lt;/p&gt;

&lt;p&gt;The inspection happens inline with minimal latency, typically adding only single digit milliseconds to request processing time. If WAF blocks a request, the connection never reaches your application layer. The request is terminated at the ALB with a 403 Forbidden response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Configuring IAM Role for Systems Manager
&lt;/h3&gt;

&lt;p&gt;To enable secure, SSH free access to the EC2 instance, we attach an IAM role that allows Systems Manager Session Manager to function.&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%2F1bomh0iaud2rdgyfad95.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%2F1bomh0iaud2rdgyfad95.png" alt="IAM Role for SSM" width="800" height="805"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 7: IAM role configuration for Systems Manager access&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The IAM role includes the &lt;code&gt;AmazonSSMManagedInstanceCore&lt;/code&gt; managed policy, which provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permission for the SSM agent to communicate with Systems Manager service&lt;/li&gt;
&lt;li&gt;Ability to retrieve commands and send outputs&lt;/li&gt;
&lt;li&gt;CloudWatch Logs integration for session logging (optional but recommended)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note on SSM Agent:&lt;/strong&gt; If you are using Amazon Linux 2023 (as in this setup), the SSM agent comes pre installed and enabled by default. For other AMIs like Ubuntu or older Amazon Linux versions, you may need to install the agent manually. The combination of the IAM role and the pre installed agent is what enables Session Manager to work immediately after instance launch.&lt;/p&gt;

&lt;p&gt;Once attached, you can access the instance through the AWS console or CLI without opening SSH ports or managing key pairs. All sessions are authenticated through IAM and can be logged for audit purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: Monitoring and testing
&lt;/h3&gt;

&lt;p&gt;After everything is configured, you can monitor WAF activity through CloudWatch metrics.&lt;/p&gt;

&lt;p&gt;AWS WAF provides real time metrics that show how your Web ACL is performing. These metrics are automatically published to CloudWatch and typically appear within 5 to 10 minutes of activity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key metrics to watch:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AllowedRequests:&lt;/strong&gt; Legitimate traffic getting through&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BlockedRequests:&lt;/strong&gt; Malicious requests stopped by WAF&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CountedRequests:&lt;/strong&gt; Requests matching rules in count mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view these metrics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the AWS WAF console&lt;/li&gt;
&lt;li&gt;Select your Web ACL&lt;/li&gt;
&lt;li&gt;Go to the Overview tab&lt;/li&gt;
&lt;li&gt;CloudWatch metrics will display showing request patterns over time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also view detailed logs in CloudWatch Logs if you enable WAF logging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transport security with HTTPS
&lt;/h2&gt;

&lt;p&gt;All traffic between clients and the Application Load Balancer is encrypted using TLS 1.2 or higher. The SSL certificate is provided by AWS Certificate Manager at no cost and renews automaticaly.&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%2Fe8aym6syxy6abohjspf7.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%2Fe8aym6syxy6abohjspf7.png" alt="HTTPS Certificate Configuration" width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 10: SSL/TLS certificate from AWS Certificate Manager&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The ALB is configured to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accept HTTPS connections on port 443 with a valid SSL certificate&lt;/li&gt;
&lt;li&gt;Redirect all HTTP traffic to HTTPS (301 permanent redirect)&lt;/li&gt;
&lt;li&gt;Use modern cipher suites (TLS 1.2+ only)&lt;/li&gt;
&lt;li&gt;Serve a certificate trusted by all major browsers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that sensitive data cannot be intercepted or read by attackers performing man-in-the-middle attacks. The certificate is issued and managed by AWS Certificate Manager, which handles automatic renewal before expiration.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Video walkthrough&lt;/strong&gt;: For a complete hands on demonstration of this setup, check out the video tutorial below where I walk through each step in the AWS console.&lt;/p&gt;

&lt;p&gt;[Vídeo soon]&lt;/p&gt;




&lt;h2&gt;
  
  
  What AWS WAF protects against in practice
&lt;/h2&gt;

&lt;p&gt;Using AWS Managed Rules, AWS WAF can block common attack patterns like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL injection attempts&lt;/li&gt;
&lt;li&gt;Cross-Site Scripting (XSS)&lt;/li&gt;
&lt;li&gt;Path traversal attacks&lt;/li&gt;
&lt;li&gt;Malformed or suspicious HTTP requests&lt;/li&gt;
&lt;li&gt;Basic automated scanners and bots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important point:&lt;/strong&gt; AWS WAF doesn't fix insecure code. What it does is reduce your exposure by blocking known malicious patterns before they ever reach your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this architecture does NOT cover (and why it matters)
&lt;/h2&gt;

&lt;p&gt;This architecture provides solid foundational protection with network segmentation, application layer filtering, encrypted transport, and IAM based instance access. However, it's important to understand its limitations. This is a strong starting point that demonstrates core security principles, &lt;u&gt;not a complete enterprise grade solution&lt;/u&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's missing for a production environment:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Network Isolation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 in public subnet (production should use private subnet, see "Ideal Architecture" below)&lt;/li&gt;
&lt;li&gt;EC2 has public IP (though no direct access is possible due to Security Groups)&lt;/li&gt;
&lt;li&gt;No VPC Endpoints for fully isolated SSM access&lt;/li&gt;
&lt;li&gt;No NAT Gateway for controlled outbound traffic from private instances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced DDoS Protection:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No AWS Shield Advanced for sophisticated volumetric attacks&lt;/li&gt;
&lt;li&gt;No rate based rules in WAF to limit request velocity per IP&lt;/li&gt;
&lt;li&gt;No geographic restrictions (geo blocking) for region specific threats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Monitoring and Threat Detection:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WAF logging disabled (to minimize costs for this demo)&lt;/li&gt;
&lt;li&gt;No AWS GuardDuty for threat intelligence and anomaly detection&lt;/li&gt;
&lt;li&gt;No Security Hub for centralized security findings across services&lt;/li&gt;
&lt;li&gt;No VPC Flow Logs for network traffic analysis&lt;/li&gt;
&lt;li&gt;No CloudWatch Alarms for proactive alerting on suspicious activity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Identity and Secrets Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No AWS Secrets Manager for database credentials or API keys&lt;/li&gt;
&lt;li&gt;Session Manager logging not enabled (optional enhancement)&lt;/li&gt;
&lt;li&gt;No MFA requirement for Session Manager access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Compliance and Governance:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No AWS Config for continuous compliance checking&lt;/li&gt;
&lt;li&gt;No automated patch management with Systems Manager Patch Manager&lt;/li&gt;
&lt;li&gt;No backup strategy with AWS Backup&lt;/li&gt;
&lt;li&gt;No vulnerability scanning with AWS Inspector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced Application Protection:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No AWS WAF Bot Control for sophisticated bot mitigation&lt;/li&gt;
&lt;li&gt;No reCAPTCHA challenges for suspicious activity&lt;/li&gt;
&lt;li&gt;No account takeover prevention features&lt;/li&gt;
&lt;li&gt;No fraud detection patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Content Delivery:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No CloudFront for global edge caching and additional DDoS protection&lt;/li&gt;
&lt;li&gt;No origin shielding to reduce load on the ALB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommendation:&lt;/strong&gt; For production, place CloudFront in front of the ALB to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hide the ALB's DNS name from public access&lt;/li&gt;
&lt;li&gt;Add an additional WAF layer at the edge&lt;/li&gt;
&lt;li&gt;Improve global performance with caching&lt;/li&gt;
&lt;li&gt;Protect against DDoS attacks with AWS Shield&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ideal architecture for production:
&lt;/h3&gt;

&lt;p&gt;For production workloads, the recommended architecture would place the EC2 instance in a private subnet with no public IP address and use VPC Interface Endpoints for Systems Manager connectivity. Here's what that would look like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Network Architecture:&lt;/strong&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%2Fyvk8mf41se5gaon2jwjg.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%2Fyvk8mf41se5gaon2jwjg.png" alt=" " width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key differences:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2 in private subnet&lt;/strong&gt; - No public IP, no direct internet access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC Interface Endpoints&lt;/strong&gt; - Enable SSM access without internet gateway (~$21.60/month for 3 endpoints)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT Gateway&lt;/strong&gt; - If EC2 needs outbound internet access (~$32.40/month + data transfer)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudFront&lt;/strong&gt; - Global distribution and edge protection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why not include this in the current architecture?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VPC Interface Endpoints cost approximately &lt;strong&gt;$0.01/hour per endpoint&lt;/strong&gt; (~$7.20/month each). For Systems Manager to work in a private subnet, you need 3 endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;com.amazonaws.region.ssm&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;com.amazonaws.region.ec2messages&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;com.amazonaws.region.ssmmessages&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total cost: ~$21.60/month&lt;/strong&gt; just for the VPC Endpoints, plus additional complexity in setup and troubleshooting. For an educational article focused on WAF and application security fundamentals, this additional cost would make the architecture less accessible for learning purposes.&lt;/p&gt;

&lt;p&gt;The current implementation keeps the EC2 in a public subnet but eliminates SSH exposure entirely through Systems Manager Session Manager. While the instance has a public IP, the Security Group ensures no direct access is possible, only the ALB can reach it on port 80. This achieves approximately 90% of the security benefit of a private subnet at 0% of the additional cost, making it ideal for learning, development, and testing environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this matters for your security journey:
&lt;/h3&gt;

&lt;p&gt;This architecture demonstrates Layer 3, 4, and 7 protection fundamentals with encrypted transport, IAM based access control, and zero SSH exposure. It's an excellent educational starting point and works well for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development and testing environments&lt;/li&gt;
&lt;li&gt;Learning AWS security concepts and best practices&lt;/li&gt;
&lt;li&gt;Understanding the defense in depth model&lt;/li&gt;
&lt;li&gt;Proof of concepts and demos&lt;/li&gt;
&lt;li&gt;Small internal tools with limited exposure&lt;/li&gt;
&lt;li&gt;Personal projects and portfolios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, for &lt;strong&gt;&lt;u&gt;production workloads handling real user data, PII, or serving public traffic at scale&lt;/u&gt;&lt;/strong&gt;, you need the additional layers mentioned above. Security is not a single solution, it's a layered approach where each control addresses specific attack vectors and threat models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended next steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enable Session Manager logging&lt;/strong&gt; to CloudWatch for audit trails (minimal cost)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add rate-based rules&lt;/strong&gt; to WAF for basic request rate limiting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable CloudWatch logging&lt;/strong&gt; for WAF and create alarms for blocked requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement GuardDuty&lt;/strong&gt; for threat detection ($4-$10/month for light usage)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Security Hub&lt;/strong&gt; for centralized security findings (additional cost)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluate private subnet migration&lt;/strong&gt; with VPC Endpoints when budget allows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider CloudFront&lt;/strong&gt; for global distribution and additional edge protection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable automated patching&lt;/strong&gt; with Systems Manager Patch Manager&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these topics deserves its own deep dive, which I plan to cover in future articles as part of a comprehensive AWS security series.&lt;/p&gt;

&lt;p&gt;AWS WAF pricing is based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of Web ACLs&lt;/li&gt;
&lt;li&gt;Number of rules&lt;/li&gt;
&lt;li&gt;Number of requests inspected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few things to know for this setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS WAF is &lt;strong&gt;not&lt;/strong&gt; included in the AWS Free Tier&lt;/li&gt;
&lt;li&gt;For low traffic environments, costs are typically minimal&lt;/li&gt;
&lt;li&gt;Costs stay predictable as long as you clean up resources after testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're just experimenting, expect single digit dollar amounts per month for WAF itself, assuming moderate traffic.&lt;/p&gt;

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

&lt;p&gt;Security Groups and AWS WAF aren't competing solutions. They work at different layers and solve different problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Groups&lt;/strong&gt; control who can connect.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;AWS WAF&lt;/strong&gt; controls what those connections are trying to do.&lt;/p&gt;

&lt;p&gt;Understanding which control applies at which layer is what makes it possible to build secure, scalable architectures, even for relatively simple workloads.&lt;/p&gt;

&lt;p&gt;Protecting a web application doesn't require complex tooling. It requires putting the right controls at the right layers.&lt;/p&gt;

&lt;p&gt;If you're running web applications on EC2 without WAF, this architecture is a solid starting point.&lt;/p&gt;




&lt;h2&gt;
  
  
  A note on this content
&lt;/h2&gt;

&lt;p&gt;This article documents my learning journey with AWS security architecture. I'm sharing what I've learned and built, not claiming to be an expert. If you spot something that could be improved, or if you have a better approach, I genuinely want to hear about it.&lt;/p&gt;

&lt;p&gt;Security architecture is complex, and there are often multiple valid ways to solve the same problem. The setup I've described here prioritizes learning and understanding core concepts over production grade completeness. Real production environments would require additional layers like GuardDuty, Security Hub, comprehensive logging, and a more robust network isolation strategy.&lt;/p&gt;

&lt;p&gt;If you have feedback, corrections, or suggestions, please reach out that's how we all get better.&lt;/p&gt;

&lt;p&gt;Thanks for reading.🙂&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>aws</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Securing Serverless APIs with Amazon Cognito and API Gateway JWT Authorizers</title>
      <dc:creator>Geovane Oliveira</dc:creator>
      <pubDate>Wed, 24 Dec 2025 13:41:36 +0000</pubDate>
      <link>https://dev.to/geovane_oliveira/securing-serverless-apis-with-amazon-cognito-and-api-gateway-jwt-authorizers-5819</link>
      <guid>https://dev.to/geovane_oliveira/securing-serverless-apis-with-amazon-cognito-and-api-gateway-jwt-authorizers-5819</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Securing APIs is one of those topics that looks simple at first, but quickly becomes complex in real world scenarios.&lt;br&gt;
When you move to a serverless architecture, this challenge becomes even more critical.&lt;/p&gt;

&lt;p&gt;Many implementations end up pushing authentication logic into Lambda functions, creating custom token validation, extra code paths, and unnecessary operational overhead.&lt;/p&gt;

&lt;p&gt;In this article, I will walk through a practical and production ready approach to secure an AWS API Gateway endpoint using Amazon Cognito and the native JWT Authorizer, without Lambda authorizers or custom authentication logic.&lt;/p&gt;

&lt;p&gt;This setup is cost efficient, scalable, and relies entirely on managed AWS services.&lt;/p&gt;

&lt;p&gt;All the reference code and supporting artifacts used in this article are available in the following GitHub repository:&lt;br&gt;
&lt;a href="https://github.com/Geovane-Oliveira/aws-secure-serverless-api-cognito-jwt" rel="noopener noreferrer"&gt;aws-secure-serverless-api-cognito-jwt&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;The architecture used in this experiment is the following:&lt;/p&gt;

&lt;p&gt;Amazon Cognito User Pool for authentication&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Gateway HTTP API&lt;/li&gt;
&lt;li&gt;Native JWT Authorizer&lt;/li&gt;
&lt;li&gt;AWS Lambda as the backend&lt;/li&gt;
&lt;li&gt;CloudWatch Logs for observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key idea is to let Amazon Cognito handle authentication, while API Gateway is responsible for validating JWTs before the request ever reaches Lambda.&lt;/p&gt;

&lt;p&gt;This means invalid or expired tokens never invoke your backend code.&lt;/p&gt;

&lt;p&gt;The full request flow is illustrated in the diagram below:&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%2F4bfxw9r62921zpj5w370.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%2F4bfxw9r62921zpj5w370.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Creating the Cognito User Pool and App Client
&lt;/h2&gt;

&lt;p&gt;We start by creating a Cognito User Pool and an App Client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important configuration points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable USER_PASSWORD_AUTH&lt;/li&gt;
&lt;li&gt;Disable client secret (required for public clients and Postman testing)&lt;/li&gt;
&lt;li&gt;Use email as a sign-in alias&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%2Fvpfe9lzuxzawaarcp4ab.jpeg" 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%2Fvpfe9lzuxzawaarcp4ab.jpeg" alt="Cognito User Pool used as the authentication provider" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This App Client will be responsible for issuing Access Tokens and ID Tokens.&lt;/p&gt;

&lt;p&gt;This corresponds to step 1 in the architecture, where the user authenticates directly with Amazon Cognito.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User confirmation requirement:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When users are created manually or via the AWS Console, they may initially be in the &lt;code&gt;FORCE_CHANGE_PASSWORD&lt;/code&gt; or &lt;code&gt;UNCONFIRMED state&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For this experiment, the user must be fully confirmed before authentication succeeds.&lt;/p&gt;

&lt;p&gt;To ensure this, the user account was confirmed using AWS CloudShell and the AWS CLI, setting a permanent password and moving the user to the CONFIRMED state.&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%2F5w90virvs75kthdgph9u.jpeg" 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%2F5w90virvs75kthdgph9u.jpeg" alt="CloudShell confirming the Cognito user status" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This step is important because Cognito will reject authentication attempts for users that are not fully confirmed.&lt;/p&gt;

&lt;p&gt;Once the user is confirmed, authentication via Postman works as expected.&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%2F2bmcmq80doyfg1c20drr.jpeg" 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%2F2bmcmq80doyfg1c20drr.jpeg" alt="App Client settings" width="800" height="189"&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%2Fp3qfknmuf7fs8vp9soq8.jpeg" 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%2Fp3qfknmuf7fs8vp9soq8.jpeg" alt="App Client settings B" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2: Authenticating with Cognito
&lt;/h2&gt;

&lt;p&gt;Authentication is performed using the InitiateAuth API.&lt;/p&gt;

&lt;p&gt;Using Postman, we send a request to the Cognito endpoint with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AuthFlow: USER_PASSWORD_AUTH&lt;/li&gt;
&lt;li&gt;ClientId&lt;/li&gt;
&lt;li&gt;Username and password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If authentication succeeds, Cognito returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AccessToken&lt;/li&gt;
&lt;li&gt;IdToken&lt;/li&gt;
&lt;li&gt;RefreshToken&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, we already have everything needed to call a protected API.&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%2F38ubvarju4pecxasdq78.jpg" 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%2F38ubvarju4pecxasdq78.jpg" alt="PRINT 4 – Postman InitiateAuth request" width="800" height="469"&gt;&lt;/a&gt;&lt;br&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%2F3k4tksg9u56feupb0mth.jpg" 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%2F3k4tksg9u56feupb0mth.jpg" alt="PRINT 5 – Successful token response" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 3: Configuring the API Gateway JWT Authorizer
&lt;/h2&gt;

&lt;p&gt;Instead of using a Lambda Authorizer, we configure a native JWT Authorizer directly in API Gateway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key settings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Issuer:&lt;/strong&gt; Cognito User Pool issuer URL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audience:&lt;/strong&gt; Cognito App Client ID&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity source:&lt;/strong&gt; Authorization header&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells API Gateway exactly how to validate incoming JWTs automatically.&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%2Flrdneq2b9gkw5ksvowew.jpeg" 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%2Flrdneq2b9gkw5ksvowew.jpeg" alt="PRINT 6 – JWT Authorizer configuration" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 4: Protecting the API Route
&lt;/h2&gt;

&lt;p&gt;Next, we attach the JWT Authorizer to the /secure route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Once attached:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests without a token return 401 Unauthorized&lt;/li&gt;
&lt;li&gt;Requests with invalid or expired tokens are rejected&lt;/li&gt;
&lt;li&gt;Only valid tokens are allowed through&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this is enforced by API Gateway itself, before Lambda is invoked.&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%2Fjggkq50g3supgyqg84c5.jpeg" 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%2Fjggkq50g3supgyqg84c5.jpeg" alt="PRINT 7 – Route authorization attached" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 5: Lambda Backend and Token Claims
&lt;/h2&gt;

&lt;p&gt;At this stage, authentication and token validation are already completed.&lt;/p&gt;

&lt;p&gt;The Lambda function does not validate JWTs, does not decode tokens, and does not contain authentication logic.&lt;/p&gt;

&lt;p&gt;API Gateway injects the decoded JWT claims directly into the request context, under:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;event.requestContext.authorizer.jwt.claims&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below is the complete Lambda function used as the secure backend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json

def lambda_handler(event, context):
    print("Lambda secure-api-backend INVOCADA")
    print("RequestId:", context.aws_request_id)

    claims = event["requestContext"]["authorizer"]["jwt"]["claims"]

    print("JWT claims recebidas:")
    print(json.dumps({
        "sub": claims.get("sub"),
        "email": claims.get("email"),
        "username": claims.get("cognito:username"),
        "issuer": claims.get("iss"),
        "token_use": claims.get("token_use"),
        "scope": claims.get("scope")
    }))

    response = {
        "message": "Authorized request",
        "user": {
            "sub": claims.get("sub"),
            "email": claims.get("email"),
            "username": claims.get("cognito:username"),
            "issuer": claims.get("iss"),
            "token_use": claims.get("token_use"),
            "scope": claims.get("scope")
        }
    }

    return {
        "statusCode": 200,
        "headers": {
            "Content-Type": "application/json"
        },
        "body": json.dumps(response)
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This keeps the backend extremely simple and focused:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Gateway handles security&lt;/li&gt;
&lt;li&gt;Lambda consumes already validated identity data&lt;/li&gt;
&lt;li&gt;Logs provide full traceability&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%2F6w2eyw4ql2njryh2k7xt.jpeg" 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%2F6w2eyw4ql2njryh2k7xt.jpeg" alt="PRINT 8 – Lambda code" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Validation and Results
&lt;/h2&gt;

&lt;p&gt;We tested three different scenarios:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No token&lt;/strong&gt;&lt;br&gt;
401 Unauthorized&lt;br&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%2Fqoq1h52wuuungfv456kr.jpg" 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%2Fqoq1h52wuuungfv456kr.jpg" alt="PRINT 10 – Postman unauthorized response" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invalid token&lt;/strong&gt;&lt;br&gt;
401 Unauthorized&lt;br&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%2Ftpyljkme2mmlmyip7vt8.jpg" 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%2Ftpyljkme2mmlmyip7vt8.jpg" alt="Invalid token" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Valid Access Token&lt;/strong&gt;&lt;br&gt;
200 OK and Lambda executed&lt;br&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%2Fi2qrwq3e9wogrfpfqk4k.jpg" 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%2Fi2qrwq3e9wogrfpfqk4k.jpg" alt="PRINT 11 – Postman authorized response + Lambda output" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CloudWatch Logs confirm that the Lambda function is only invoked when the token is valid, proving that the security boundary is enforced at the API Gateway level.&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%2Fk205l085kkryqvbxja8v.jpeg" 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%2Fk205l085kkryqvbxja8v.jpeg" alt="PRINT 9 – CloudWatch Logs showing JWT claims" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Reference Implementation
&lt;/h2&gt;

&lt;p&gt;The complete reference implementation, including the Lambda function, Postman collection, and architecture diagram, is available on GitHub:&lt;br&gt;
&lt;a href="https://github.com/Geovane-Oliveira/aws-secure-serverless-api-cognito-jwt" rel="noopener noreferrer"&gt;aws-secure-serverless-api-cognito-jwt&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Using Amazon Cognito together with API Gateway JWT Authorizers is one of the cleanest and most efficient ways to secure serverless APIs on AWS.&lt;/p&gt;

&lt;p&gt;There is no custom authentication code, no Lambda Authorizers, and no additional infrastructure to manage.&lt;/p&gt;

&lt;p&gt;API Gateway becomes the security gate, and Lambda focuses only on business logic.&lt;/p&gt;

&lt;p&gt;This is a pattern I recommend for modern, scalable, and secure serverless applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  A note on this content
&lt;/h2&gt;

&lt;p&gt;This article documents my learning journey with AWS security architecture. I'm sharing what I've learned and built, not claiming to be an expert. If you spot something that could be improved, or if you have a better approach, I genuinely want to hear about it.&lt;/p&gt;

&lt;p&gt;If you have feedback, corrections, or suggestions, please reach out that's how we all get better.&lt;/p&gt;

&lt;p&gt;Thanks for reading.🙂&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>serverless</category>
      <category>awscommunitybuilder</category>
    </item>
  </channel>
</rss>
