Sägetstrasse 18, 3123 Belp, Switzerland +41 79 173 36 84 info@ict.technology

    Terraform @ Scale - Parte 3c: Monitoraggio e allerta per eventi di Blast Radius

    Neanche l’architettura infrastrutturale più sofisticata può prevenire ogni errore. È quindi fondamentale monitorare in modo proattivo le operazioni Terraform - in particolare quelle che potrebbero avere effetti distruttivi. L’obiettivo è rilevare tempestivamente modifiche critiche e attivare automaticamente degli allarmi, prima che si verifichi un raggio d’azione incontrollato.

    Certo – il suo System Engineer Le farà sicuramente notare che Terraform mostra l’intero piano prima dell’esecuzione di un apply e che tale esecuzione deve essere approvata manualmente digitando "yes".

    Quello che però il suo Engineer non Le dice: in realtà non legge mai davvero il piano prima di eseguirlo.

    «Andrà tutto bene.»

    Sistema di allerta precoce: Analisi automatizzata del piano

    Terraform mette a disposizione, con il flag -json, una funzionalità che consente di elaborare automaticamente le informazioni del piano. Questo permette di rilevare le eliminazioni pianificate (destroy) e avviare automaticamente contromisure, come ad esempio un avviso su Slack o l’interruzione automatica della pipeline CI/CD.

    Un altro indicatore precoce è il valore di ritorno di terraform plan -detailed-exitcode: un codice di uscita 2 segnala modifiche pianificate, incluse eliminazioni.

    Esempio: Script Bash per l’analisi del piano

    Questo script può essere integrato come hook nella pipeline CI/CD. Se vengono rilevate eliminazioni pianificate, avviene una notifica immediata – oppure, in modo opzionale, un arresto automatico del rollout.

    Uno script di esempio come riferimento:


    #!/bin/bash
    # Automated Plan Analysis Script
    
    set -e  # Exit on any error
    
    # Create the Terraform plan and export it in JSON format
    terraform plan -out=tfplan -detailed-exitcode
    PLAN_EXIT_CODE=$?
    
    # Check if there are changes (exit code 2)
    if [ $PLAN_EXIT_CODE -eq 2 ]; then
        terraform show -json tfplan > plan.json
        
        # Analyze planned deletions with more robust jq query
        DELETIONS=$(jq -r '.resource_changes[]? | select(.change.actions[]? == "delete") | .address' plan.json 2>/dev/null)
        
        if [ -n "$DELETIONS" ]; then
            echo "BLAST RADIUS ALERT: Planned deletions detected:"
            echo "$DELETIONS" | while read -r resource; do
                echo "  - $resource"
            done
            
            # Send alert with proper error handling
            if ! curl -f -X POST "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK" \
                -H 'Content-type: application/json' \
                --data "{\"text\":\"ALERT: Terraform Destroy detected in $WORKSPACE:\\n$DELETIONS\"}"; then
                echo "Warning: Failed to send Slack notification"
            fi
            
            exit 2
        fi
    fi
    

    Monitoraggio dei log basato su cloud con sistema di allerta

    Per ambienti produttivi si consiglia un monitoraggio centralizzato e nativo per il cloud. Questo può essere realizzato, ad esempio, tramite Splunk in esecuzione locale nel proprio data center. Oppure con servizi cloud come AWS CloudWatch o Oracle Logging. L’obiettivo è rilevare voci di log sospette con parole chiave distruttive come “destroy” e generare allarmi in tempo reale.

    Nota: I seguenti esempi servono come riferimento e, pur includendo le dichiarazioni di risorse necessarie, non sono ancora eseguibili End-to-End. I dettagli mancanti, come versions.tf e variables.tf, sono lasciati alla competenza del lettore sufficientemente esperto.

    Esempio: Integrazione con AWS CloudWatch

    Gli allarmi possono essere collegati direttamente a un aws_sns_topic, che a sua volta può inoltrare notifiche tramite e-mail, Slack, PagerDuty o altri sistemi. In questo modo, nessuna operazione critica di terraform destroy passerà inosservata.


    provider "aws" {
      region = "eu-central-1"
    }
    
    resource "aws_cloudwatch_log_group" "terraform_logs" {
      name              = "/terraform/cicd"
      retention_in_days = 7
    
      tags = {
        Environment = "production"
        Purpose     = "terraform-monitoring"
      }
    }
    
    resource "aws_cloudwatch_metric_filter" "terraform_destroy_filter" {
      name           = "terraform-destroy-keyword"
      log_group_name = aws_cloudwatch_log_group.terraform_logs.name
      pattern = "\"destroy\""
    
      metric_transformation {
        name      = "DestroyMatches"
        namespace = "Terraform/CI"
        value     = "1"
        unit      = "Count"  
      }
    }
    
    resource "aws_sns_topic" "alerts" {
      name = "terraform-blast-radius-alerts"
      
      tags = {
        Environment = "production"
        Purpose     = "terraform-alerts"
      }
    }
    
    resource "aws_sns_topic_subscription" "email_alert" {
      topic_arn = aws_sns_topic.alerts.arn
      protocol  = "email"
      endpoint  = var.alert_email 
    }
    
    resource "aws_cloudwatch_metric_alarm" "blast_radius_alarm" {
      alarm_name          = "Terraform-Destroy-Detected"
      alarm_description   = "Detects destroy operations in Terraform CI output"
      comparison_operator = "GreaterThanThreshold"
      evaluation_periods  = 1
      threshold           = 0
      metric_name         = "DestroyMatches"
      namespace           = "Terraform/CI"
      statistic           = "Sum"
      period              = 60
      treat_missing_data  = "notBreaching"
      
      insufficient_data_actions = []
      alarm_actions            = [aws_sns_topic.alerts.arn]
      ok_actions              = [aws_sns_topic.alerts.arn]
    
      tags = {
        Environment = "production"
        Purpose     = "blast-radius-monitoring"
      }
    }

    Esempio: OCI Logging con sistema di allerta

    In Oracle Cloud Infrastructure si utilizza il servizio Logging in combinazione con una Logging Query, un allarme e il servizio Notifications. In questo modo è possibile rilevare azioni distruttive come terraform destroy tramite parole chiave nel flusso di log della pipeline CI/CD o nei log di audit.

    Passaggi per la configurazione:

    1. Configurare un Log Group per i log di build o i log di audit
    2. Creare una Logging Search con una query come data.message CONTAINS "destroy"
    3. Definire un Alarm che si attivi in caso di corrispondenze
    4. Collegare un Notification Topic (email, PagerDuty, ecc.)

    Esempio di allarme tramite Terraform:


    resource "oci_logging_log_group" "terraform_logs" {
      display_name   = "terraform-ci-logs"
      compartment_id = var.compartment_id
      
      freeform_tags = {
        "Environment" = "production"
        "Purpose"     = "terraform-monitoring"
      }
    }
    
    resource "oci_logging_log" "cicd_log" {
      display_name = "terraform-cicd-log"
      log_group_id = oci_logging_log_group.terraform_logs.id
      log_type     = "CUSTOM"
      
      configuration {
        source {
          category    = "write"
          resource    = var.compartment_id
          service     = "objectstorage"
          source_type = "OCISERVICE"
        }
        
        compartment_id = var.compartment_id
      }
    
      is_enabled         = true
      retention_duration = 30
    }
    
    resource "oci_ons_notification_topic" "alerts" {
      name           = "terraform-destroy-alerts"
      compartment_id = var.compartment_id
      description    = "Alerts for blast-radius related events"
      
      freeform_tags = {
        "Environment" = "production"
        "Purpose"     = "terraform-alerts"
      }
    }
    
    resource "oci_ons_subscription" "email_subscription" {
      compartment_id = var.compartment_id
      topic_id       = oci_ons_notification_topic.alerts.id
      protocol       = "EMAIL"
      endpoint       = var.alert_email
    }
    
    resource "oci_monitoring_alarm" "terraform_destroy_alarm" {
      display_name         = "Terraform-Destroy-Detected"
      compartment_id       = var.compartment_id
      metric_compartment_id = var.compartment_id
      
      query = <<-EOQ
        LoggingAnalytics[1m]{
          logGroup = "${oci_logging_log_group.terraform_logs.display_name}",
          log = "${oci_logging_log.cicd_log.display_name}"
        } | where data.message =~ ".*destroy.*" | count()
      EOQ
      
      severity     = "CRITICAL"
      body         = "Terraform destroy operation detected in CI/CD pipeline!"
      is_enabled   = true
      
      pending_duration             = "PT1M"
      repeat_notification_duration = "PT15M"
      resolution                   = "1m"
    
      suppression {
        description = "Planned maintenance window"
        # time_suppress_from und time_suppress_until can be added if needed
      }
    
      destinations = [oci_ons_notification_topic.alerts.id]
      
      freeform_tags = {
        "Environment" = "production"
        "Purpose"     = "blast-radius-monitoring"
      }
    }

    Nota: La Logging Query utilizza una semplice ricerca testuale. Per ambienti produttivi, è consigliabile utilizzare filtri più precisi - ad esempio espressioni regolari o campi di log strutturati, qualora i tool CI producano log strutturati.
    In alternativa, è possibile utilizzare anche il motore di query LoggingSearch semplificato, se Logging Analytics non è attivato nella propria tenancy.

    Vantaggio aggiuntivo: Questo metodo può essere esteso anche ad azioni di apply, violazioni di policy o drift in OCI, a condizione che i log vengano alimentati correttamente (ad es. tramite output di Terraform Plan, avvisi di Sentinel o eventi di audit).

    ✅Checklist: Blast Radius Readiness

    Questa checklist può aiutarLa a costruire un'infrastruttura il più possibile resiliente.

    ✅ Misure preventive

    • [ ] States segmentati in base al Blast Radius Impact
    • [ ] Lifecycle Rules implementate per le risorse critiche
    • [ ] Validazioni di Remote State presenti
    • [ ] Policy-as-Code per le Destroy Operations
    • [ ] Analisi automatizzata del piano attivata
    • [ ] Mappatura delle dipendenze Cross-State creata

    🚨 Preparazione per il caso critico

    • [ ] Strategia di backup dello state implementata
    • [ ] Script di import per risorse critiche testati
    • [ ] Playbook di Incident Response disponibili
    • [ ] Formazione del team per operazioni di State Surgery effettuata
    • [ ] Monitoraggio e allerta per eventi Blast Radius attivi

    ✍️Pianificazione accurata e mentalità giusta

    Implementazioni Terraform di successo a livello enterprise richiedono anche:

    • Architettura proattiva: progettare i states in base al Blast Radius Impact
    • Programmazione difensiva: implementare guardrail e validazioni
    • Monitoring e alerting: rilevare tempestivamente eventi di Blast Radius
    • Preparazione alla recovery: essere pronti per il caso critico

    Conclusione: Esplosioni controllate anziché caos

    Importante: Il Blast Radius Management non è un setup una tantum, ma un processo continuo.

    La sfida è trovare il giusto equilibrio tra flessibilità e controllo - proprio come nel principio di Goldilocks, che abbiamo già descritto in dettaglio in un articolo precedente.

    Perché la migliore esplosione è quella che non avviene affatto.