Azure Application Gateway — as Shared Service for multiple application team & manage it as IaC through Terraform
Azure Application Gateway (AGW) is a web traffic load balancer that enables you to manage traffic to your web applications, it works with Layer 7 traffic, and specifically with HTTP/S. It can make routing decisions based on additional attributes of an HTTP request, for example URI path or host headers. We will explore in this blog, why & how you can use this as Shared Service in your organization (this is my personal opinion), and how to maintain/manage it via Terraform.
Azure Application Gateway
Traditional Azure Load Balancers operate at the layer 4 TCP/UDP and route traffic based on source IP address and port, to a destination IP address and port.
Azure Application Gateway is a web traffic manager for your web applications (one or multiple) operate at the layer 7. With AGW, on top of load balancing your workloads, you can make routing decisions based on URI path or host headers. For example, you can route traffic based on the incoming URL. If /images are in the inbound URL, you can route traffic to a specific set of servers (or pool) configured for images. If /video is in the URL, that traffic is routed to another pool that’s optimized for videos processing.
It can be used to do TLS/SSL termination. TLS/SSL termination can be useful to allow unencrypted traffic between AGW and backend servers saving some of processing load needed to encrypt and decrypt said traffic. However, sometimes unencrypted communication to the servers is not acceptable because of security requirements, compliance requirements, or application may only accept a secure connection. In these situations, Application Gateway also supports end-to-end TLS/SSL encryption
It includes firewall called Web application firewall (WAF) that protects your workload from common exploits like SQL injection attacks or cross-site scripting attacks, to name a few.
Application Gateway is available in 3 flavor tier of SKU - Standard (v1), Standard_v2 & WAF_v2 SKU. Existing features under the Standard SKU continue to be supported in the new v2 SKU, with new enhancements like
Autoscaling, Zone redundancy, Static VIP, Header Rewrite , Key Vault Integration, Mutual Authentication(mTLS), AKS Ingress Controller,
Performance enhancements, Faster Deployment and update time.
See feature comparison between v1 SKU and v2 SKU here
Why share Application Gateway?
One reason is cost. As of Apr 30th, 2022 the lowest monthly price for Application Gateway with Web Application Firewall is ~$278 (31 days Fixed Gateway hours with 1 capacity unit) as per Azure Pricing Calculator here . To get understanding on AGW pricing, see here .
Other reason is dedicated subnet requirement. Within your virtual network, a dedicated subnet is required for the application gateway. You can have multiple instances of a given application gateway deployment in a subnet. You can also deploy other application gateways in the subnet. But you can’t deploy any other resource in the application gateway subnet.
Although a /24 subnet is not required per Application Gateway v2 SKU deployment, however it is highly recommended by Azure. This is to ensure that Application Gateway v2 has sufficient space for autoscaling expansion and maintenance upgrades.
Multiple Applications sharing one Application Gateway
Azure Application Gateway uses one private and one public IP address on which it listens for traffic. Therefore if several applications share Application Gateway you need ensure your applications can be accessed via the same Application Gateway front-end port. Following are the options to allow multiple applications to be deployed and share the same port on Azure Application Gateway.
Multi-site Hosting:
Application Gateway configured with multi-site hosting determines the back-end pool that will serve the request received by AGW based on the value of Host header in http request.
To enable multi-site hosting configure multi-site listeners (rather than basic listeners) on application gateway. Essentially specify host that every listener will serve.
Path-based routing rules:
URL Path Based Routing allows you to route traffic to AGW back-end server pools based on URL Paths of the request
Application Gateway Deployment via Terraform
Deployment of AGW can be achieved by Terraform. If you are using single application per AGW, input configuration parameters will be less and its easy to manage and operate it. For deployment, you will create Terraform module and will split input parameters as below. Have a look at sample main.tf file of module here to understand how this input parameters used.
backend_address_pools = [],
backend_http_settings = [],
http_listeners = [],
basic_request_routing_rules = [],
path_based_request_routing_rules = [],
redirect_request_routing_rules = [],
redirect_configurations = [],
ssl_certificate_configs = [],
url_path_map_configs = [],
probe_configs = [],
rewrite_rule_sets = []
However, when you use AGW as shared service for multiple application, providing input configuration parameters for all application will become cumbersome, difficult to maintain, and operate it. Any single input parameter should include requirement for that configuration from all multiple applications. Example, if you have 10 applications, your “backend_address_pools” input parameter should have configuration details for all 10 application backends. To overcome this challenge, we will take input file per application, which will be process and validated by wrapper code (in go language), merge into respective single input parameter, and will pass to Terraform module as tfvars.json. This approach, help you to formulate naming of rules, handle configuration error by validating references in rules and then merge it. You can write wrapper code in your choice of programming language. Here is snippet of go code for reference.
With this, your Terraform module invocation code directory structure will be as below. Trusted root certificate and Rewrite rule set are global for AGW and not bound to specific application, hence need to be treated differently.
.
├── configs ==> directory for application Config files
│ ├── app1_config.json
│ ├── app2_config.json
│ ├── rewrite_rule_set.json
├── cert ==> directory for trusted root certs
│ ├── root_cert1.crt
│ ├── root_cert2.crt
├── provider.tf
├── main.tf
├── build-pipeline.yaml ==> include task for wrapper code
├── README.md
├── tf_agw_wrapper
└── variables.tf
Each application config file will have
{
"app_id": "1234",
"env" : "qty",
"backend_address_pools" : [],
"backend_http_settings" : [],
"http_listeners" : [],
"basic_request_routing_rules" : [],
"path_based_request_routing_rules" : [],
"redirect_request_routing_rules" : [],
"redirect_configurations" : [],
"ssl_certificate_configs" : [],
"url_path_map_configs" : [],
"probe_configs" : []
}
Here is sample application config input file. Complete input template is available here for reference
Managing listeners certificates in Azure Key Vault
To enable TLS/SSL termination at AGW, we need to add TLS/SSL certificates to AGW listeners. TLS certificate should be in PFX format. Azure Key Vault is a service where we can store secrets, keys, certificates securely.
Application Gateway can read certificates from Key Vault and install them locally for TLS termination. For this, we need to create a user-assigned managed identity, assign it to AGW and give “Get” access on Key Vault. Application gateway keeps polling Key Vault for every 4 hours to check if any renewed version of the certificate is added or not. If Application gateway finds a renewed certificate then it automatically rotates the existing certificate.
Using this feature and integrating it in our code, removes storing this certificates in git repo. This also enable, individual team to maintain their own application certificate in their own Azure Key Vault. They only need to provide “Get” access on Key Vault to AGW use-assigned managed identity.
"http_listeners" : [
{
"name" : "demo2",
"frontend_port_number" : 443,
"protocol" : "Https" ,
"ssl_certificate_name" : "democrt1"
}
],
"ssl_certificate_configs" : [
{
"name" : "democrt1",
"key_vault_secret_id" : "https://dummyvault1234.vault.azure.net/secrets/demo"
}
]
Hope this blog help you to give an idea on how you can use Azure Application Gateway as Shared Service to reduce cost and maximize its usage within multiple application teams.
Note: My code snippet is available here for reference. Please note this is not complete code.