Skip to content

claranet/terraform-azurerm-app-gateway

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure Application Gateway

Changelog Notice Apache V2 License OpenTofu Registry

This Terraform module creates an Application Gateway associated with a Public IP and with a Subnet, a Network Security Group and network security rules authorizing port 443 and ports for internal healthcheck of Application Gateway. The Diagnostics Logs are activated.

Naming

Resource naming is based on the Microsoft CAF naming convention best practices. Legacy naming is available by setting the parameter use_caf_naming to false. We rely on the official Terraform Azure CAF naming provider to generate resource names.

Global versioning rule for Claranet Azure modules

Module version Terraform version OpenTofu version AzureRM version
>= 8.x.x Unverified 1.8.x >= 4.0
>= 7.x.x 1.3.x >= 3.0
>= 6.x.x 1.x >= 3.0
>= 5.x.x 0.15.x >= 2.0
>= 4.x.x 0.13.x / 0.14.x >= 2.0
>= 3.x.x 0.12.x >= 2.0
>= 2.x.x 0.12.x < 2.0
< 2.x.x 0.11.x < 2.0

Contributing

If you want to contribute to this repository, feel free to use our pre-commit git hook configuration which will help you automatically update and format some files for you by enforcing our Terraform code module best-practices.

More details are available in the CONTRIBUTING.md file.

Usage

This module is optimized to work with the Claranet terraform-wrapper tool which set some terraform variables in the environment needed by this module. More details about variables set by the terraform-wrapper available in the documentation.

⚠️ Since modules version v8.0.0, we do not maintain/check anymore the compatibility with Hashicorp Terraform. Instead, we recommend to use OpenTofu.

module "azure_virtual_network" {
  source  = "claranet/vnet/azurerm"
  version = "x.x.x"

  environment    = var.environment
  location       = module.azure_region.location
  location_short = module.azure_region.location_short
  client_name    = var.client_name
  stack          = var.stack

  resource_group_name = module.rg.name

  cidrs = ["192.168.0.0/16"]
}

locals {
  base_name = "${var.stack}-${var.client_name}-${module.azure_region.location_short}-${var.environment}"
}

module "appgw" {
  source  = "claranet/app-gateway/azurerm"
  version = "x.x.x"

  stack               = var.stack
  environment         = var.environment
  location            = module.azure_region.location
  location_short      = module.azure_region.location_short
  client_name         = var.client_name
  resource_group_name = module.rg.name

  virtual_network_name = module.azure_virtual_network.name
  subnet_cidr          = "192.168.1.0/24"

  backend_http_settings = [
    {
      name                  = "${local.base_name}-backhttpsettings-http"
      cookie_based_affinity = "Disabled"
      path                  = "/"
      port                  = 80
      protocol              = "Http"
      request_timeout       = 300
    },
    # {
    #   name                  = "${local.base_name}-backhttpsettings-https"
    #   cookie_based_affinity = "Disabled"
    #   path                  = "/"
    #   port                  = 443
    #   protocol              = "Https"
    #   request_timeout       = 300
    # }
  ]

  backend_address_pools = [{
    name  = "${local.base_name}-backendpool"
    fqdns = ["example.com"]
  }]

  request_routing_rules = [
    {
      name                       = "${local.base_name}-routing-http"
      rule_type                  = "Basic"
      http_listener_name         = "${local.base_name}-listener-http"
      backend_address_pool_name  = "${local.base_name}-backendpool"
      backend_http_settings_name = "${local.base_name}-backhttpsettings-http"
    },
    # {
    #   name                       = "${local.base_name}-routing-https"
    #   rule_type                  = "Basic"
    #   http_listener_name         = "${local.base_name}-listener-https"
    #   backend_address_pool_name  = "${local.base_name}-backendpool"
    #   backend_http_settings_name = "${local.base_name}-backhttpsettings-https"
    # }
  ]

  frontend_ip_configuration_custom_name = "${local.base_name}-frontipconfig"

  http_listeners = [
    {
      name                           = "${local.base_name}-listener-http"
      frontend_ip_configuration_name = "${local.base_name}-frontipconfig"
      frontend_port_name             = "frontend-http-port"
      protocol                       = "Http"
      host_name                      = "example.com"
    },
    # {
    #   name                           = "${local.base_name}-listener-https"
    #   frontend_ip_configuration_name = "${local.base_name}-frontipconfig"
    #   frontend_port_name             = "frontend-https-port"
    #   protocol                       = "Https"
    #   ssl_certificate_name           = "${local.base_name}-example-com-sslcert"
    #   require_sni                    = true
    #   host_name                      = "example.com"
    # }
  ]

  frontend_ports = [{
    name = "frontend-http-port"
    port = 80
  }]

  #  ssl_certificates = [{
  #    name     = "${local.base_name}-example-com-sslcert"
  #    data     = var.certificate_example_com_filebase64
  #    password = var.certificate_example_com_password
  #  }]

  ssl_policy = {
    policy_type = "Predefined"
    policy_name = "AppGwSslPolicy20170401S"
  }

  rewrite_rule_sets = [{
    name = "${local.base_name}-example-rewrite-rule-set"
    rewrite_rules = [
      {
        name          = "${local.base_name}-example-rewrite-rule-response-header"
        rule_sequence = 100
        conditions = [
          {
            ignore_case = true
            negate      = false
            pattern     = "text/html(.*)"
            variable    = "http_resp_Content-Type"
          }
        ]
        response_header_configurations = [{
          header_name  = "X-Frame-Options"
          header_value = "DENY"
        }]
      },
      {
        name          = "${local.base_name}-example-rewrite-rule-url"
        rule_sequence = 100
        conditions = [
          {
            ignore_case = false
            negate      = false
            pattern     = ".*-R[0-9]{10,10}\\.html"
            variable    = "var_uri_path"
          },
          {
            ignore_case = true
            negate      = false
            pattern     = ".*\\.fr"
            variable    = "var_host"
          }
        ]
        url_reroute = {
          path         = "/fr{var_uri_path}"
          query_string = null
          reroute      = false
        }
      }
    ]
  }]

  url_path_maps = [
    {
      name                               = "${local.base_name}-example-url-path-map"
      default_backend_http_settings_name = "${local.base_name}-backhttpsettings-http"
      default_backend_address_pool_name  = "${local.base_name}-backendpool"
      default_rewrite_rule_set_name      = "${local.base_name}-example-rewrite-rule-set"
      # default_redirect_configuration_name = "${local.base_name}-redirect"
      path_rules = [
        {
          name                       = "${local.base_name}-example-url-path-rule"
          backend_address_pool_name  = "${local.base_name}-backendpool"
          backend_http_settings_name = "${local.base_name}-backhttpsettings-http"
          rewrite_rule_set_name      = "${local.base_name}-example-rewrite-rule-set"
          paths                      = ["/demo/"]
        }
      ]
    }
  ]

  # Disabled WAF rule and WAF exclusion configuration example
  # waf_configuration = {
  #   disabled_rule_group = [
  #     {
  #       rule_group_name = "REQUEST-920-PROTOCOL-ENFORCEMENT"
  #       rules           = ["920420", "920320", "920330"]
  #     }
  #   ]
  #   exclusion = [
  #     {
  #       match_variable          = "RequestArgNames"
  #       selector                = "picture"
  #       selector_match_operator = "Equals"
  #     }
  #   ]
  # }

  autoscale_configuration = {
    min_capacity = 2
    max_capacity = 15
  }

  logs_destinations_ids = [
    # module.logs.id,
    # module.logs.storage_account_id,
  ]
}

Providers

Name Version
azurecaf ~> 1.2.28
azurerm ~> 4.0
terraform n/a

Modules

Name Source Version
diagnostics claranet/diagnostic-settings/azurerm ~> 8.0.0
nsg claranet/nsg/azurerm ~> 8.0.0
subnet claranet/subnet/azurerm ~> 8.0.0

Resources

Name Type
azurerm_application_gateway.main resource
azurerm_public_ip.main resource
terraform_data.create_subnet_condition resource
azurecaf_name.appgw data source
azurecaf_name.frontipconfig data source
azurecaf_name.frontipconfig_priv data source
azurecaf_name.gwipconfig data source
azurecaf_name.nsg_appgw data source
azurecaf_name.nsr_healthcheck data source
azurecaf_name.nsr_https data source
azurecaf_name.pip_appgw data source
azurecaf_name.subnet_appgw data source

Inputs

Name Description Type Default Required
app_gateway_tags Application Gateway tags. map(string) {} no
authentication_certificates List of objects with authentication certificates configurations.
The path to a base-64 encoded certificate is expected in the 'data' attribute:
data = filebase64("./file_path")
list(object({
name = string
data = string
}))
[] no
autoscale_configuration Map containing autoscaling parameters. Must contain at least min_capacity.
object({
min_capacity = number
max_capacity = optional(number, 5)
})
null no
backend_address_pools List of objects with backend pool configurations.
list(object({
name = string
fqdns = optional(list(string))
ip_addresses = optional(list(string))
}))
n/a yes
backend_http_settings List of objects including backend http settings configurations.
list(object({
name = string
port = optional(number, 443)
protocol = optional(string, "Https")

path = optional(string)
probe_name = optional(string)

cookie_based_affinity = optional(string, "Disabled")
affinity_cookie_name = optional(string, "ApplicationGatewayAffinity")
request_timeout = optional(number, 20)
host_name = optional(string)
pick_host_name_from_backend_address = optional(bool, true)
trusted_root_certificate_names = optional(list(string), [])
authentication_certificate = optional(string)

connection_draining_timeout_sec = optional(number)
}))
n/a yes
client_name Client name/account used in naming. string n/a yes
create_nsg Boolean to create the network security group. bool false no
create_nsg_healthprobe_rule Boolean to create the network security group rule for the health probes. bool true no
create_nsg_https_rule Boolean to create the network security group rule opening https to everyone. bool true no
create_subnet Boolean to create subnet with this module. bool true no
custom_error_configurations List of objects with global level custom error configurations.
list(object({
status_code = string
custom_error_page_url = string
}))
[] no
custom_name Custom Application Gateway name, generated if not set. string "" no
default_tags_enabled Option to enable or disable default tags. bool true no
diagnostic_settings_custom_name Custom name of the diagnostics settings, name will be 'default' if not set. string "default" no
environment Project environment. string n/a yes
extra_tags Extra tags to add. map(string) {} no
firewall_policy_id ID of a Web Application Firewall Policy. string null no
flow_log_enabled Provision network watcher flow logs. bool false no
flow_log_location The location where the Network Watcher Flow Log resides. Changing this forces a new resource to be created. Defaults to the location of the Network Watcher. string null no
flow_log_logging_enabled Enable Network Flow Logging. bool true no
flow_log_retention_policy_days The number of days to retain flow log records. number 31 no
flow_log_retention_policy_enabled Boolean flag to enable/disable retention. bool true no
flow_log_storage_account_id Network watcher flow log storage account ID. string null no
flow_log_traffic_analytics_enabled Boolean flag to enable/disable traffic analytics. bool true no
flow_log_traffic_analytics_interval_in_minutes How frequently service should do flow analytics in minutes. number 10 no
force_firewall_policy_association Enable if the Firewall Policy is associated with the Application Gateway. bool false no
frontend_ip_configuration_custom_name The custom name of the Frontend IP Configuration used. Generated by default. string "" no
frontend_ports List of objects with frontend ports. Each one contains the name and the port for the frontend port.
list(object({
name = string
port = number
}))
[] no
frontend_private_ip_configuration Configuration of frontend private IP.
object({
private_ip_address_allocation = optional(string, "Static")
private_ip_address = optional(string)
})
null no
frontend_private_ip_configuration_custom_name The Name of the private Frontend IP Configuration used for this HTTP Listener. string "" no
gateway_ip_configuration_custom_name The Name of the Application Gateway IP Configuration. string "" no
http2_enabled Whether to enable http2 or not. bool true no
http_listeners List of objects with HTTP listeners configurations and custom error configurations.
list(object({
name = string

frontend_ip_configuration_name = optional(string)
frontend_port_name = optional(string)
host_name = optional(string)
host_names = optional(list(string))
protocol = optional(string, "Https")
require_sni = optional(bool, false)
ssl_certificate_name = optional(string)
ssl_profile_name = optional(string)
firewall_policy_id = optional(string)

custom_error_configurations = optional(list(object({
status_code = string
custom_error_page_url = string
})), [])
}))
n/a yes
ip_tags Public IP tags. map(string) {} no
location Azure location. string n/a yes
location_short Short string for Azure location. string n/a yes
log_analytics_workspace_guid The resource GUID of the attached workspace. string null no
log_analytics_workspace_id The resource ID of the attached workspace. string null no
log_analytics_workspace_location The location of the attached workspace. string null no
logs_categories Log categories to send to destinations. list(string) null no
logs_destinations_ids List of destination resources IDs for logs diagnostic destination.
Can be Storage Account, Log Analytics Workspace and Event Hub. No more than one of each can be set.
If you want to use Azure EventHub as a destination, you must provide a formatted string containing both the EventHub Namespace authorization send ID and the EventHub name (name of the queue to use in the Namespace) separated by the | character.
list(string) n/a yes
logs_metrics_categories Metrics categories to send to destinations. list(string) null no
name_prefix Optional prefix for the generated name. string "" no
name_suffix Optional suffix for the generated name. string "" no
network_watcher_name The name of the Network Watcher. Changing this forces a new resource to be created. string null no
network_watcher_resource_group_name The name of the resource group in which the Network Watcher was deployed. Changing this forces a new resource to be created. string null no
nsg_custom_name Custom name for the network security group. string null no
nsg_tags Network Security Group tags. map(string) {} no
nsr_healthcheck_custom_name Custom name for the network security rule for internal health check of Application Gateway. string null no
nsr_https_custom_name Custom name for the network security rule for HTTPS protocol. string null no
nsr_https_source_address_prefix Source address prefix to allow to access on port 443 defined in dedicated network security rule. string "*" no
probes List of objects with probes configurations.
list(object({
name = string
host = optional(string)
port = optional(number, null)
interval = optional(number, 30)
path = optional(string, "/")
protocol = optional(string, "Https")
timeout = optional(number, 30)

unhealthy_threshold = optional(number, 3)
pick_host_name_from_backend_http_settings = optional(bool, false)
minimum_servers = optional(number, 0)

match = optional(object({
body = optional(string, "")
status_code = optional(list(string), ["200-399"])
}), {})
}))
[] no
public_ip Public IP parameters.
object({
ddos_protection_mode = optional(string, "VirtualNetworkInherited")
ddos_protection_plan_id = optional(string)
extra_tags = optional(map(string), {})
})
{} no
public_ip_custom_name Public IP custom name. Generated by default. string "" no
public_ip_label_custom_name Domain name label for public IP. string "" no
redirect_configurations List of objects with redirect configurations.
list(object({
name = string

redirect_type = optional(string, "Permanent")
target_listener_name = optional(string)
target_url = optional(string)

include_path = optional(bool, true)
include_query_string = optional(bool, true)
}))
[] no
request_routing_rules List of objects with request routing rules configurations. With AzureRM v3+ provider, priority attribute becomes mandatory.
list(object({
name = string
rule_type = optional(string, "Basic")
http_listener_name = optional(string)
backend_address_pool_name = optional(string)
backend_http_settings_name = optional(string)
url_path_map_name = optional(string)
redirect_configuration_name = optional(string)
rewrite_rule_set_name = optional(string)
priority = optional(number)
}))
n/a yes
resource_group_name Resource group name. string n/a yes
rewrite_rule_sets List of rewrite rule set objects with rewrite rules.
list(object({
name = string
rewrite_rules = list(object({
name = string
rule_sequence = string

conditions = optional(list(object({
variable = string
pattern = string
ignore_case = optional(bool, false)
negate = optional(bool, false)
})), [])

response_header_configurations = optional(list(object({
header_name = string
header_value = string
})), [])

request_header_configurations = optional(list(object({
header_name = string
header_value = string
})), [])

url_reroute = optional(object({
path = optional(string)
query_string = optional(string)
components = optional(string)
reroute = optional(bool)
}))
}))
}))
[] no
route_table_name The Route Table name to associate with the subnet string null no
route_table_rg The Route Table RG to associate with the subnet. Default is the same RG than the subnet. string null no
sku The Name of the SKU to use for this Application Gateway. Possible values are Standard_v2 and WAF_v2. string "WAF_v2" no
sku_capacity The capacity of the SKU to use for this Application Gateway - which must be between 1 and 10, optional if autoscale_configuration is set. number 2 no
ssl_certificates List of objects with SSL certificates configurations.
The path to a base-64 encoded certificate is expected in the 'data' attribute:
data = filebase64("./file_path")
list(object({
name = string
data = optional(string)
password = optional(string)
key_vault_secret_id = optional(string)
}))
[] no
ssl_policy List of objects with SSL configurations. The list of available policies can be found here.
object({
disabled_protocols = optional(list(string), [])
policy_type = optional(string, "Predefined")
policy_name = optional(string, "AppGwSslPolicy20170401S")
cipher_suites = optional(list(string), [])
min_protocol_version = optional(string, "TLSv1_2")
})
{} no
ssl_profiles List of objects with SSL profiles. Default profile is used when this variable is set to null.
list(object({
name = string
trusted_client_certificate_names = optional(list(string), [])
verify_client_cert_issuer_dn = optional(bool, false)
ssl_policy = optional(object({
disabled_protocols = optional(list(string), [])
policy_type = optional(string, "Predefined")
policy_name = optional(string, "AppGwSslPolicy20170401S")
cipher_suites = optional(list(string), [])
min_protocol_version = optional(string, "TLSv1_2")
}))
}))
[] no
stack Project stack name. string n/a yes
subnet_cidr Subnet CIDR to create. string "" no
subnet_custom_name Custom name for the subnet. string "" no
subnet_id Custom subnet ID for attaching the Application Gateway. Used only when the variable create_subnet = false. string "" no
subnet_resource_group_name Resource group name of the subnet. string "" no
trusted_client_certificates List of objects with trusted client certificates configurations.
The path to a base-64 encoded certificate is expected in the 'data' attribute:
data = filebase64("./file_path")
list(object({
name = string
data = string
}))
[] no
trusted_root_certificates List of trusted root certificates. file_path is checked first, using data (base64 cert content) if null. This parameter is required if you are not using a trusted certificate authority (eg. selfsigned certificate).
list(object({
name = string
data = optional(string)
file_path = optional(string)
key_vault_secret_id = optional(string)
}))
[] no
url_path_maps List of objects with URL path map configurations.
list(object({
name = string

default_backend_address_pool_name = optional(string)
default_redirect_configuration_name = optional(string)
default_backend_http_settings_name = optional(string)
default_rewrite_rule_set_name = optional(string)

path_rules = list(object({
name = string

backend_address_pool_name = optional(string)
backend_http_settings_name = optional(string)
rewrite_rule_set_name = optional(string)
redirect_configuration_name = optional(string)
firewall_policy_id = optional(string)

paths = optional(list(string), [])
}))
}))
[] no
user_assigned_identity_id User assigned identity id assigned to this resource. string null no
virtual_network_name Virtual network name to attach the subnet. string null no
waf_configuration WAF configuration object (only available with WAF_v2 SKU) with following attributes:
- enabled:                  Boolean to enable WAF.
- file_upload_limit_mb: The File Upload Limit in MB. Accepted values are in the range 1MB to 500MB.
- firewall_mode: The Web Application Firewall Mode. Possible values are Detection and Prevention.
- max_request_body_size_kb: The Maximum Request Body Size in KB. Accepted values are in the range 1KB to 128KB.
- request_body_check: Is Request Body Inspection enabled ?
- rule_set_type: The Type of the Rule Set used for this Web Application Firewall.
- rule_set_version: The Version of the Rule Set used for this Web Application Firewall. Possible values are 2.2.9, 3.0, and 3.1.
- disabled_rule_group: The rule group where specific rules should be disabled. Accepted values can be found here.
- exclusion: WAF exclusion rules to exclude header, cookie or GET argument. More informations here.
object({
enabled = optional(bool, true)
file_upload_limit_mb = optional(number, 100)
firewall_mode = optional(string, "Prevention")
max_request_body_size_kb = optional(number, 128)
request_body_check = optional(bool, true)
rule_set_type = optional(string, "OWASP")
rule_set_version = optional(string, "3.1")
disabled_rule_group = optional(list(object({
rule_group_name = string
rules = optional(list(string))
})), [])
exclusion = optional(list(object({
match_variable = string
selector = optional(string)
selector_match_operator = optional(string)
})), [])
})
{} no
waf_rules_for_dev_portal_enabled Whether to enabled some WAF rules if the APIM developer portal is hosted behind this Application Gateway. See locals.tf for the documentation link. bool true no
zones A collection of availability zones to spread the Application Gateway over. This option is only supported for v2 SKUs. list(number)
[
1,
2,
3
]
no

Outputs

Name Description
backend_address_pool_ids List of backend address pool IDs.
backend_http_settings_ids List of backend HTTP settings IDs.
backend_http_settings_probe_ids List of probe IDs from backend HTTP settings.
custom_error_configuration_ids List of custom error configuration IDs.
frontend_ip_configuration_ids List of frontend IP configuration IDs.
frontend_port_ids List of frontend port IDs.
gateway_ip_configuration_ids List of IP configuration IDs.
http_listener_frontend_ip_configuration_ids List of frontend IP configuration IDs from HTTP listeners.
http_listener_frontend_port_ids List of frontend port IDs from HTTP listeners.
http_listener_ids List of HTTP listener IDs.
id Application Gateway ID.
module_nsg Network Security Group module object.
module_subnet Subnet module object.
name Application Gateway name.
nsg_id The ID of the network security group from the subnet where the Application Gateway is attached.
nsg_name The name of the network security group from the subnet where the Application Gateway is attached.
public_ip_address The public IP address of Application Gateway.
public_ip_domain_name Domain Name part from FQDN of the A DNS record associated with the public IP.
public_ip_fqdn Fully qualified domain name of the A DNS record associated with the public IP.
redirect_configuration_ids List of redirect configuration IDs.
request_routing_rule_backend_address_pool_ids List of backend address pool IDs attached to request routing rules.
request_routing_rule_backend_http_settings_ids List of HTTP settings IDs attached to request routing rules.
request_routing_rule_http_listener_ids List of HTTP listener ICs attached to request routing rules.
request_routing_rule_ids List of request routing rules IDs.
request_routing_rule_redirect_configuration_ids List of redirect configuration IDs attached to request routing rules.
request_routing_rule_rewrite_rule_set_ids List of rewrite rule set IDs attached to request routing rules.
request_routing_rule_url_path_map_ids List of URL path map IDs attached to request routing rules.
resource Application Gateway resource object.
resource_public_ip Public IP resource object.
ssl_certificate_ids List of SSL certificate IDs.
subnet_id The ID of the subnet where the Application Gateway is attached.
subnet_name The name of the subnet where the Application Gateway is attached.
url_path_map_default_backend_address_pool_ids List of default backend address pool IDs attached to URL path maps.
url_path_map_default_backend_http_settings_ids List of default backend HTTP settings IDs attached to URL path maps.
url_path_map_default_redirect_configuration_ids List of default redirect configuration IDs attached to URL path maps.
url_path_map_ids List of URL path map IDs.

Related documentation

Microsoft Azure documentation: docs.microsoft.com/en-us/azure/application-gateway/overview