<?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: Rahman Badru</title>
    <description>The latest articles on DEV Community by Rahman Badru (@rahmantheman).</description>
    <link>https://dev.to/rahmantheman</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%2F1249794%2Fd5c08514-60a6-47c6-9114-2e941c4ab31c.jpg</url>
      <title>DEV Community: Rahman Badru</title>
      <link>https://dev.to/rahmantheman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rahmantheman"/>
    <language>en</language>
    <item>
      <title>Sports API Management System</title>
      <dc:creator>Rahman Badru</dc:creator>
      <pubDate>Sun, 09 Feb 2025 19:48:13 +0000</pubDate>
      <link>https://dev.to/rahmantheman/sports-api-management-system-1k</link>
      <guid>https://dev.to/rahmantheman/sports-api-management-system-1k</guid>
      <description>&lt;h2&gt;
  
  
  Project Description
&lt;/h2&gt;

&lt;p&gt;This project demonstrates building a containerized api management system for querying sports data. It uses &lt;em&gt;Amazon ECS&lt;/em&gt; for running containers, &lt;em&gt;Amazon API Gateway&lt;/em&gt; for exposing REST Endpoints and an external Sports API for real-time sports data. The project showcases advanced cloud computing practices, including API management, container orchestration, and secure AWS integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Architecture
&lt;/h2&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%2Fuzcdjqm4ogggzy9vfvwv.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%2Fuzcdjqm4ogggzy9vfvwv.png" alt="Image description" width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Clone the Repository
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ifeanyiro9/containerized-sports-api.git
&lt;span class="nb"&gt;cd &lt;/span&gt;containerized-sports-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-Create an ECR Repository&lt;br&gt;
&lt;code&gt;aws ecr create-repository --repository-name sports-api --region us-east-1&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticate, Build, and Push Docker Image
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &amp;lt;AWS_ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com

docker build &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 &lt;span class="nt"&gt;-t&lt;/span&gt; sports-api &lt;span class="nb"&gt;.&lt;/span&gt;
docker tag sports-api:latest &amp;lt;AWS_ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/sports-api:sports-api-latest
docker push &amp;lt;AWS_ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/sports-api:sports-api-latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Set Up an ECS Cluster with Fargate&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an ECS Cluster:&lt;/li&gt;
&lt;li&gt;Navigate to the ECS Console → Clusters → Create Cluster.&lt;/li&gt;
&lt;li&gt;Name the cluster (e.g., sports-api-cluster).&lt;/li&gt;
&lt;li&gt;Choose Fargate as the infrastructure type, then create the cluster.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Create a Task Definition:&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Go to Task Definitions → Create New Task Definition.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name the task definition (e.g., sports-api-task).&lt;/li&gt;
&lt;li&gt;Choose Fargate as the infrastructure type.&lt;/li&gt;
&lt;li&gt;Add the container:&lt;/li&gt;
&lt;li&gt;Name: sports-api-container&lt;/li&gt;
&lt;li&gt;Image URI: .dkr.ecr.us-east-1.amazonaws.com/sports-api:sports-api-latest&lt;/li&gt;
&lt;li&gt;Container Port: 8080&lt;/li&gt;
&lt;li&gt;Environment Variables:

&lt;ul&gt;
&lt;li&gt;Key: SPORTS_API_KEY&lt;/li&gt;
&lt;li&gt;Value: &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Save and create the task definition.&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Deploy the Service with an Application Load Balancer (ALB):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Clusters → Select Cluster → Service → Create Service.&lt;/li&gt;
&lt;li&gt;Configuration:&lt;/li&gt;
&lt;li&gt;Capacity Provider: Fargate&lt;/li&gt;
&lt;li&gt;Task Definition: sports-api-task&lt;/li&gt;
&lt;li&gt;Service Name: sports-api-service&lt;/li&gt;
&lt;li&gt;Desired Tasks: 2&lt;/li&gt;
&lt;li&gt;Networking:

&lt;ul&gt;
&lt;li&gt;Create a new security group allowing TCP traffic.&lt;/li&gt;
&lt;li&gt;Type: All TCP, Source: Anywhere&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Load Balancer:

&lt;ul&gt;
&lt;li&gt;Select Application Load Balancer (ALB).&lt;/li&gt;
&lt;li&gt;ALB Configuration:&lt;/li&gt;
&lt;li&gt;Create a new ALB named sports-api-alb.&lt;/li&gt;
&lt;li&gt;Health Check Path: /sports&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Create the service.&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Test the ALB:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve the ALB DNS name (e.g., sports-api-alb-.us-east-1.elb.amazonaws.com).&lt;/li&gt;
&lt;li&gt;Verify the API is accessible by visiting &lt;a href="http://sports-api-alb-" rel="noopener noreferrer"&gt;http://sports-api-alb-&lt;/a&gt;.us-east-1.amazonaws.com/sports.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Configure API Gateway&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a REST API:&lt;/li&gt;
&lt;li&gt;Navigate to API Gateway Console → Create API → REST API.&lt;/li&gt;
&lt;li&gt;Name the API (e.g., Sports API Gateway).&lt;/li&gt;
&lt;li&gt;Set Up Integration:&lt;/li&gt;
&lt;li&gt;Create a resource /sports.&lt;/li&gt;
&lt;li&gt;Create a GET method and choose HTTP Proxy as the integration type.&lt;/li&gt;
&lt;li&gt;Enter the ALB DNS name followed by /sports.&lt;/li&gt;
&lt;li&gt;Deploy the API:
-Deploy the API to a stage (e.g., prod) and note the endpoint URL.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Test the System&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a browser or curl to test:
&lt;code&gt;curl https://&amp;lt;api-gateway-id&amp;gt;.execute-api.us-east-1.amazonaws.com/prod/sports&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;This project demonstrates how to build a scalable, containerized sports data API management system using modern AWS services such as ECS with Fargate, API Gateway, and CloudWatch. By integrating these services, we achieved a reliable and secure infrastructure for hosting and managing APIs, while also adhering to best practices like containerization and least privilege IAM policies. Future enhancements like caching with ElastiCache, user-specific data storage with DynamoDB, and implementing CI/CD pipelines can further optimize the system for performance and maintainability. This documentation serves as a comprehensive guide to replicate, deploy, and extend the system, empowering developers to leverage AWS for similar use cases.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>NBA DATA LAKE</title>
      <dc:creator>Rahman Badru</dc:creator>
      <pubDate>Mon, 13 Jan 2025 20:26:07 +0000</pubDate>
      <link>https://dev.to/rahmantheman/nba-data-lake-41i9</link>
      <guid>https://dev.to/rahmantheman/nba-data-lake-41i9</guid>
      <description>&lt;h1&gt;
  
  
  Project Description
&lt;/h1&gt;

&lt;p&gt;This project automates the creation of a data lake for NBA Analytics using AWS Services. It makes use of AWS S3, Glue and Athena to store and query NBA related Data&lt;/p&gt;

&lt;p&gt;This is the third project for the Devops All Stars Challenge&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Architecture
&lt;/h2&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%2Frp16g65kzjv8bqm939eu.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%2Frp16g65kzjv8bqm939eu.png" alt="Image description" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Overview
&lt;/h3&gt;

&lt;p&gt;The script &lt;code&gt;data-lake.py&lt;/code&gt; creates an Amazon Bucket to store raw data, uploads NBA Data (json format) to the Bucket and creates an Amazon glue database and table to query the data, It also configures Amazon Athena for querying data stored in the S3 bucket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get your api key from &lt;a href="//sportsdata.io"&gt;sportsdata&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the file called data-lake.py and copy the contents of the &lt;code&gt;src/data-lake.py&lt;/code&gt; inside&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Create the env file:
&lt;/h2&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;nano .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following variables in the env file:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SPORTS_DATA_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{SPORTS_DATA_API_KEY}"&lt;/span&gt;
&lt;span class="nv"&gt;NBA_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.sportsdata.io/v3/nba/scores/json/Players"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install requirements from the &lt;code&gt;requirements.txt&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv &lt;span class="c"&gt;## To create a virtual environment&lt;/span&gt;
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate &lt;span class="c"&gt;## To activate virtual environment&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt &lt;span class="c"&gt;## to install requirements&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Set your &lt;code&gt;bucket_name&lt;/code&gt; and &lt;code&gt;glue_database_name&lt;/code&gt; in the &lt;code&gt;data-lake.py&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the code with &lt;code&gt;python3 src/data-lake.py&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Login to AWS Console and confirm:

&lt;ul&gt;
&lt;li&gt;The S3 Bucket has been created&lt;/li&gt;
&lt;li&gt;The Amazon Glue Database has been created&lt;/li&gt;
&lt;li&gt;Run an athena query to confirm with this, Go to Amazon Athena and paste in Query Editor:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;Position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Team&lt;/span&gt;
 &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;nba_players&lt;/span&gt;
 &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;Position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'PG'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a 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%2Fn1f65sgbpogh64tj9luk.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%2Fn1f65sgbpogh64tj9luk.png" alt="Image description" width="800" height="400"&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%2Fugs0e0kz853jwfqfciij.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%2Fugs0e0kz853jwfqfciij.png" alt="Image description" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can clean up resources by runnning &lt;code&gt;python3 src/delete-resources.py&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This project demonstrates the power of AWS services in creating a robust and automated data lake for NBA analytics. By integrating Amazon S3 for data storage, AWS Glue for data cataloging, and Amazon Athena for querying, we have built a scalable and efficient pipeline for managing and analyzing NBA data. The simplicity of the setup process ensures accessibility for developers, while the automated cleanup script emphasizes resource management and cost efficiency. This project not only highlights the capabilities of cloud-based data lakes but also serves as a foundation for exploring more advanced data analytics and insights, making it an invaluable asset for sports analytics enthusiasts and professionals.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Day 2: Creating NBA Game Day Notification System using Event-Driven Architecture</title>
      <dc:creator>Rahman Badru</dc:creator>
      <pubDate>Sat, 11 Jan 2025 09:44:01 +0000</pubDate>
      <link>https://dev.to/rahmantheman/day-2-creating-nba-game-day-notification-system-using-event-driven-architecture-14kh</link>
      <guid>https://dev.to/rahmantheman/day-2-creating-nba-game-day-notification-system-using-event-driven-architecture-14kh</guid>
      <description>&lt;h2&gt;
  
  
  Project Description
&lt;/h2&gt;

&lt;p&gt;This article details building a notification system using event driven architecture that sends NBA Game day Results to your mail at specific intervals.&lt;/p&gt;

&lt;p&gt;This is the second project for the Devops All Stars Challenge&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Architecture
&lt;/h2&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%2Fi8q4pwj7258pwtuvjktd.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%2Fi8q4pwj7258pwtuvjktd.png" alt="Image description" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Requirements
&lt;/h2&gt;

&lt;p&gt;The following services/tools are required for this project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AWS Lambda&lt;/li&gt;
&lt;li&gt;AWS EventBridge&lt;/li&gt;
&lt;li&gt;AWS SNS (Simple Notification System)&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Project Workflow
&lt;/h2&gt;

&lt;p&gt;Basically the project uses AWS EventBridge to run a scheduled rule at intervals that triggers the Lambda Function which contains a python script to pull game data via the Sports Data API and send to an SNS Topic which is then now sent to either your mail or sms&lt;/p&gt;

&lt;p&gt;The Project can be found here: &lt;a href="https://github.com/RahmanBadru/gameday-notifications" rel="noopener noreferrer"&gt;Gameday-Notification&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This project is implemented as follows:&lt;/p&gt;

&lt;h3&gt;
  
  
  Create AWS SNS TOPIC
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the AWS Management Console&lt;/li&gt;
&lt;li&gt;GO to SNS&lt;/li&gt;
&lt;li&gt;Click on topics, click create topic&lt;/li&gt;
&lt;li&gt;Select Standard as topic type&lt;/li&gt;
&lt;li&gt;Name your topic (e.g gameday-topic) and click create topic&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create a Subscription for the Topic
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click on your topic&lt;/li&gt;
&lt;li&gt;Click create subscription&lt;/li&gt;
&lt;li&gt;Set Protocol to email&lt;/li&gt;
&lt;li&gt;Put your mail&lt;/li&gt;
&lt;li&gt;Click create Subscription&lt;/li&gt;
&lt;li&gt;Confirm the subscription from your mail&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create an SNS Publish Policy
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the IAM service in the AWS Management Console.&lt;/li&gt;
&lt;li&gt;Navigate to Policies → Create Policy.&lt;/li&gt;
&lt;li&gt;Click JSON and paste the JSON policy from gd_sns_policy.json file&lt;/li&gt;
&lt;li&gt;Replace REGION and ACCOUNT_ID with your AWS region and account ID.&lt;/li&gt;
&lt;li&gt;Click Next: Tags (you can skip adding tags).&lt;/li&gt;
&lt;li&gt;Click Next: Review.&lt;/li&gt;
&lt;li&gt;Enter a name for the policy (e.g., gameday-policy).&lt;/li&gt;
&lt;li&gt;Review and click Create Policy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Create IAM Role for Lambda
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the IAM service in the AWS Management Console.&lt;/li&gt;
&lt;li&gt;Navigate to Roles -&amp;gt; Create Role&lt;/li&gt;
&lt;li&gt;Click on use case drop down and click Lambda&lt;/li&gt;
&lt;li&gt;Click Next and then attach two policies:

&lt;ul&gt;
&lt;li&gt;The policy create earlier (gameday-policy)&lt;/li&gt;
&lt;li&gt;The Lambda Basic Execution Role (AWSLambdaBasicExecutionRole) (an AWS managed policy).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CLick Next, skip tags and create the role&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%2Fpu5jpkvov3c1kc14x7ua.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%2Fpu5jpkvov3c1kc14x7ua.png" alt="IAM ROLE" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Lambda Function
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the AWS Management Console and navigate to the Lambda service.&lt;/li&gt;
&lt;li&gt;Click Create Function.&lt;/li&gt;
&lt;li&gt;Select Author from Scratch.&lt;/li&gt;
&lt;li&gt;Enter a function name (e.g., gameday-function).&lt;/li&gt;
&lt;li&gt;Choose Python 3.x as the runtime.&lt;/li&gt;
&lt;li&gt;Assign the IAM role created earlier (gameday-role) to the function.&lt;/li&gt;
&lt;li&gt;Under the Function Code section:

&lt;ul&gt;
&lt;li&gt;Copy the content of the src/gd_notifications.py file from the repository.&lt;/li&gt;
&lt;li&gt;Paste it into the inline code editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Under the Environment Variables section, add the following:

&lt;ul&gt;
&lt;li&gt;NBA_API_KEY: your NBA API key.&lt;/li&gt;
&lt;li&gt;SNS_TOPIC_ARN: the ARN of the SNS topic created earlier.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click Create Function&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Set up EventBridge Schedule to trigger Lambda
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the Eventbridge service in the AWS Management Console.&lt;/li&gt;
&lt;li&gt;Go to Rules → Create Rule.&lt;/li&gt;
&lt;li&gt;Select Event Source: Schedule.&lt;/li&gt;
&lt;li&gt;Set the cron schedule for when you want updates (e.g., hourly).&lt;/li&gt;
&lt;li&gt;Under Targets, select the Lambda function (gameday-function) and save the rule.&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%2F9thrkb3l2vhfx05t3c16.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%2F9thrkb3l2vhfx05t3c16.png" alt="Event Bridge" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the System
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open Lambda function and click on the function you created&lt;/li&gt;
&lt;li&gt;click on test and name the event&lt;/li&gt;
&lt;li&gt;Test the function&lt;/li&gt;
&lt;li&gt;Verify you get a mail confirming it was successful&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%2Fixxub8tby1t6a7ch7zhy.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%2Fixxub8tby1t6a7ch7zhy.png" alt="Successful Game day Updates" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This project demonstrates how to build a notification system using event-driven architecture on AWS. By leveraging AWS Lambda, EventBridge, and SNS, you can create a reliable and efficient system to receive NBA Game Day updates via email or SMS. This setup is a great example of automating tasks and building scalable systems using cloud services.&lt;/p&gt;

</description>
      <category>eventdriven</category>
      <category>aws</category>
    </item>
    <item>
      <title>Day 1: Setting up the AWS Weather Dashboard Application</title>
      <dc:creator>Rahman Badru</dc:creator>
      <pubDate>Thu, 09 Jan 2025 21:19:37 +0000</pubDate>
      <link>https://dev.to/rahmantheman/day-1-setting-up-the-aws-weather-dashboard-application-23oj</link>
      <guid>https://dev.to/rahmantheman/day-1-setting-up-the-aws-weather-dashboard-application-23oj</guid>
      <description>&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;This project is a part of the 30 Days All Star Devops Challenge that aims to increase proficiency in Devops through a series of hands-on projects and documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Description
&lt;/h2&gt;

&lt;p&gt;This project makes use of Python and AWS Services (S3) to retrieve weather data from OpenWeatherAPI and stores the results in a json format in an S3 Bucket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools Used:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Python: Language used to set up the Weather Dashboard&lt;/li&gt;
&lt;li&gt;AWS S3 ( Simple Storage Service): AWS Storage Solution&lt;/li&gt;
&lt;li&gt;OpenWeather API Key&lt;/li&gt;
&lt;li&gt;Boto3 : AWS SDK used by python to interact with the S3 Bucket&lt;/li&gt;
&lt;li&gt;requests: Python library used to send requests and fetch data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Environment Setup
&lt;/h3&gt;

&lt;p&gt;Before implementing the weather dashboard, here are a few things needed to set up your environment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;AWS Account and AWS CLI: You need an AWS Account where your bucket will be created and the AWS CLI to set up credentials to interact with AWS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python: Make sure Python &lt;code&gt;3.x&lt;/code&gt; is installed on your system as well as pip, It will be needed to install libraries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenWeather API Key: Get the OpenWeather API Key by signing up to this page &lt;a href="https://openweathermap.org/api" rel="noopener noreferrer"&gt;OpenWeather&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Architecture Diagram
&lt;/h3&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%2Fchp97ak11kmpyrp8lgmf.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%2Fchp97ak11kmpyrp8lgmf.png" alt="Image description" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Workflow
&lt;/h3&gt;

&lt;p&gt;This project uses a python script that fetches weather data from openweather via its API Key and then sends/stores it to a S3 bucket in JSON Format&lt;/p&gt;

&lt;p&gt;Here are some excerpts of the code:&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;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherDashboard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPENWEATHER_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Get the OpenWeather API key from environment variables
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS_BUCKET_NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Get the AWS S3 bucket name from environment variables
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Create an S3 client for interacting with AWS S3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets up the API key, bucket name, and S3 client when you create an instance of the WeatherDashboard class.&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;fetch_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://api.openweathermap.org/data/2.5/weather&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# The API endpoint for weather data
&lt;/span&gt;    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                        &lt;span class="c1"&gt;# The city name to fetch weather for
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;appid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;# The API key for authentication
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;units&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;imperial&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;               &lt;span class="c1"&gt;# Use imperial units (Fahrenheit)
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&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;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Make a GET request to the API
&lt;/span&gt;        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                       &lt;span class="c1"&gt;# Raise an error if the response indicates failure
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                            &lt;span class="c1"&gt;# Return the weather data as JSON
&lt;/span&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error fetching weather data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Print error if the request fails
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This section gets weather information like temperature and conditions for a given city&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;save_to_s3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# If no data is passed, return False (skip saving)
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%Y%m%d-%H%M%S&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Create a timestamp (e.g., 20250107-153045)
&lt;/span&gt;    &lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weather-data/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;    &lt;span class="c1"&gt;# Define the file path and name
&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;  &lt;span class="c1"&gt;# Add a timestamp to the weather data
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;             &lt;span class="c1"&gt;# Save the data to S3
&lt;/span&gt;            &lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# The S3 bucket name
&lt;/span&gt;            &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                     &lt;span class="c1"&gt;# The file path in the bucket
&lt;/span&gt;            &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weather_data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;     &lt;span class="c1"&gt;# Convert data to JSON format for saving
&lt;/span&gt;            &lt;span class="n"&gt;ContentType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;     &lt;span class="c1"&gt;# Specify the file type as JSON
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully saved data for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; to S3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Confirm success
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error saving to S3: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Print error if saving fails
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This section saves it in s3 bucket&lt;/p&gt;

&lt;p&gt;To run the project on your machine, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clone the repository from here: &lt;a href="https://github.com/RahmanBadru/weather-dashboard" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follow the instructions in the README here: &lt;a href="https://github.com/RahmanBadru/weather-dashboard/blob/main/README.md" rel="noopener noreferrer"&gt;README.md&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When the project has been run, you should get the following output&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%2Ft3ggron37c85op35bj6m.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%2Ft3ggron37c85op35bj6m.png" alt="Image description" width="800" height="228"&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%2Fpr3mpmnyq4zi3ukc49bg.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%2Fpr3mpmnyq4zi3ukc49bg.png" alt="Image description" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This project successfully demonstrates how to build a simple yet functional weather dashboard application by integrating Python, OpenWeatherAPI, and AWS S3. Through this project, we explored retrieving real-time weather data using APIs, processing it in Python, and securely storing the results in an S3 bucket in JSON format. It highlights practical use cases of Python libraries like boto3 and requests, emphasizing the importance of cloud storage solutions in managing and persisting data. This project is an excellent starting point for developers looking to enhance their skills in API integration, cloud computing, and DevOps practices.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>devops</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Enhance Your Web Protection: AWS WAF Essentials</title>
      <dc:creator>Rahman Badru</dc:creator>
      <pubDate>Mon, 15 Apr 2024 09:46:56 +0000</pubDate>
      <link>https://dev.to/rahmantheman/enhance-your-web-protection-aws-waf-essentials-1ff3</link>
      <guid>https://dev.to/rahmantheman/enhance-your-web-protection-aws-waf-essentials-1ff3</guid>
      <description>&lt;h3&gt;
  
  
  &lt;u&gt;What is the AWS WAF?&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;The AWS WAF which stands for Web Application Firewall is a tool that lets you monitor requests to your web application resources. It protects some of the following AWS Resources like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Cloudfront Distribution&lt;/li&gt;
&lt;li&gt;Application Load Balancer&lt;/li&gt;
&lt;li&gt;Amazon API Gateway REST API and a couple of other resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;What does the AWS WAF do?&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;It basically lets you control access to your content, Based on whatever conditions you specify e.g the IP addresses the requests come from, the path being requested or the location the requests originate from , the service associated with whichever resource is being protected either gives the right response, or a forbidden permission response ( also known as the 403 error) or a custom response configured by the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;How does the AWS WAF work&lt;/u&gt;?
&lt;/h3&gt;

&lt;p&gt;The WAF works to control how your protected resources respond to web requests and it does that using a Web ACL (Access Control List) and associating it with the resources to be secured. The resources then forward any incoming requests to the ACL for inspection.&lt;/p&gt;

&lt;p&gt;With the web access control list,you define rules for traffic patterns which you look for in those requests,and then set the action to be taken on requests that match the patterns, which can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Allow the requests to go to the protected resource for processing and response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Block the requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run CAPTCHA or challenge checks against requests to verify human users&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;u&gt; Components of the WAF&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;These are some of the components that make up the AWS WAF&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Web ACL: You use this to protect your AWS resources via rules, The rules help define the criteria for the requests coming in and also the action to take on requests that match the rules, You can set default actions on matched requests as listed above. As an example, you can set a rule to block all requests coming from a specific IP address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rules: These are the building blocks of the Web ACL and they determine what actions are to be taken on requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rule Groups: A rule group is a reusable set of rules that you can add to a web ACL.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;Configuring the AWS WAF (Walkthrough)&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;To show the capabilities of the AWS Web Application Firewall, we will create an EC2 Instance running Wordpress, place it behind an Application Load Balancer and associate a WAF Web ACL to it.&lt;/p&gt;

&lt;p&gt;We will then explore rules we can create , as well as set up logging for the WAF.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;u&gt;Step 1 - Creating the EC2 Instance.&lt;/u&gt;
&lt;/h5&gt;

&lt;p&gt;First we create the EC2 Instance , using a wordpress image gotten from this link: &lt;a href="https://bitnami.com/stack/wordpress/cloud/aws/amis" rel="noopener noreferrer"&gt;https://bitnami.com/stack/wordpress/cloud/aws/amis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the image id for the region you want to deploy the instance in.&lt;/p&gt;

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

&lt;p&gt;Login to the AWS EC2 Console: &lt;a href="https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#Home:" rel="noopener noreferrer"&gt;EC2 Console&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on launch instance.&lt;/p&gt;

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

&lt;p&gt;Give the instance , the name &lt;strong&gt;wordpress&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;Application and OS Images&lt;/strong&gt;, Paste the image ID you copied and search for it under Community Images.&lt;/p&gt;

&lt;p&gt;Select the &lt;strong&gt;Image&lt;/strong&gt;&lt;/p&gt;

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

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

&lt;p&gt;Leave the &lt;strong&gt;instance type&lt;/strong&gt; as default (t2.micro) which is free tier &lt;/p&gt;

&lt;p&gt;Set the &lt;strong&gt;key pair login&lt;/strong&gt; to "Proceed without a keypair" as we don't need access to the instance.&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;Network settings&lt;/strong&gt;, click edit&lt;/p&gt;

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

&lt;p&gt;Make sure the &lt;strong&gt;default VPC&lt;/strong&gt; is selected and ensure auto assign public IP is enabled.&lt;/p&gt;

&lt;p&gt;Create a &lt;strong&gt;new security group&lt;/strong&gt; named &lt;strong&gt;wordpress-waf&lt;/strong&gt; and change the security group rule 1 to HTTP.&lt;/p&gt;

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

&lt;p&gt;Leave all other settings as default and launch the instance.&lt;/p&gt;

&lt;p&gt;Once the instance has been created, copy the public ip and navigate to it in your browser.&lt;/p&gt;

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

&lt;p&gt;You should see the wordpress default page.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  &lt;u&gt;Step 2 - Creating a target group.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Go back to the EC2 Console: &lt;a href="https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#Home:" rel="noopener noreferrer"&gt;EC2 Console&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to target groups and click on create target group.&lt;/p&gt;

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

&lt;p&gt;Choose the &lt;strong&gt;target type&lt;/strong&gt; as instances.&lt;/p&gt;

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

&lt;p&gt;Set the &lt;strong&gt;target group name&lt;/strong&gt; to be wordpress&lt;/p&gt;

&lt;p&gt;Leave everything else as default and click Next.&lt;/p&gt;

&lt;p&gt;Select the instance created previously and select include as pending below.&lt;/p&gt;

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

&lt;p&gt;Click on create target group.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;u&gt;Step 3 - Creating an Application Load Balancer.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;On the EC2 Console Page , click on load balancers and then create load balancer.&lt;/p&gt;

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

&lt;p&gt;Select the &lt;strong&gt;Application Load Balancer&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Set the Load Balancer name to wordpress-lb&lt;/p&gt;

&lt;p&gt;Make sure the VPC is default and select all subnets under Network mapping.&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Security Groups&lt;/strong&gt;, select the wordpress-waf group we created&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Listeners and Routing&lt;/strong&gt; , change the action for HTTP to forward to the wordpress target group we created earlier.&lt;/p&gt;

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

&lt;p&gt;Leave all other settings and create the load Balancer.&lt;/p&gt;

&lt;p&gt;Once the ALB ( Application Load Balancer ) is created , Paste the DNS Name in the Browser, you should see the same wordpress default page as earlier.&lt;/p&gt;

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

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

&lt;h4&gt;
  
  
  &lt;u&gt;Step 4 - Creating an s3 Bucket for WAF Logs.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Head to the S3 Console: &lt;a href="https://us-east-1.console.aws.amazon.com/s3/home?region=us-east-1" rel="noopener noreferrer"&gt;S3 Console&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to Buckets and click create bucket.&lt;/p&gt;

&lt;p&gt;S3 buckets for aws waf logs must begin with &lt;strong&gt;aws-waf-logs-&lt;/strong&gt; , so name your bucket with that prefix.&lt;/p&gt;

&lt;p&gt;Make sure the bucket is in the same region as your EC2 Instance.&lt;/p&gt;

&lt;p&gt;Leave all other settings as default and create the bucket.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  &lt;u&gt;Step 5 - Setting up the WAF.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Go over to the WAF Console, which can be found here: &lt;a href="https://us-east-1.console.aws.amazon.com/wafv2/home?region=us-east-1" rel="noopener noreferrer"&gt;https://us-east-1.console.aws.amazon.com/wafv2/home?region=us-east-1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ensure that the region is the same as the region your instance is in, in my case, its the us-east-1 region.&lt;/p&gt;

&lt;p&gt;First, we would create an IP Set, which is basically a group of IP's ( which is used commonly for IP addresses you want to allow).  IP Sets can contain up to &lt;strong&gt;10,000 CIDR ranges&lt;/strong&gt;, which makes allowing or blocking large numbers of networks very easy.&lt;/p&gt;

&lt;p&gt;Check your IP address using this link: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://checkip.amazonaws.com/" rel="noopener noreferrer"&gt;https://checkip.amazonaws.com/&lt;/a&gt; and copy your IP Address.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;IP Sets&lt;/strong&gt; and create IP Set.&lt;/p&gt;

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

&lt;p&gt;Set the IP Set name to &lt;strong&gt;home-ip&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the IP Addresses box, add the IP you copied with the /32. e.g 172.35.40.78/32.&lt;/p&gt;

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

&lt;p&gt;Create the IP Set.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;Regex Pattern Sets&lt;/strong&gt; and click on create regex pattern set.&lt;/p&gt;

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

&lt;p&gt;Set the regex pattern name to &lt;strong&gt;no-wp-files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the Regular expressions box, enter:&lt;/p&gt;

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

(wp\-login\.php)$
(.*wp\-config.*)
(xmlrpc\.php)


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

&lt;/div&gt;

&lt;p&gt;Click on create regex pattern set.&lt;/p&gt;

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

&lt;p&gt;Go to &lt;strong&gt;Web ACL&lt;/strong&gt;  and click on create Web ACL&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Resource Type&lt;/strong&gt;, click Regional Resources.&lt;/p&gt;

&lt;p&gt;Set the Name to &lt;strong&gt;wordpress-acl&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Associated AWS Resources&lt;/strong&gt;, click Add AWS Resources.&lt;/p&gt;

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

&lt;p&gt;Under AWS Resources, click on Application Load Balancer and select the ALB we created earlier.&lt;/p&gt;

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

&lt;p&gt;Click on next.&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;Rules&lt;/strong&gt;, click on Add Rules, and then Add Managed rule groups.&lt;/p&gt;

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

&lt;p&gt;Expand AWS Managed Rule Groups and you will see a list of WAF rule groups that are supplied and maintained by AWS.&lt;/p&gt;

&lt;p&gt;Under the Free Rule Groups, Select the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core rule set&lt;/li&gt;
&lt;li&gt;PHP application&lt;/li&gt;
&lt;li&gt;SQL database&lt;/li&gt;
&lt;li&gt;WordPress application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each rule group has a description showing what kind of attacks the rule group helps protect against.&lt;/p&gt;

&lt;p&gt;Given that our infrastructure is centered around a WordPress application, it's essential to prioritize the WordPress rules for enhanced protection. Additionally, since WordPress is PHP-based, integrating PHP application rules is crucial. As our WordPress database relies on MySQL, implementing the SQL database rule set becomes imperative to safeguard against potential SQL Injection attacks, among other threats.&lt;/p&gt;

&lt;p&gt;The “Core rule set” contains the most rules, and protects against common attack methods provided by the open source OWASP organisation&lt;/p&gt;

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

&lt;p&gt;Click on Add rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Note:&lt;/u&gt;&lt;/strong&gt; each rule group has a “capacity” value. Each Web ACL has a maximum capacity of 1500 “WebACL Capacity Units” (WCUs), and each rule we add uses up some of those units. E.g The SQL rule has a capacity value of 200.&lt;/p&gt;

&lt;p&gt;Under the &lt;strong&gt;Default web ACL action for requests that don't match any rules&lt;/strong&gt; , set it to Allow, this is because we only want to block traffic matching any of our rules.&lt;/p&gt;

&lt;p&gt;Click on Next.&lt;/p&gt;

&lt;p&gt;You can also set the rule priority for the rules selected earlier. Web ACL rules are executed top to bottom, so the first rule is executed first and so on.&lt;/p&gt;

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

&lt;p&gt;Click Next and ensure that &lt;strong&gt;Request sampling options&lt;/strong&gt; is set to enabled.&lt;/p&gt;

&lt;p&gt;Create your Web ACL&lt;/p&gt;

&lt;p&gt;Once the WAF has been created, click on it and under Logging and metrics, click Enable&lt;/p&gt;

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

&lt;p&gt;Then click on s3 bucket as logging destination and select the bucket we created earlier.&lt;/p&gt;

&lt;p&gt;Then save.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  &lt;u&gt;Step 6 - Testing the WAF.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Open the ALB URL that we visited earlier.&lt;/p&gt;

&lt;p&gt;We should be able to view the wordpress page, and even the blog and admin page (/sample-page/ and /wp-admin).&lt;/p&gt;

&lt;p&gt;If we try a simple SQL Injection Attack like : &lt;code&gt;/wp-login.php?user=1+ORDER+BY+10&lt;/code&gt; , the WAF should stop us with a code 403 ( permission denied).&lt;/p&gt;

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

&lt;p&gt;Once verified that the WAF rules are working as expected.&lt;/p&gt;

&lt;p&gt;Go back to the WAF Console, click on your WAF and navigate to the Sampled requests.&lt;/p&gt;

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

&lt;p&gt;If you search for your IP Address, you should see the requests you made,  the actions applied on those requests (ALLOW/BLOCK) and the rule that cause any block action.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  &lt;u&gt;Step 7 - Adding Custom Rules to your WAF Web ACL.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;We don’t want our WordPress login page or XML-RPC page being accessed by anyone, so we’re going to use our regex pattern we created earlier to block any requests to &lt;code&gt;/wp-login.php&lt;/code&gt; or &lt;code&gt;/xmlrpc.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Go to your WAF console: &lt;a href="https://us-east-1.console.aws.amazon.com/wafv2/home?region=us-east-1" rel="noopener noreferrer"&gt;https://us-east-1.console.aws.amazon.com/wafv2/home?region=us-east-1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on your wordpress web acl.&lt;/p&gt;

&lt;p&gt;Navigate to rules. &lt;strong&gt;Then click on Add rules, and add my own rule and rule groups&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Leave the rule type as &lt;strong&gt;Rule Builder&lt;/strong&gt; and name it &lt;strong&gt;no-wp-files&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Leave the type as a regular based rule.&lt;/p&gt;

&lt;p&gt;Under the block &lt;strong&gt;If a request matches the statement&lt;/strong&gt;, set the inspection option to &lt;strong&gt;URI Path&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set &lt;strong&gt;Match Type&lt;/strong&gt; to “Matches pattern from regex pattern set”&lt;/p&gt;

&lt;p&gt;Set &lt;strong&gt;Regex pattern&lt;/strong&gt; set to the pattern set we created earlier (no-wp-files).&lt;/p&gt;

&lt;p&gt;Set &lt;strong&gt;Text transformation&lt;/strong&gt; to “Lowercase” ,this changes everything in our inspection option which is the URI path to lowercase. e.g &lt;code&gt;/wp-login.php&lt;/code&gt; and &lt;code&gt;/WP-LOGIN.PHP&lt;/code&gt; will be seen by the WAF as &lt;code&gt;/wp-login.php&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Under &lt;strong&gt;Action&lt;/strong&gt;, Select Block&lt;/p&gt;

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

&lt;p&gt;On the next page, we need to move our new rule to the top of the priority list. Remember that rules in Web ACL are executed in order of top to bottom.&lt;/p&gt;

&lt;p&gt;Select your new rule, and keep clicking &lt;strong&gt;Move up&lt;/strong&gt; until it’s at the top of the list.&lt;/p&gt;

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

&lt;p&gt;Then save&lt;/p&gt;

&lt;p&gt;Now if we try accessing either the &lt;code&gt;/wp-login.php&lt;/code&gt;,&lt;code&gt;/wp-admin&lt;/code&gt; or &lt;code&gt;/xmlrpc.php&lt;/code&gt;. We will get a &lt;strong&gt;403 forbidden message&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;If we check the sampled requests of the AWS WAF console, we would see our IP and the path requested, with the action shown as &lt;strong&gt;BLOCK&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;We can also add many other custom rules such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allowing our home ip access to the application, since it is a trusted ip&lt;/li&gt;
&lt;li&gt;Allowing requests coming from a particular country, while blocking all other requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;u&gt;Step 8 - Viewing our WAF Logs.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;We can view our WAF Logs by going to the bucket we created in the S3 Console: &lt;a href="https://us-east-1.console.aws.amazon.com/s3/home?region=us-east-1" rel="noopener noreferrer"&gt;S3 Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Go to buckets and click on our waf logs bucket.&lt;/p&gt;

&lt;p&gt;The directory structure will be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/AWSLogs/[ACCOUNT ID]/WAFLogs/[REGION]/[WEB ACL]/[YEAR]/[MONTH]/[DAY]/[HOUR]/[5 MINUTE BLOCK]/[LOGS]&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;You can download the logs (which is in the .log format) and view it using the json pretty print website: &lt;a href="https://jsonformatter.org/json-pretty-print" rel="noopener noreferrer"&gt;https://jsonformatter.org/json-pretty-print&lt;/a&gt;, as the json file might be difficult to read.&lt;/p&gt;

&lt;p&gt;An example of a log can be this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1713169621018&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"formatVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"webaclId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:wafv2:us-east-1:567635759120:regional/webacl/wordpress-acl/24ce438c-a4b9-467f-8b4c-ba5ab8d56db3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terminatingRuleId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no-wp-files"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terminatingRuleType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REGULAR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BLOCK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terminatingRuleMatchDetails"&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;"conditionType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REGEX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"URI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchedData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchedFieldName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"httpSourceName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ALB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"httpSourceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"567635759120-app/wordpress-lb/3630369d4fc6a356"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ruleGroupList"&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;"ruleGroupId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWS#AWSManagedRulesPHPRuleSet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"terminatingRule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nonTerminatingMatchingRules"&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;"excludedRules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"customerConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;"rateBasedRuleList"&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;"nonTerminatingMatchingRules"&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;"requestHeadersInserted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"responseCodeSent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"httpRequest"&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;"clientIp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"154.118.22.58"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NG"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"headers"&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;"Host"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wordpress-lb-1743095222.us-east-1.elb.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="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;"Connection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"keep-alive"&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;"Upgrade-Insecure-Requests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&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;"User-Agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"&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;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"&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;"Accept-Encoding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gzip, deflate"&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;"Accept-Language"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en-GB,en-US;q=0.9,en;q=0.8"&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;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/xmlrpc.php"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"httpVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HTTP/1.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"httpMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1-661ce4d5-403eac0b43ee412a6810f599"&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;Here in this log file,you see the ACTION set to block and the terminating rule ID is the no-wp-files custom rule we created earlier.&lt;/p&gt;

&lt;p&gt;You can also see all of our request headers are there, as well as the URI, query strings, etc. This can be removed if you prefer.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;u&gt;Step 9- Clean Up.&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Ensure all the resources created during this walkthrough are deleted. These include :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web ACL &lt;/li&gt;
&lt;li&gt;IP Sets&lt;/li&gt;
&lt;li&gt;Regex Pattern Sets&lt;/li&gt;
&lt;li&gt;S3 Bucket&lt;/li&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;li&gt;Target Groups&lt;/li&gt;
&lt;li&gt;Load Balancer&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I trust that this article has effectively demonstrated the capabilities of AWS WAF and provided you with a deeper understanding of its functionality and implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;References&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html" rel="noopener noreferrer"&gt;AWS WAF Documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/acantril/learn-cantrill-io-labs/blob/master/aws-waf/readme.md" rel="noopener noreferrer"&gt;Andrew Cantrill's WAF Demo Guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>devops</category>
      <category>security</category>
    </item>
  </channel>
</rss>
