WAF-OPS-030 โ€“ Observability Stack Configured

Description

Every production workload MUST emit structured logs, expose metrics, and support distributed tracing. An observability stack MUST be configured with centralized log aggregation, a metrics collection system, and distributed tracing. Logs MUST be structured (JSON), include trace IDs and request IDs, and be routed to a centralized platform with defined retention periods.

Rationale

Risk Description

Risk

Unstructured logs and missing metrics delay troubleshooting and incident detection.

Risk

Without centralized observability data, SLO breaches and security incidents cannot be correlated.

Requirements

  • Every production workload MUST emit structured logs, expose metrics, and support distributed tracing.

  • An observability stack MUST be configured with centralized log aggregation, a metrics collection system, and distributed tracing.

  • Logs MUST be structured (JSON), include trace IDs and request IDs, and be routed to a centralized platform with defined retention periods.

Implementation Guidance

  1. Document the requirement in a version-controlled policy or standard.

  2. Assign ownership and establish a review cadence (e.g., quarterly).

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

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-ops-030.tf.aws.cloudwatch-log-group-retention

Engine: terraform | Provider: aws | Automated: Yes

CloudWatch log groups must define retention period

All AWS CloudWatch log groups MUST define a retention_in_days value. Log groups without retention will accumulate indefinitely, increasing costs and violating data governance requirements.

Scope: resource โ€” aws_cloudwatch_log_group

Assertions: * retention_in_days attribute exists โ€” CloudWatch log group must define retention_in_days. * retention_in_days greater than or equal 1 โ€” Log group retention must be at least 30 days.

Remediation: Add retention_in_days to all aws_cloudwatch_log_group resources. Recommended: 90 days for application logs, 365 days for security/audit logs.

Compliant
resource "aws_cloudwatch_log_group" "app_logs" {
  name              = "/aws/ecs/payment-service"
  retention_in_days = 90
  tags = {
    environment = "production"
    workload    = "payment-service"
  }
}
Non-Compliant
resource "aws_cloudwatch_log_group" "app_logs" {
  name = "/aws/ecs/payment-service"
  # No retention_in_days โ€“ logs stored indefinitely
  # WAF-OPS-030 Violation
}

waf-ops-030.tf.aws.xray-tracing-enabled

Engine: terraform | Provider: aws | Automated: Yes

AWS Lambda functions must have X-Ray tracing enabled

AWS Lambda functions in production MUST have X-Ray tracing enabled to support distributed request tracing and latency analysis.

Scope: resource โ€” aws_lambda_function

Assertions: * tracing_config.mode not in ['0.0.0.0/0', ''] โ€” Lambda tracing mode must be Active, not PassThrough.

Remediation: Add tracing_config { mode = "Active" } to all aws_lambda_function resources.

Compliant
resource "aws_lambda_function" "processor" {
  function_name = "payment-processor"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "index.handler"
  runtime       = "nodejs20.x"

  tracing_config {
    mode = "Active"
  }
}
Non-Compliant
resource "aws_lambda_function" "processor" {
  function_name = "payment-processor"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "index.handler"
  runtime       = "nodejs20.x"
  # No tracing_config โ€“ WAF-OPS-030 Violation
}

waf-ops-030.tf.azurerm.log-analytics-workspace

Engine: terraform | Provider: azurerm | Automated: Yes

Azure Log Analytics workspace must be configured with retention

Azure deployments MUST configure a Log Analytics workspace with an appropriate retention period for centralized log aggregation.

Scope: resource โ€” azurerm_log_analytics_workspace

Assertions: * retention_in_days greater than or equal 1 โ€” Log Analytics workspace retention must be at least 30 days.

Remediation: Set retention_in_days to at least 90 for application logs in the azurerm_log_analytics_workspace resource.

Compliant
resource "azurerm_log_analytics_workspace" "main" {
  name                = "law-payment-service-prod"
  location            = var.location
  resource_group_name = azurerm_resource_group.main.name
  sku                 = "PerGB2018"
  retention_in_days   = 90
}
Non-Compliant
resource "azurerm_log_analytics_workspace" "main" {
  name                = "law-payment-service-prod"
  location            = var.location
  resource_group_name = azurerm_resource_group.main.name
  sku                 = "PerGB2018"
  retention_in_days   = 7
  # 7 days is insufficient โ€“ WAF-OPS-030 Violation
}

waf-ops-030.tf.google.logging-project-sink-exists

Engine: terraform | Provider: google | Automated: Yes

GCP Cloud Logging sink must route structured logs to a centralized destination

Every production GCP project must define a google_logging_project_sink that routes structured logs to a central BigQuery dataset or Cloud Storage bucket. Cloud Trace must be enabled via the trace API usage.

Scope: resource โ€” google_logging_project_sink

Assertions: * destination attribute exists โ€” GCP project must route logs to a centralized BigQuery or Cloud Storage destination.

Remediation: Create a google_logging_project_sink for each production project with filter capturing application, audit, and security logs. Enable Cloud Trace API and configure applications to export traces.

Compliant
resource "google_logging_project_sink" "central" {
  name        = "centralized-logs"
  destination = "bigquery.googleapis.com/projects/${var.project_id}/datasets/logs"
  filter      = "severity >= WARNING OR protoPayload.serviceName != \"\""

  unique_writer_identity = true
}
Non-Compliant
# No google_logging_project_sink defined
# Application logs remain only in default log buckets

waf-ops-030.tf.stackit.log-destination-exists

Engine: terraform | Provider: stackit | Automated: Yes

STACKIT workloads must ship logs to a central destination

STACKIT workloads must ship logs to a central destination. This check validates the Terraform configuration uses the expected resource and attribute.

Scope: resource โ€” stackit_argus_instance, stackit_logme_instance, stackit_observability_instance

Assertions: * project_id attribute exists โ€” STACKIT observability/log instance must be configured.

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_argus_instance" "example" {
  # required attribute/tag/label present
}
Non-Compliant
# Example resource does not meet the requirement.
resource "stackit_argus_instance" "example" {
  # Missing required attribute/tag/label
}

waf-ops-030.tf.ovh.log-destination-exists

Engine: terraform | Provider: ovh | Automated: Yes

OVHcloud workloads must ship logs to a central destination

OVHcloud workloads must ship logs to a central destination. This check validates the Terraform configuration uses the expected resource and attribute.

Scope: resource โ€” ovh_cloud_project_database_postgresql, ovh_cloud_project_kube, ovh_dedicated_server

Assertions: * service_name attribute exists โ€” OVHcloud service must be configured for log forwarding.

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-ops-030.tf.hcloud.log-destination-exists

Engine: terraform | Provider: hcloud | Automated: Yes

Hetzner Cloud workloads must ship logs to a central destination

Hetzner Cloud workloads must ship logs to a central destination. This check validates the Terraform configuration uses the expected resource and attribute.

Scope: resource โ€” hcloud_server

Assertions: * labels.log-destination key exists โ€” Hetzner Cloud server must declare a log destination 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/IEC 20000-1

* Monitoring, measurement, analysis, and evaluation * Service availability management

ITIL 4

* Monitoring and event management * Service configuration management

SOC 2 Type II

* CC7.1 โ€“ Detect and Monitor โ€“ Vulnerability and Threat Detection

BSI C5:2020

* OIS-10 Protokollierung und Monitoring