Skip to content

Application Gateway

See below for an example of an application gateway configuration. Tags are used to identify the resources that will be added to the application gateway's backend address pool.

Application Gateway Variables Example

agws = {
    myagw = {
        name = "agw-epic-eus2-np"
        resource_group = "network"
        gateway_ip_configuration = [{
            name = "agw-gic-epic-eus2-np"
            subnet = "sharedinfra.agw"
        }]
        frontend_ip_configuration = [{
            name = "agw-gic-epic-eus2-np"
            public_ip_address = "agw"
        }]
        probe = [{}]
        ssl_certificate = [{}]
        trusted_root_certificate = [{}]
        backend_address_pool = [
            {
                name = "backend_address_hsw"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "hsw"
                    }
                }
            },
            {
                name = "backend_address_slic"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "slic"
                    }
                }
            },
            {
                name = "backend_address_wbs"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "wbs"
                    }
                }
            },
            {
                name = "backend_address_eds"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "eds"
                    }
                }
            },
            {
                name = "backend_address_erpx"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "erpx"
                    }
                }
            },
            {
                name = "backend_address_icfg"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "icfg"
                    }
                }
            },
            {
                name = "backend_address_rpx"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "rpx"
                    }
                }
            },
            {
                name = "backend_address_wbs"
                target = {
                    vm_tag = {
                        key = "backend_address_pool"
                        value = "wbs"
                    }
                }
            }
        ]
        backend_http_settings = [
            {
                name = "backend_https_hsw"
                host_name = "agw.ibx.com"
                affinity_cookie_name = "hsw-affinitycookie"
                connection_draining = {}
            },
            {
                name = "backend_https_slic"
                host_name = "agw.ibx.com"
                affinity_cookie_name = "slic-affinitycookie"
                connection_draining = {}
            },
            {
                name = "backend_https_wbs"
                host_name = "agw.ibx.com"
            },
            {
                name = "backend_https_eds"
                host_name = "agw.ibx.com"
            },
            {
                name = "backend_https_erpx"
                host_name = "agw.ibx.com"
            },
            {
                name = "backend_https_icfg"
                host_name = "agw.ibx.com"
            },
            {
                name = "backend_https_rpx"
                host_name = "agw.ibx.com"
            }
        ]
        http_listener = [
            {
                name = "http_listener_hsw"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["hsw.sapphirehealth.org"]
            },
            {
                name = "https_listener_hsw"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["hsw.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            },
            {
                name = "http_listener_slic"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["slic.sapphirehealth.org"]
            },
            {
                name = "https_listener_slic"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["slic.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            },
            {
                name = "http_listener_wbs"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["wbs.sapphirehealth.org"]
            },
            {
                name = "https_listener_wbs"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["wbs.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            },
            {
                name = "http_listener_eds"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["eds.sapphirehealth.org"]
            },
            {
                name = "https_listener_eds"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["eds.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            },
            {
                name = "http_listener_erpx"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["erpx.sapphirehealth.org"]
            },
            {
                name = "https_listener_erpx"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["erpx.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            },
            {
                name = "http_listener_icfg"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["icfg.sapphirehealth.org"]
            },
            {
                name = "https_listener_icfg"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["icfg.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            },
            {
                name = "http_listener_rpx"
                frontend_port_name = "port_80"
                protocol = "Http"
                host_names = ["rpx.sapphirehealth.org"]
            },
            {
                name = "https_listener_rpx"
                frontend_port_name = "port_443"
                protocol = "Https"
                host_names = ["rpx.sapphirehealth.org"]
                ssl_certificate_name = "default_listener"
            }
        ]
        redirect_configuration = [
            {
                name = "redirect_80_to_443_hsw"
                target_listener_name = "https_listener_hsw"
            },
            {
                name = "redirect_80_to_443_slic"
                target_listener_name = "https_listener_slic"
            },
            {
                name = "redirect_80_to_443_wbs"
                target_listener_name = "https_listener_wbs"
            },
            {
                name = "redirect_80_to_443_eds"
                target_listener_name = "https_listener_eds"
            },
            {
                name = "redirect_80_to_443_erpx"
                target_listener_name = "https_listener_erpx"
            },
            {
                name = "redirect_80_to_443_icfg"
                target_listener_name = "https_listener_icfg"
            },
            {
                name = "redirect_80_to_443_rpx"
                target_listener_name = "https_listener_rpx"
            }
        ]
        request_routing_rule = [
            {
                name = "hsw_http"
                priority = 10
                rule_type = "Basic"
                http_listener_name = "http_listener_hsw"
                redirect_configuration_name = "redirect_80_to_443_hsw"
            },
            {
                name = "hsw_https"
                priority = 20
                rule_type = "Basic"
                http_listener_name = "https_listener_hsw"
                backend_address_pool_name = "backend_address_hsw"
                backend_http_settings_name = "backend_https_hsw"
            },
            {
                name = "slic_http"
                priority = 30
                rule_type = "Basic"
                http_listener_name = "http_listener_slic"
                redirect_configuration_name = "redirect_80_to_443_slic"
            },
            {
                name = "slic_https"
                priority = 40
                rule_type = "Basic"
                http_listener_name = "https_listener_slic"
                backend_address_pool_name = "backend_address_slic"
                backend_http_settings_name = "backend_https_slic"
            },
            {
                name = "wbs_http"
                priority = 50
                rule_type = "Basic"
                http_listener_name = "http_listener_wbs"
                redirect_configuration_name = "redirect_80_to_443_wbs"
            },
            {
                name = "wbs_https"
                priority = 60
                rule_type = "Basic"
                http_listener_name = "https_listener_wbs"
                backend_address_pool_name = "backend_address_wbs"
                backend_http_settings_name = "backend_https_wbs"
            },
            {
                name = "eds_http"
                priority = 70
                rule_type = "Basic"
                http_listener_name = "http_listener_eds"
                redirect_configuration_name = "redirect_80_to_443_eds"
            },
            {
                name = "eds_https"
                priority = 80
                rule_type = "Basic"
                http_listener_name = "https_listener_eds"
                backend_address_pool_name = "backend_address_eds"
                backend_http_settings_name = "backend_https_eds"
            },
            {
                name = "erpx_http"
                priority = 90
                rule_type = "Basic"
                http_listener_name = "http_listener_erpx"
                redirect_configuration_name = "redirect_80_to_443_erpx"
            },
            {
                name = "erpx_https"
                priority = 100
                rule_type = "Basic"
                http_listener_name = "https_listener_erpx"
                backend_address_pool_name = "backend_address_erpx"
                backend_http_settings_name = "backend_https_erpx"
            },
            {
                name = "icfg_http"
                priority = 110
                rule_type = "Basic"
                http_listener_name = "http_listener_icfg"
                redirect_configuration_name = "redirect_80_to_443_icfg"
            },
            {
                name = "icfg_https"
                priority = 120
                rule_type = "Basic"
                http_listener_name = "https_listener_icfg"
                backend_address_pool_name = "backend_address_icfg"
                backend_http_settings_name = "backend_https_icfg"
            },
            {
                name = "rpx_http"
                priority = 130
                rule_type = "Basic"
                http_listener_name = "http_listener_rpx"
                redirect_configuration_name = "redirect_80_to_443_rpx"
            },
            {
                name = "rpx_https"
                priority = 140
                rule_type = "Basic"
                http_listener_name = "https_listener_rpx"
                backend_address_pool_name = "backend_address_rpx"
                backend_http_settings_name = "backend_https_rpx"
            }
        ]
    }
}

VM Tags Example

windows_vms = {
    hsw_z1 = {
        names = [
            "HSW1TEST",
            "HSW2TEST"
        ]
        zones = ["1"]
        size = "Standard_D2s_v4"
        virtual_machine_scale_set = "testvmss"
        resource_group = "hsw"
        nics = {
            primary = {
                ip_configuration = [{
                    subnet = "main.hsw"
                }]
            }
        }
        boot_diagnostics = {
            storage_account = "diag2"
        }
        tags = {
            application = "hsw"
            backend_address_pool = "hsw"
        }
    }
    hsw_z2 = {
        ##Hyperspace Web Servers##
        names = [
            "HSW3TEST",
            "HSW4TEST"
        ]
        zones = ["2"]
        size = "Standard_D2s_v4"
        virtual_machine_scale_set = "testvmss"
        resource_group = "hsw"
        nics = {
            primary = {
                ip_configuration = [{
                    subnet = "main.hsw"
                }]
            }
        }
        boot_diagnostics = {
            storage_account = "diag2"
        }
        tags = {
            application = "hsw"
            backend_address_pool = "hsw"
        }
    }

Private DNS A Record for a Frontend

A private DNS A record can resolve to an application gateway frontend's private IP by referencing the gateway key (from agws) and the frontend's name. The IP is read at apply time, so Dynamic allocation works. See Private DNS A Record for the full variable reference.

private_dns_a_record = {
    portal = {
        resource_group = "network"
        zone = "sapphirehealth"
        application_gateway = {
            key = "dmz"
            frontend_ip_configuration = "appGwPrivateFrontendIp"
        }
    }
}

SSL Policy

Set the TLS policy enforced on the gateway's HTTPS/TLS listeners with an optional ssl_policy block. The block is a 0-or-1 element list, so omit it (or pass []) to leave the gateway on the Azure default policy. There are two mutually exclusive modes:

  • Predefined - reference a named Azure policy with policy_name (for example AppGwSslPolicy20220101, which enforces a minimum of TLS 1.2). Keep policy_type = "Predefined" (the default).
  • Custom - set policy_type = "Custom" (or "CustomV2") and provide min_protocol_version plus the explicit list of cipher_suites.

disabled_protocols is an alternative mode for disabling specific protocol versions; do not combine it with policy_name/policy_type.

agws = {
    dmz = {
        resource_group = "dmz"
        # ... gateway_ip_configuration, frontend_ip_configuration, listeners, etc. ...

        # Predefined policy - enforce a minimum of TLS 1.2.
        ssl_policy = [{
            policy_name = "AppGwSslPolicy20220101"
            policy_type = "Predefined"
        }]
    }
}

A custom policy instead looks like:

1
2
3
4
5
        ssl_policy = [{
            policy_type          = "Custom"
            min_protocol_version = "TLSv1_2"
            cipher_suites        = ["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"]
        }]

SSL Policy Variable Reference

Field Type Description Default
policy_name string Name of a Predefined Azure policy (e.g. AppGwSslPolicy20220101 = min TLS 1.2). Predefined mode only. null
policy_type string Predefined, Custom, or CustomV2. "Predefined"
disabled_protocols list(string) Protocol versions to disable. Alternative to policy_name/policy_type; do not combine. null
cipher_suites list(string) Explicit cipher suite list. Custom mode only. null
min_protocol_version string Minimum TLS protocol version (e.g. TLSv1_2). Custom mode only. null

Layer 4 (TCP/TLS) Proxy

In addition to the Layer 7 HTTP/HTTPS routing shown above, the gateway supports Layer 4 (TCP/TLS) proxying. The L4 blocks are direct analogues of their L7 counterparts:

  • listener - the L4 analogue of http_listener.
  • backend - the L4 analogue of backend_http_settings.
  • routing_rule - the L4 analogue of request_routing_rule.

Each defaults to [], so existing L7-only gateways are unaffected. A listener and backend use protocol = "Tcp" for a raw TCP passthrough (no TLS termination at the gateway) or protocol = "Tls" to terminate TLS at the gateway. The shared probe block also supports protocol = "Tcp" and protocol = "Tls"; for those L4 protocols the path and match fields do not apply and are omitted by the module, so leave match = null.

Note: L4 support requires azurerm >= 4.67.0, which is the version this repository is pinned at (see src/providers.tf). The Azure Application Gateway L4 (TCP/TLS) feature is in public preview.

The example below adds a TCP passthrough on port 7327 alongside the existing L7 443 listeners (frontend port, L4 listener, backend, routing rule, and a Tcp probe):

agws = {
    dmz = {
        resource_group = "dmz"
        frontend_ip_configuration = [
            { name = "appGwPublicFrontendIp", public_ip_address = "appgw" }
        ]
        frontend_port = [
            { name = "port_443", port = 443 },
            { name = "port_7327", port = 7327 }
        ]
        backend_address_pool = [
            { name = "nginx-pool", target = { vm_tag = { key = "backend_address_pool", value = "nginx" } } }
        ]

        # min TLS 1.2 on the HTTPS/TLS listeners.
        ssl_policy = [{ policy_name = "AppGwSslPolicy20220101", policy_type = "Predefined" }]

        # ---- 7327 L4 TCP passthrough (no TLS termination at the gateway) ----
        listener = [
            {
                name                           = "nginx-tcp7327"
                frontend_ip_configuration_name = "appGwPublicFrontendIp"
                frontend_port_name             = "port_7327"
                protocol                       = "Tcp"
            }
        ]
        backend = [
            {
                name               = "nginx-tcp7327-backend"
                protocol           = "Tcp"
                port               = 7327
                probe_name         = "nginx-tcp7327-probe"
                timeout_in_seconds = 90
            }
        ]
        routing_rule = [
            {
                name                      = "nginx-tcp7327-rule"
                listener_name             = "nginx-tcp7327"
                backend_name              = "nginx-tcp7327-backend"
                backend_address_pool_name = "nginx-pool"
                priority                  = 130
            }
        ]
        # Tcp probe - path/match are invalid for L4 and are omitted by the module.
        probe = [
            {
                name                                      = "nginx-tcp7327-probe"
                protocol                                  = "Tcp"
                port                                      = 7327
                interval                                  = 30
                timeout                                   = 20
                unhealthy_threshold                       = 3
                pick_host_name_from_backend_http_settings = false
                match                                     = null
            }
        ]
    }
}

L4 listener Variable Reference

Field Type Description Default
name string Listener name. Required
frontend_ip_configuration_name string Name of the frontend_ip_configuration entry this listener binds to. Required
frontend_port_name string Name of the frontend_port entry this listener listens on. Required
protocol string Tcp (raw passthrough, no TLS at the gateway) or Tls (TLS terminated at the gateway). Required
host_names list(string) Host names for SNI routing. Not allowed when protocol = "Tcp". null
ssl_certificate_name string Name of the ssl_certificate entry to present. Required when protocol = "Tls". null
ssl_profile_name string Name of the ssl_profile entry to apply. null

L4 backend Variable Reference

Field Type Description Default
name string Backend settings name. Required
port number Backend port. Required
protocol string Tcp or Tls. Required
client_ip_preservation_enabled bool Preserve the original client IP to the backend. null
host_name string Override host name sent to the backend. Tls only. null
probe_name string Name of the probe entry used for health checks. null
timeout_in_seconds number Backend connection timeout, in seconds. null
trusted_root_certificate_names list(string) Names of trusted_root_certificate entries to trust on the backend. null

L4 routing_rule Variable Reference

Field Type Description Default
name string Routing rule name. Required
listener_name string Name of the L4 listener this rule binds to. Required
backend_name string Name of the L4 backend this rule forwards to. Required
backend_address_pool_name string Name of the backend_address_pool this rule targets. Required
priority number Rule priority. Required

Note: The probe block is shared between L7 and L4 routing. For protocol = "Tcp" or protocol = "Tls" probes, set match = null; the path and match fields are invalid for L4 probes and are omitted by the module.