# Deploying an AWS ALB with AWS WAF Protection using Terraform

Hello everyone,

Hope you all are doing well. In today's blog we will be learning about deploying an AWS ALB with AWS WAF Protection using Terraform.

It is very important to secure your resources when you deploy them to cloud. Security is a shared responsibility model. An **Application Load Balancer (ALB)** helps distribute incoming traffic, while **AWS WAF (Web Application Firewall)** protects against common web exploits.

In this guide, we’ll build a fully automated setup using **Terraform**:

1. **Create an Application Load Balancer (ALB)**
    
2. **Deploy an AWS WAF WebACL**
    
3. **Associate the WAF WebACL with the ALB**
    

Before starting, here's some resources you should check -

[**https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2\_web\_acl**](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl)

[**https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb**](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb)

Also, my Github repo for the same.

[**https://github.com/sankalpsp07/Deploying-an-AWS-ALB-with-AWS-WAF-Protection-using-Terraform-**](https://github.com/sankalpsp07/Deploying-an-AWS-ALB-with-AWS-WAF-Protection-using-Terraform-)

Let's dive in!

Let's create a [**provider.tf**](http://provider.tf/) file.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQF1bfPIBUkSnw/article-inline_image-shrink_1500_2232/B4DZgyT1.GH4AY-/0/1753190720076?e=1759968000&v=beta&t=zu53QQCoacFW5P9O8TOavahzgyIJejVbaBYoiBTSXyE align="left")

Now let's create a [**variables.tf**](http://variables.tf/) file.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQFJY6RaRsBglg/article-inline_image-shrink_400_744/B4DZgyUAvlHAAY-/0/1753190764117?e=1759968000&v=beta&t=EliY1_h_DFB5nLnoSqwOyZCW9BoznR9_71v1fiNmeNQ align="left")

For this blog, we will use default vpc, but in actual production scenario, we will not use use the default vpc.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQG17oW7H3gZxg/article-inline_image-shrink_400_744/B4DZgyUnLDHYAY-/0/1753190921536?e=1759968000&v=beta&t=iPZydpBBvzQ6yGuHxqLyQdRlCUUvwCKYvr3zKLzZXcU align="left")

We will be using terraform modules for ALB, WAF, and required security groups. Let's create folders and files for that.

Let's create a security group for ALB. In this we are specifying inbound and outbound rules.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQERMUzV6UZLxw/article-inline_image-shrink_1000_1488/B4DZgyaq6nG8AQ-/0/1753192510027?e=1759968000&v=beta&t=oBe3rRairBYZKi_uto0HLa_lvZelanylszCaMOt-x3U align="left")

main.tf

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQFUmoYn_zSURw/article-inline_image-shrink_1500_2232/B4DZgyb7SrH4Ac-/0/1753192839311?e=1759968000&v=beta&t=78NlyPsdzAu31eip96q5WbZvGgRDh2cKBjqFfE0YFWo align="left")

varibles.tf

Let's create ALB, target group, and listener with required attributes. As of now we will only create a HTTP Listener.

We can refer to [**https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb**](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb)

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQG6IjaYWMPPbA/article-inline_image-shrink_1500_2232/B4DZgyZhY0GQAU-/0/1753192208844?e=1759968000&v=beta&t=Ajol3FUpfy33IUoKrc1tAVq_a7J2XkmzyO3Mwcr8CVg align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQF6Cnyo0UO7LQ/article-inline_image-shrink_1000_1488/B4DZgyaTw4HYAQ-/0/1753192414971?e=1759968000&v=beta&t=vbTlvHzjpKU2TqiZYnSH4RDMhsSTKdWoRbTdQFtNO98 align="left")

variables.tf

Next step is to use command - terraform init. The terraform init command initializes a working directory containing Terraform configuration files

Next run - terraform validate. The terraform validate command is used to verify the correctness of Terraform configuration files within a given directory

Next use command terraform plan to check what all resources will be created.

Next apply terraform apply -

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQFLYreYwh8yZA/article-inline_image-shrink_1000_1488/B4DZgyc7QhG8AQ-/0/1753193101632?e=1759968000&v=beta&t=nALAfYxyFJFifbGXWG8bwxn9PMiEc4-yd-7dj2YsHes align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQG0ikfLf9xJMQ/article-inline_image-shrink_1000_1488/B4DZgydALyGgAU-/0/1753193122021?e=1759968000&v=beta&t=b63I10rdDR76o33cDJmwEr8MXklZ_knkpxWE79MkL7k align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQEX3FLEGi13aQ/article-inline_image-shrink_1000_1488/B4DZgydFzIHsAU-/0/1753193144642?e=1759968000&v=beta&t=6PJAzAb8ArN19cQifnW8wt-Eg1YaDMBiqkvnihC9ztQ align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQEcfk4WG3vTfA/article-inline_image-shrink_1000_1488/B4DZgydKNMHYAU-/0/1753193162426?e=1759968000&v=beta&t=1kho-WH0G4vG7JsnSGJwC9a1wyCNyTU-O6kdzQNRYEg align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQE6R6uAZxpR_Q/article-inline_image-shrink_1500_2232/B4DZgydP_lGkAU-/0/1753193186628?e=1759968000&v=beta&t=BTLGAJ_XK4z5RaudF8AuN1qCMUpyKpafOI3I-X8nqIk align="left")

Hence, it has created all 4 things - ALB, Listener, target groups and security group for ALB.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQGiYph4psC8WA/article-inline_image-shrink_1500_2232/B4DZgydoGZGkAg-/0/1753193285165?e=1759968000&v=beta&t=_107_kMPVz3QWroa2dxSl5xJ6fXjKpBtoGZ3tL-Gt2Q align="left")

In AWS Management Console

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQEbxh_BKLwPQw/article-inline_image-shrink_1500_2232/B4DZgydzQUGQAg-/0/1753193330886?e=1759968000&v=beta&t=WHZFYHY_jmtmY4wOpx93qHrSGJFLC5x9ioX0YWhZjnE align="left")

Listener and Target groups also created by terraform

Now, let's create WAF Web ACL and will associate it with Load balancer -

We will be using 2 rules -

1) [**AWSManagedRulesCommonRuleSet**](https://us-east-1.console.aws.amazon.com/wafv2/homev2/web-acl/rule/alb-waf-acl/41735bf2-4db8-4d0a-9a8c-ce6ebf32c8f1/AWSManagedRulesCommonRuleSet?region=ap-south-1)

2) [**RateLimitRule**](https://us-east-1.console.aws.amazon.com/wafv2/homev2/web-acl/rule/alb-waf-acl/41735bf2-4db8-4d0a-9a8c-ce6ebf32c8f1/RateLimitRule?region=ap-south-1)

You can add or remove the rules as and when required. We will also define their priority.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHm9tpjYvOpNg/article-inline_image-shrink_1000_1488/B4DZgyeLc6HsAU-/0/1753193429632?e=1759968000&v=beta&t=gcHxzERyAufcoonljU-a2Mv8blWaHl9VLXvlp6MYMlQ align="left")

Main.tf

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQEQTs_2kqcPag/article-inline_image-shrink_1500_2232/B4DZgyerK7HYAY-/0/1753193559721?e=1759968000&v=beta&t=sP3cG-RtUUOzAiNvqFj9qZnKIwe52rDYOaADy8agdo8 align="left")

Main.tf

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQEBEde9Dguzhw/article-inline_image-shrink_1000_1488/B4DZgyewKdGQFs-/0/1753193579905?e=1759968000&v=beta&t=TSHE817AA-3T7JYx2fUBfPHpHCX8C0jVh2A6AnTh0rA align="left")

Association

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQGknuUyDAkryw/article-inline_image-shrink_1500_2232/B4DZgye9quHAAo-/0/1753193635109?e=1759968000&v=beta&t=_7h0CHumHzCAyt3sxxZwKXI9_hnoMsmJw0pjV6AIyto align="left")

variables.tf

Now again run terraform init -

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQE6VD2hz71kBw/article-inline_image-shrink_1500_2232/B4DZgyfJ2rGkAU-/0/1753193685092?e=1759968000&v=beta&t=n6R3FKs26IzfDm5iQ17-X3-sLB3dRUCNUF_7gHXa8OY align="left")

Use terraform plan and terraform validate command to check what resources are getting create and validate configuration resp.

Let's now apply it.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHCxt63JUsu7g/article-inline_image-shrink_1000_1488/B4DZgyfrRFHAAQ-/0/1753193822227?e=1759968000&v=beta&t=L6ISw1j81_1QN9V5vGzYlNzn366_EEel6chCt8UBqNY align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQGwmA06XssRdQ/article-inline_image-shrink_1000_1488/B4DZgyfv8pGkAQ-/0/1753193841681?e=1759968000&v=beta&t=IeyOdNBRADVCJqoTMGLtaKRDOy8gccVqVBL81SufiJg align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHzB13PIU13wQ/article-inline_image-shrink_1000_1488/B4DZgyf1pzGgAQ-/0/1753193864747?e=1759968000&v=beta&t=Nlyjgq4Vqe9i7fl8GzIz5lHrRAhgjX2vaRycFvD7Y-k align="left")

Now, let's go to the console, and see.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHIRIYMgUmqPw/article-inline_image-shrink_1500_2232/B4DZgygANjGkAU-/0/1753193907946?e=1759968000&v=beta&t=wC5xGD6VMmpaIlVLZ21t4Zl891k9xynN0KMLUNkdIzk align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHSe8Vns---vQ/article-inline_image-shrink_1500_2232/B4DZgygHbTH4AU-/0/1753193937838?e=1759968000&v=beta&t=7sGGQQI-T9xXIalPitO5sOtmcdrgfv4s4aQZN87GDpw align="left")

Now, let's check the rules -

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQFN7cjmytN5PQ/article-inline_image-shrink_1500_2232/B4DZgygPXqGQAY-/0/1753193969840?e=1759968000&v=beta&t=WYkLFxbZ1XJvYegY4z5ljMe-uunFTZ1xyE6B0fOJZGM align="left")

Now, let's check associated resources -

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQEJPpkZc0oFjw/article-inline_image-shrink_1500_2232/B4DZgygXDxGkAc-/0/1753194001449?e=1759968000&v=beta&t=g8IOZSUiazsseybkvew_7alrnmPYJR5q8_sXHRuuT9g align="left")

Hence, we deployed the AWS Application load balancer with AWS WAF Web ACL to protect it.

Now, let's clean the resources.

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHRXgxlaOhgPw/article-inline_image-shrink_1000_1488/B4DZgyiu9oGQAg-/0/1753194623847?e=1759968000&v=beta&t=il6Qwy4GjjkIX23D5w3I78r99HjbelfvAFmhJvjl4bY align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHahn7xFeBlTg/article-inline_image-shrink_1000_1488/B4DZgyi0PQHsAQ-/0/1753194645349?e=1759968000&v=beta&t=OZN0S_CkhFJcUPqnJtb0ruwhlNWSTlk2N7WSLAEaFbo align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHKMitbzfSWXQ/article-inline_image-shrink_1000_1488/B4DZgyi4DsHAAY-/0/1753194661019?e=1759968000&v=beta&t=hPP4ILLSTLyLE-b6-wOkxnyX0rJPwlY3rTZa5MCzHN8 align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQHp_HNZTS0KFg/article-inline_image-shrink_1000_1488/B4DZgyi7ueGsAQ-/0/1753194675975?e=1759968000&v=beta&t=u35l8djyCnrg58EtDQUD60skxpenc7DPpiD3t3ySoMw align="left")

![Article content](https://media.licdn.com/dms/image/v2/D4D12AQFSDupXGW8imw/article-inline_image-shrink_1000_1488/B4DZgyjAfAHwAU-/0/1753194695342?e=1759968000&v=beta&t=qh7pcsNxTzaAN2Xkrj0gkW8iQo0XSg7tfu0uIwGywTQ align="left")

That's it for this blog.

Let's meet again in the next blog.

Thanks,

Regards,

[**Sankalp Sandeep Paranjpe**](https://www.linkedin.com/in/sankalp-s-paranjpe/)
