Managing Azure Front Door with Terraform
Learn how to set up and manage Azure Front Door using Terraform, including WAF policies, routing rules, and caching
Managing Azure Front Door with Terraform
Azure Front Door is a global, scalable entry-point that uses Microsoft’s global edge network to create fast, secure, and widely available web applications. This guide demonstrates how to set up and manage Front Door using Terraform.
Video Tutorial
Learn more about managing Azure Front Door with Terraform in this comprehensive video tutorial:
Prerequisites
- Azure CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Resource group created
- Understanding of CDN and WAF concepts
Project Structure
terraform-azure-frontdoor/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── frontdoor/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── policies/
└── waf.json
Front Door Configuration
Create modules/frontdoor/main.tf
:
# Front Door Profile
resource "azurerm_cdn_frontdoor_profile" "main" {
name = "${var.project_name}-fd"
resource_group_name = var.resource_group_name
sku_name = "Premium_AzureFrontDoor"
tags = var.tags
}
# WAF Policy
resource "azurerm_cdn_frontdoor_firewall_policy" "main" {
name = "${var.project_name}-waf"
resource_group_name = var.resource_group_name
sku_name = azurerm_cdn_frontdoor_profile.main.sku_name
enabled = true
mode = "Prevention"
custom_rule {
name = "BlockIPRange"
enabled = true
priority = 100
rate_limit_duration_in_minutes = 1
rate_limit_threshold = 10
type = "MatchRule"
action = "Block"
match_condition {
match_variable = "RemoteAddr"
operator = "IPMatch"
negation_condition = false
match_values = ["192.168.1.0/24"]
}
}
managed_rule {
type = "DefaultRuleSet"
version = "1.0"
action = "Block"
override {
rule_group_name = "PHP"
rule {
rule_id = "933100"
enabled = false
action = "Block"
}
}
}
managed_rule {
type = "BotProtection"
version = "1.0"
action = "Block"
}
}
# Endpoint
resource "azurerm_cdn_frontdoor_endpoint" "main" {
name = "${var.project_name}-endpoint"
cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id
tags = var.tags
}
# Origin Group
resource "azurerm_cdn_frontdoor_origin_group" "main" {
name = "${var.project_name}-origin-group"
cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id
session_affinity_enabled = true
load_balancing {
sample_size = 4
successful_samples_required = 3
additional_latency_in_ms = 50
}
health_probe {
path = "/health"
protocol = "Https"
interval_in_seconds = 100
request_type = "HEAD"
}
}
# Origin
resource "azurerm_cdn_frontdoor_origin" "main" {
name = "${var.project_name}-origin"
cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.main.id
enabled = true
certificate_name_check_enabled = true
host_name = "api.example.com"
http_port = 80
https_port = 443
origin_host_header = "api.example.com"
priority = 1
weight = 1000
private_link {
request_message = "Request access for Front Door"
target_type = "sites"
location = var.location
private_link_target_id = var.app_service_id
}
}
# Route
resource "azurerm_cdn_frontdoor_route" "main" {
name = "${var.project_name}-route"
cdn_frontdoor_endpoint_id = azurerm_cdn_frontdoor_endpoint.main.id
cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.main.id
enabled = true
forwarding_protocol = "HttpsOnly"
https_redirect_enabled = true
patterns_to_match = ["/*"]
supported_protocols = ["Http", "Https"]
cache {
query_string_caching_behavior = "IgnoreQueryString"
compression_enabled = true
content_types_to_compress = ["text/html", "text/javascript", "text/css"]
}
custom_domains = [azurerm_cdn_frontdoor_custom_domain.main.id]
}
# Custom Domain
resource "azurerm_cdn_frontdoor_custom_domain" "main" {
name = "${var.project_name}-custom-domain"
cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id
dns_zone_id = var.dns_zone_id
host_name = "www.example.com"
tls {
certificate_type = "ManagedCertificate"
minimum_tls_version = "TLS12"
}
}
# Rule Set
resource "azurerm_cdn_frontdoor_rule_set" "main" {
name = "${var.project_name}-ruleset"
cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id
}
# Rules
resource "azurerm_cdn_frontdoor_rule" "redirect" {
name = "redirect-rule"
cdn_frontdoor_rule_set_id = azurerm_cdn_frontdoor_rule_set.main.id
order = 1
behavior_on_match = "Continue"
conditions {
url_path_condition {
operator = "BeginsWith"
negate_condition = false
match_values = ["/old"]
}
}
actions {
url_redirect_action {
redirect_type = "Found"
destination_path = "/new"
destination_fragment = "section1"
query_string = "path={path}"
}
}
}
resource "azurerm_cdn_frontdoor_rule" "cache" {
name = "cache-rule"
cdn_frontdoor_rule_set_id = azurerm_cdn_frontdoor_rule_set.main.id
order = 2
behavior_on_match = "Continue"
conditions {
url_file_extension_condition {
operator = "Equal"
negate_condition = false
match_values = ["jpg", "png", "gif"]
}
}
actions {
cache_expiration_action {
behavior = "Override"
duration = "08:00:00"
}
}
}
# Security Policy
resource "azurerm_cdn_frontdoor_security_policy" "main" {
name = "${var.project_name}-security"
cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.main.id
security_policies {
firewall {
cdn_frontdoor_firewall_policy_id = azurerm_cdn_frontdoor_firewall_policy.main.id
association {
patterns_to_match = ["/*"]
domain {
cdn_frontdoor_domain_id = azurerm_cdn_frontdoor_endpoint.main.id
}
}
}
}
}
## DNS Configuration
1. **DNS Records**
```hcl
resource "azurerm_dns_cname_record" "frontdoor" {
name = "www"
zone_name = var.dns_zone_name
resource_group_name = var.resource_group_name
ttl = 3600
record = azurerm_cdn_frontdoor_endpoint.main.host_name
}
resource "azurerm_dns_txt_record" "frontdoor" {
name = "_dnsauth.www"
zone_name = var.dns_zone_name
resource_group_name = var.resource_group_name
ttl = 3600
record {
value = azurerm_cdn_frontdoor_custom_domain.main.validation_token
}
}
Monitoring Configuration
- Diagnostic Settings
resource "azurerm_monitor_diagnostic_setting" "frontdoor" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_cdn_frontdoor_profile.main.id
log_analytics_workspace_id = var.log_analytics_workspace_id
log {
category = "FrontDoorAccessLog"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
resource "azurerm_monitor_metric_alert" "frontdoor" {
name = "${var.project_name}-latency-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_cdn_frontdoor_profile.main.id]
description = "Alert when latency is high"
criteria {
metric_namespace = "Microsoft.Cdn/profiles"
metric_name = "TotalLatency"
aggregation = "Average"
operator = "GreaterThan"
threshold = 1000
}
action {
action_group_id = var.action_group_id
}
}
Best Practices
-
Performance
- Enable caching
- Configure compression
- Use custom domains
- Optimize routing
-
Security
- Enable WAF
- Configure SSL/TLS
- Implement rate limiting
- Monitor traffic
-
High Availability
- Use multiple origins
- Configure health probes
- Implement load balancing
- Monitor endpoints
-
Cost Optimization
- Monitor usage
- Configure rules
Conclusion
You’ve learned how to set up and manage Azure Front Door using Terraform. This setup provides:
- Global load balancing
- WAF protection
- SSL/TLS termination
- Caching and compression
Remember to:
- Monitor performance
- Review security rules
- Update WAF policies
- Maintain configurations