Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This documentation describes a list of rules available by enabling this ruleset.

|Rule|Enabled by default|
| --- | --- |
|[azurerm_app_service_missing_auto_heal_setting](rules/azurerm_app_service_missing_auto_heal_setting.md)|✔|
|[azurerm_linux_virtual_machine_invalid_name](rules/azurerm_linux_virtual_machine_invalid_name.md)|✔|
|[azurerm_linux_virtual_machine_invalid_size](rules/azurerm_linux_virtual_machine_invalid_size.md)|✔|
|[azurerm_linux_virtual_machine_scale_set_invalid_sku](rules/azurerm_linux_virtual_machine_scale_set_invalid_sku.md)|✔|
Expand Down
126 changes: 126 additions & 0 deletions docs/rules/azurerm_app_service_missing_auto_heal_setting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# azurerm_app_service_missing_auto_heal_setting

Disallow missing auto_heal_setting configuration in site_config block for Azure App Service resources.

This rule applies to the following Azure App Service resource types:
- `azurerm_linux_web_app`
- `azurerm_linux_web_app_slot`
- `azurerm_windows_web_app`
- `azurerm_windows_web_app_slot`

## Configuration

```hcl
rule "azurerm_app_service_missing_auto_heal_setting" {
enabled = true
}
```

## Example

### Terraform Configuration

```hcl
# Non-compliant: Linux Web App with site_config but no auto_heal_setting
resource "azurerm_linux_web_app" "example" {
name = "example-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
service_plan_id = azurerm_service_plan.example.id

site_config {
always_on = true
}
}

# Compliant: Linux Web App with auto_heal_setting configured
resource "azurerm_linux_web_app" "example" {
name = "example-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
service_plan_id = azurerm_service_plan.example.id

site_config {
always_on = true

auto_heal_setting {
action {
action_type = "Recycle"
}
trigger {
status_code {
count = 5
interval = "00:01:00"
status_code_range = "500-599"
}
}
}
}
}

# Compliant: Windows Web App Slot with comprehensive auto_heal_setting
resource "azurerm_windows_web_app_slot" "example" {
name = "example-slot"
app_service_id = azurerm_windows_web_app.example.id

site_config {
auto_heal_setting {
action {
action_type = "Recycle"
minimum_process_execution_time = "00:01:00"
}
trigger {
status_code {
count = 5
interval = "00:01:00"
status_code_range = "500-599"
}
requests {
count = 100
interval = "00:01:00"
}
slow_request {
count = 10
interval = "00:02:00"
time_taken = "00:00:45"
}
}
}
}
}
```

## Why

Configuring `auto_heal_setting` in the `site_config` block is a best practice for production Azure App Service resources. Auto-healing helps improve application resilience by automatically recycling or restarting the app when specific conditions are met, such as:

- High number of HTTP errors (status codes in the 400-599 range)
- Excessive request volume
- Slow response times
- Memory threshold breaches

By proactively detecting and responding to unhealthy states, auto-healing can prevent prolonged outages and improve overall application availability. This rule ensures that App Service resources have auto-healing configured to maintain production resilience.

For more information about building robust apps for the cloud with auto-heal, see the [Azure App Service documentation on Auto Heal](https://azure.github.io/AppService/2020/05/15/Robust-Apps-for-the-cloud.html#auto-heal).

## How to Fix

Add an `auto_heal_setting` block within the `site_config` block:

```hcl
site_config {
auto_heal_setting {
action {
action_type = "Recycle"
}
trigger {
status_code {
count = 5
interval = "00:01:00"
status_code_range = "500-599"
}
}
}
}
```
You can combine multiple triggers to create comprehensive auto-healing policies.
122 changes: 122 additions & 0 deletions rules/azurerm_app_service_missing_auto_heal_setting.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package rules

import (
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/logger"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/terraform-linters/tflint-ruleset-azurerm/project"
)

// AzurermAppServiceMissingAutoHealSettingRule checks whether auto_heal_setting is configured in site_config
type AzurermAppServiceMissingAutoHealSettingRule struct {
tflint.DefaultRule
}

const (
autoHealSettingBlockName = "auto_heal_setting"
)

var autoHealResourceTypes = []string{
"azurerm_linux_web_app",
"azurerm_linux_web_app_slot",
"azurerm_windows_web_app",
"azurerm_windows_web_app_slot",
}

// NewAzurermAppServiceMissingAutoHealSettingRule returns new rule for checking auto_heal_setting configuration
func NewAzurermAppServiceMissingAutoHealSettingRule() *AzurermAppServiceMissingAutoHealSettingRule {
return &AzurermAppServiceMissingAutoHealSettingRule{}
}

// Name returns the rule name
func (r *AzurermAppServiceMissingAutoHealSettingRule) Name() string {
return "azurerm_app_service_missing_auto_heal_setting"
}

// Enabled returns whether the rule is enabled by default
func (r *AzurermAppServiceMissingAutoHealSettingRule) Enabled() bool {
return true
}

// Severity returns the rule severity
func (r *AzurermAppServiceMissingAutoHealSettingRule) Severity() tflint.Severity {
return tflint.WARNING
}

// Link returns the rule reference link
func (r *AzurermAppServiceMissingAutoHealSettingRule) Link() string {
return project.ReferenceLink(r.Name())
}

// checkResourceType checks a specific resource type for auto_heal_setting configuration
func (r *AzurermAppServiceMissingAutoHealSettingRule) checkResourceType(runner tflint.Runner, resourceType string) error {
resources, err := runner.GetResourceContent(resourceType, &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "site_config",
Body: &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: autoHealSettingBlockName,
},
},
},
},
},
}, nil)

if err != nil {
return err
}

for _, resource := range resources.Blocks {
logger.Debug("checking", "resource type", resource.Labels[0], "resource name", resource.Labels[1])

// Check if site_config block exists
hasSiteConfig := false
hasAutoHealSetting := false

for _, block := range resource.Body.Blocks {
if block.Type == "site_config" {
hasSiteConfig = true

// Check for auto_heal_setting block
for _, siteConfigBlock := range block.Body.Blocks {
if siteConfigBlock.Type == "auto_heal_setting" {
hasAutoHealSetting = true
break
}
}

break
}
}

// If site_config doesn't exist, skip this resource
if !hasSiteConfig {
logger.Debug("no site_config block found", "resource type", resource.Labels[0], "resource name", resource.Labels[1])
continue
}

// Emit issue if auto_heal_setting is not configured in site_config
if !hasAutoHealSetting {
issue := "auto_heal_setting should be configured in site_config block for robust app services."
if err := runner.EmitIssue(r, issue, resource.DefRange); err != nil {
return err
}
}
}

return nil
}

// Check checks whether auto_heal_setting is configured in site_config
func (r *AzurermAppServiceMissingAutoHealSettingRule) Check(runner tflint.Runner) error {
for _, resourceType := range autoHealResourceTypes {
if err := r.checkResourceType(runner, resourceType); err != nil {
return err
}
}

return nil
}
Loading