Search code examples
azureterraformterraform-provider-azureazure-application-gateway

Azure Application gateway IPs allowlist terraform


I have the following application gateway defined in terraform

resource "azurerm_application_gateway" "app_gateway" {
    name                = "agw-${local.application_context}"
    resource_group_name = data.azurerm_resource_group.resource_group.name
    location            = data.azurerm_resource_group.resource_group.location
    ...

    sku {
     name     = "WAF_v2"
     tier     = "WAF_v2"
     capacity = 2
   }

   gateway_ip_configuration {
        name      = "agw-${local.application_context}"
        subnet_id = azurerm_subnet.snet.id
   }

   frontend_port {
     ....
   }
 
 .....

 waf_configuration {
   enabled                  = true
   firewall_mode            = "Prevention"
   rule_set_type            = "OWASP"
   rule_set_version         = "3.2"
   file_upload_limit_mb     = 100
   max_request_body_size_kb = 128
   request_body_check       = false
 }
}

I am struggling to understand how to set an IPs allowlist in order to allow only specific IPs to connect to my Application Gateway.


Solution

  • To allow IPs in an application gateway, there are two ways: one is using an NSG, and the other is using a WAF policy

    Here is the updated Terraform code to allow IPs in the application gateway using a WAF Policy

    Note: To create WAF policy you need to create a application gateway with SKU WAF V2

    provider "azurerm" {
      features {}
    }
    
    resource "azurerm_resource_group" "rgname" {
      location = "eastus"
      name     = "sample-rg-appgateway"
    }
    
    resource "azurerm_public_ip" "samplepublicip" {
      allocation_method   = "Static"
      location            = "eastus"
      name                = "demopublicip"
      resource_group_name = azurerm_resource_group.rgname.name
      sku                 = "Standard"
      zones               = ["1"]
      depends_on = [
        azurerm_resource_group.rgname,
      ]
    }
    
    resource "azurerm_virtual_network" "samplevnet" {
      address_space       = ["10.1.0.0/16"]
      location            = azurerm_resource_group.rgname.location
      name                = "samplevnet"
      resource_group_name = azurerm_resource_group.rgname.name
      depends_on = [
        azurerm_public_ip.samplepublicip,
      ]
    }
    
    resource "azurerm_subnet" "appsubnet" {
      address_prefixes     = ["10.1.0.0/24"]
      name                 = "samplesubnet"
      resource_group_name  = azurerm_resource_group.rgname.name
      virtual_network_name = azurerm_virtual_network.samplevnet.name
      depends_on = [
        azurerm_virtual_network.samplevnet,
      ]
    }
    
    resource "azurerm_web_application_firewall_policy" "appgateway" {
      location            = azurerm_resource_group.rgname.location
      name                = "appgatewaypolicy"
      resource_group_name = azurerm_resource_group.rgname.name
      custom_rules {
        action    = "Allow"
        name      = "AllowIP"
        priority  = 100
        rule_type = "MatchRule"
        match_conditions {
          match_values = ["125.19.127.99", "172.168.10.5", "192.168.10.0"]
          operator     = "IPMatch"
          match_variables {
            variable_name = "RemoteAddr"
          }
        }
      }
      managed_rules {
        managed_rule_set {
          version = "3.2"
        }
      }
      policy_settings {
        mode = "Detection"
      }
      depends_on = [
        azurerm_subnet.appsubnet,
      ]
    }
    
    locals {
      backend_address_pool_name = "${azurerm_virtual_network.samplevnet.name}-beap"
      request_routing_rule_name = "${azurerm_virtual_network.samplevnet.name}-rqrt"
    }
    
    resource "azurerm_application_gateway" "appgateway" {
      enable_http2        = true
      firewall_policy_id  = azurerm_web_application_firewall_policy.appgateway.id
      location            = azurerm_resource_group.rgname.location
      name                = "demoappgateway"
      resource_group_name = azurerm_resource_group.rgname.name
      zones               = ["1"]
      autoscale_configuration {
        max_capacity = 10
        min_capacity = 0
      }
      backend_address_pool {
        name = local.backend_address_pool_name
      }
      backend_http_settings {
        cookie_based_affinity = "Disabled"
        name                  = "sampletarget" request_routing_rule
        port                  = 80
        protocol              = "Http"
        request_timeout       = 20
      }
      frontend_ip_configuration {
        name                 = "appGwPublicFrontendIpIPv4"
        public_ip_address_id = azurerm_public_ip.samplepublicip.id
      }
      frontend_port {
        name = "port_80"
        port = 80
      }
      gateway_ip_configuration {
        name      = "appGatewayIpConfig"
        subnet_id = azurerm_subnet.appsubnet.id
      }
      http_listener {
        frontend_ip_configuration_name = "appGwPublicFrontendIpIPv4"
        frontend_port_name             = "port_80"
        name                           = "samplelistener"
        protocol                       = "Http"
      }
      request_routing_rule {
        backend_address_pool_name  = local.backend_address_pool_name
        backend_http_settings_name = "sampletarget" 
        http_listener_name         = "samplelistener"
        name                       = local.request_routing_rule_name
        priority                   = 100
        rule_type                  = "Basic"
      }
      sku {
        name = "WAF_v2"
        tier = "WAF_v2"
      }
      depends_on = [
        azurerm_web_application_firewall_policy.appgateway,
      ]
    }
    

    Terraform apply

    enter image description here

    After executing the Terraform code, the application gateway has been created with the WAF policy as shown below.

    enter image description here

    Reference: Custom rules for Web Application Firewall v2 on Azure Application Gateway

    Application Gateway infrastructure configuration, if you are using NSG