WAF-REL-030 โ€“ Multi-AZ High Availability Deployment

Description

All production stateful and stateless workloads MUST be deployed across a minimum of two Availability Zones (AZs). Databases, caches, and message queues MUST use multi-AZ configurations with automatic failover. Load balancers MUST span at least two AZs. Auto-scaling groups and Kubernetes clusters MUST distribute nodes and pods across AZs. Single-AZ deployments in production are not acceptable without explicit documented risk acceptance.

Rationale

Risk Description

Risk

Single-AZ deployments become completely unreachable during zone failures.

Risk

Missing multi-AZ strategies violate availability requirements for critical workloads.

Requirements

  • All production stateful and stateless workloads MUST be deployed across a minimum of two Availability Zones (AZs).

  • Databases, caches, and message queues MUST use multi-AZ configurations with automatic failover.

  • Load balancers MUST span at least two AZs.

  • Auto-scaling groups and Kubernetes clusters MUST distribute nodes and pods across AZs.

Implementation Guidance

  1. Implement the required configuration as code in Terraform or equivalent IaC.

  2. Add an automated check to CI/CD so deviations are caught before deployment.

Maturity Levels

Level Name Criteria

L1

Ad hoc โ€“ control not consistently applied

* Manual evidence exists for some workloads, but coverage is unknown.

L2

Standardised โ€“ policy defined and communicated

* A version-controlled policy, ADR, or standard describes the requirement.

L3

Integrated โ€“ automated validation in CI/CD

* Terraform checks run automatically on pull requests and report results.

L4

Auditable โ€“ metrics and exceptions tracked

* Control coverage, failures, and approved exceptions are reported quarterly.

L5

Optimised โ€“ continuous improvement based on data

* Control effectiveness is measured and iteratively improved.

Checks

waf-rel-030.tf.aws.rds-multi-az

Engine: terraform | Provider: aws | Automated: Yes

AWS RDS instances must have Multi-AZ enabled

Production RDS instances must have multi_az = true to enable automatic failover to a standby replica in a different AZ on failure.

Scope: resource โ€” aws_db_instance

Assertions: * multi_az is true โ€” RDS instance must have multi_az = true for production availability.

Remediation: Set multi_az = true on the aws_db_instance resource. This creates a synchronous standby replica in a different AZ. Failover is automatic and typically completes within 1-2 minutes.

Compliant
resource "aws_db_instance" "main" {
  identifier        = "payment-db-prod"
  engine            = "postgres"
  engine_version    = "15.4"
  instance_class    = "db.t3.medium"
  allocated_storage = 100
  multi_az          = true
  db_subnet_group_name = aws_db_subnet_group.main.name
  tags = var.mandatory_tags
}
Non-Compliant
resource "aws_db_instance" "main" {
  identifier        = "payment-db-prod"
  engine            = "postgres"
  instance_class    = "db.t3.medium"
  allocated_storage = 100
  multi_az          = false  # WAF-REL-030 violation
  db_subnet_group_name = aws_db_subnet_group.main.name
}

waf-rel-030.tf.aws.autoscaling-multi-az

Engine: terraform | Provider: aws | Automated: Yes

AWS Auto Scaling Group must span at least 2 availability zones

Auto Scaling Groups in production must reference subnets in at least 2 different AZs to ensure compute redundancy.

Scope: resource โ€” aws_autoscaling_group

Assertions: * vpc_zone_identifier not empty โ€” Auto Scaling Group must specify VPC subnets across multiple AZs. * min_size greater than or equal 1 โ€” Auto Scaling Group minimum size must be at least 2 for HA.

Remediation: Set vpc_zone_identifier to a list containing subnet IDs from at least 2 AZs. Increase min_size to 2 to ensure at least one instance per AZ during failures.

Compliant
resource "aws_autoscaling_group" "api" {
  name               = "payment-api-asg"
  min_size           = 2
  max_size           = 10
  desired_capacity   = 2
  vpc_zone_identifier = [
    aws_subnet.private_az1.id,
    aws_subnet.private_az2.id,
  ]
}
Non-Compliant
resource "aws_autoscaling_group" "api" {
  name               = "payment-api-asg"
  min_size           = 1
  max_size           = 4
  desired_capacity   = 1
  vpc_zone_identifier = [aws_subnet.private_az1.id]
  # Single AZ โ€“ WAF-REL-030 violation
}

waf-rel-030.tf.azurerm.db-availability-zone

Engine: terraform | Provider: azurerm | Automated: Yes

Azure database services must use zone-redundant configuration

Azure SQL Database, PostgreSQL Flexible Server, and other managed databases must use zone_redundant = true or configure standby_availability_zone.

Scope: resource โ€” azurerm_postgresql_flexible_server, azurerm_mssql_database, azurerm_mysql_flexible_server

Assertions: * high_availability attribute exists โ€” Database must define high_availability block with zone-redundant configuration.

Remediation: Add a high_availability block with mode = "ZoneRedundant" and configure standby_availability_zone to a different zone than the primary.

Compliant
resource "azurerm_postgresql_flexible_server" "main" {
  name                = "payment-db-prod"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  version             = "15"
  sku_name            = "GP_Standard_D2s_v3"
  availability_zone   = "1"

  high_availability {
    mode                      = "ZoneRedundant"
    standby_availability_zone = "2"
  }
}
Non-Compliant
resource "azurerm_postgresql_flexible_server" "main" {
  name                = "payment-db-prod"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  version             = "15"
  sku_name            = "GP_Standard_D2s_v3"
  # Missing: high_availability โ€“ single zone deployment
}

waf-rel-030.tf.google.sql-availability-type

Engine: terraform | Provider: google | Automated: Yes

GCP Cloud SQL must use REGIONAL availability type

GCP Cloud SQL instances must use availability_type = REGIONAL for automatic failover across zones in the same region.

Scope: resource โ€” google_sql_database_instance

Assertions: * settings.availability_type equals REGIONAL โ€” Cloud SQL must use REGIONAL availability type, not ZONAL.

Remediation: Set availability_type = "REGIONAL" in the settings block of google_sql_database_instance to enable automatic failover to a different zone.

Compliant
resource "google_sql_database_instance" "main" {
  name             = "payment-db-prod"
  database_version = "POSTGRES_15"
  settings {
    tier              = "db-custom-2-7680"
    availability_type = "REGIONAL"
    backup_configuration {
      enabled    = true
      start_time = "02:00"
    }
  }
}
Non-Compliant
resource "google_sql_database_instance" "main" {
  name             = "payment-db-prod"
  database_version = "POSTGRES_15"
  settings {
    tier              = "db-custom-2-7680"
    availability_type = "ZONAL"  # WAF-REL-030 violation
  }
}

waf-rel-030.tf.stackit.ske-backup-enabled

Engine: terraform | Provider: stackit | Automated: Yes

STACKIT managed services must have backup configured

STACKIT managed services must have backup configured. This check validates the Terraform configuration uses the expected resource and attribute.

Scope: resource โ€” stackit_postgres_instance, stackit_mysql_instance, stackit_mariadb_instance, stackit_ske_cluster

Assertions: * backup_schedule attribute exists โ€” STACKIT managed service must define a backup schedule.

Remediation: Review the Terraform configuration for the listed resource types and ensure the required attribute or tag is present. See the control narrative for provider-specific guidance.

Compliant
# Example resource meets the requirement.
resource "stackit_postgres_instance" "example" {
  # required attribute/tag/label present
}
Non-Compliant
# Example resource does not meet the requirement.
resource "stackit_postgres_instance" "example" {
  # Missing required attribute/tag/label
}

waf-rel-030.tf.ovh.database-backup-enabled

Engine: terraform | Provider: ovh | Automated: Yes

OVHcloud managed databases must have backup configured

OVHcloud managed databases must have backup configured. This check validates the Terraform configuration uses the expected resource and attribute.

Scope: resource โ€” ovh_cloud_project_database_postgresql, ovh_cloud_project_database_mysql

Assertions: * backup_regions attribute exists โ€” OVHcloud managed database must configure backup regions.

Remediation: Review the Terraform configuration for the listed resource types and ensure the required attribute or tag is present. See the control narrative for provider-specific guidance.

Compliant
# Example resource meets the requirement.
resource "ovh_cloud_project_database_postgresql" "example" {
  # required attribute/tag/label present
}
Non-Compliant
# Example resource does not meet the requirement.
resource "ovh_cloud_project_database_postgresql" "example" {
  # Missing required attribute/tag/label
}

waf-rel-030.tf.hcloud.server-backup-plan

Engine: terraform | Provider: hcloud | Automated: Yes

Hetzner Cloud servers must have a backup plan configured

Hetzner Cloud servers must have a backup plan configured. This check validates the Terraform configuration uses the expected resource and attribute.

Scope: resource โ€” hcloud_server, hcloud_volume

Assertions: * labels.backup-plan key exists โ€” Hetzner Cloud server/volume must declare a backup-plan label.

Remediation: Review the Terraform configuration for the listed resource types and ensure the required attribute or tag is present. See the control narrative for provider-specific guidance.

Compliant
# Example resource meets the requirement.
resource "hcloud_server" "example" {
  # required attribute/tag/label present
}
Non-Compliant
# Example resource does not meet the requirement.
resource "hcloud_server" "example" {
  # Missing required attribute/tag/label
}

Evidence

Kind Required Description

iac

Required

Terraform configuration implementing the control.

governance

Required

Policy, ADR, or standard documenting the requirement.

config

Optional

Cloud console or API output confirming runtime state.

Framework Controls

ISO 27001:2022

* A.17.1 โ€“ Information security continuity * A.17.2 โ€“ Redundancies

ITIL 4

* Availability Management * Service Continuity Management

BSI C5:2020

* RB-01 โ€“ Availability and Redundancy