Plan Approval Strategy #

terraform plan menunjukkan apa yang akan berubah. terraform apply benar-benar mengubahnya. Di antara keduanya ada jeda yang sangat berharga: kesempatan untuk verifikasi, review, dan persetujuan sebelum infrastruktur production dimodifikasi. Bagaimana jeda ini dikelola — siapa yang harus menyetujui, dalam kondisi apa apply otomatis diizinkan, dan bagaimana memastikan yang di-apply adalah persis yang sudah di-review — adalah inti dari plan approval strategy.

flowchart TD
    A["terraform plan"] --> B["plan output"]
    B --> C["Review"]
    C -->|"approve"| D["terraform apply"]
    C -->|"reject"| E["Revise config"]
    E --> A

    style A fill:#3b82f6,stroke:#1e40af,color:#fff
    style B fill:#10b981,stroke:#059669,color:#fff
    style C fill:#f97316,stroke:#ea580c,color:#fff
    style D fill:#10b981,stroke:#059669,color:#fff
    style E fill:#ef4444,stroke:#dc2626,color:#fff

Mengapa Approval Penting #

TANPA APPROVAL STRATEGY:

  Developer A menjalankan plan → melihat output → apply
  Masalah:
  - Tidak ada yang tahu apa yang berubah selain Developer A
  - Plan yang di-review dan plan yang di-apply bisa berbeda
    (jika ada perubahan di antara keduanya)
  - Tidak ada audit trail siapa yang meng-authorize perubahan
  - Untuk production: satu orang bisa destroy semua resource tanpa diketahui

DENGAN APPROVAL STRATEGY:

  Developer A → PR dengan perubahan konfigurasi
  CI/CD → jalankan plan, post ke PR sebagai comment
  Reviewer B → review plan, setujui PR
  Merge ke main → apply berjalan otomatis ATAU dipicu manual
  Semua langkah tercatat di Git history

Pola 1: PR-Based Approval (Paling Umum) #

Ini adalah pola yang paling banyak dipakai karena memanfaatkan infrastruktur PR review yang sudah ada di semua tim.

ALUR KERJA:

  1. Developer buat branch, ubah konfigurasi .tf
  2. Push dan buka PR
  3. CI pipeline otomatis:
     - Jalankan terraform plan
     - Post output plan ke PR sebagai comment
     - Upload tfplan sebagai artifact
  4. Reviewer melihat plan di PR comment — bukan hanya kode, tapi DAMPAKNYA
  5. Reviewer approve PR jika plan aman
  6. Merge ke main branch
  7. Pipeline di main branch:
     - Download tfplan artifact yang sama dari step 3
     - Jalankan terraform apply tfplan
     - BUKAN plan baru — plan yang sudah di-review

KUNCI KEAMANAN:
  Gunakan tfplan yang sama antara review dan apply.
  Jangan jalankan `terraform plan` lagi saat apply —
  kondisi infrastruktur bisa berubah di antara PR open dan merge.
# GitHub Actions: Apply menggunakan artifact dari PR plan
# .github/workflows/apply.yml

name: Terraform Apply

on:
  push:
    branches: [main]

jobs:
  apply:
    runs-on: ubuntu-latest
    environment: production  # Environment protection rules berlaku di sini
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "1.7.0"

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/TerraformApplyRole
          aws-region: ap-southeast-1

      - name: Download Plan Artifact
        uses: dawidd6/action-download-artifact@v3
        with:
          # Download artifact dari PR yang di-merge (bukan plan baru)
          workflow: terraform.yml
          commit: ${{ github.event.before }}  # Commit sebelum merge
          name: tfplan-${{ github.event.before }}
          path: infrastructure/environments/production/

      - name: Terraform Init
        run: terraform init
        working-directory: infrastructure/environments/production

      - name: Terraform Apply
        run: terraform apply tfplan
        working-directory: infrastructure/environments/production

Pola 2: Environment Protection Rules #

GitHub dan GitLab menyediakan mekanisme native untuk membutuhkan approval sebelum workflow berjalan di environment tertentu.

# GitHub: Konfigurasi di Settings > Environments > production
# Tidak perlu kode tambahan — konfigurasi di UI GitHub

# Di workflow, cukup referensikan environment:
jobs:
  apply:
    environment: production  # <- Pipeline akan pause dan tunggu approval
    runs-on: ubuntu-latest
    steps:
      - name: Terraform Apply
        run: terraform apply tfplan

# Di GitHub UI, set:
# - Required reviewers: [nama reviewer]
# - Wait timer: 0 menit (atau lebih jika butuh waktu untuk siap-siap)
# - Deployment branches: main only
# GitLab: when: manual di job apply
apply:production:
  stage: apply
  script:
    - terraform apply tfplan
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual        # Butuh klik manual
      allow_failure: false
  environment:
    name: production
  # Di GitLab Settings > CI/CD > Protected Environments:
  # Hanya role tertentu yang bisa klik "play" untuk job ini

Pola 3: Atlantis — Pull Request Automation #

Atlantis adalah tool open-source yang berjalan sebagai server dan mengelola seluruh lifecycle Terraform melalui PR comment. Sangat populer untuk tim yang ingin workflow yang lebih terintegrasi.

CARA KERJA ATLANTIS:

  Developer buka PR → Atlantis otomatis jalankan terraform plan
  Output plan muncul di PR sebagai comment dari "atlantis" bot

  Untuk apply:
  Reviewer ketik di PR comment: atlantis apply
  Atlantis jalankan terraform apply dengan plan yang sudah di-review
  Atlantis post hasil apply ke PR comment
  Atlantis otomatis merge PR jika apply berhasil

KEUNTUNGAN ATLANTIS:
  - Workflow sepenuhnya di PR — tidak perlu buka UI lain
  - Locking otomatis — tidak bisa apply dua PR sekaligus untuk workspace yang sama
  - Audit trail lengkap di PR comment history
  - Support multi-directory — bisa handle banyak workspace sekaligus
# atlantis.yaml — konfigurasi di root repository
version: 3
projects:
  - name: production
    dir: infrastructure/environments/production
    workspace: default
    terraform_version: v1.7.0
    autoplan:
      when_modified:
        - "*.tf"
        - "*.tfvars"
        - "../../../modules/**/*.tf"
      enabled: true
    apply_requirements:
      - approved          # Butuh minimal 1 approval
      - mergeable         # PR tidak boleh ada conflict

Kapan Apply Boleh Otomatis #

Tidak semua apply harus melalui approval manual. Ada kondisi di mana otomatisasi penuh masuk akal.

APPLY OTOMATIS (tanpa manual approval) — AMAN jika:
  ✓ Hanya environment dev atau staging
  ✓ Perubahan hanya pada non-destructive resources (tambah resource baru)
  ✓ Ada test otomatis yang dijalankan setelah apply
  ✓ Tim kecil dengan tingkat kepercayaan tinggi
  ✓ Infrastruktur mudah di-recreate jika ada masalah

APPLY MANUAL (butuh approval) — WAJIB jika:
  ✗ Environment production
  ✗ Ada operasi destroy dalam plan (-/+ atau -)
  ✗ Perubahan pada resource stateful (database, state backend)
  ✗ Perubahan pada security configuration (IAM, security group)
  ✗ Tim besar atau tim yang masih dalam proses onboarding
# GitHub Actions: Auto-approve untuk dev, manual untuk production
jobs:
  apply-dev:
    if: contains(github.event.head_commit.message, '[dev]')
    environment: dev  # Tidak ada required reviewers
    steps:
      - run: terraform apply -auto-approve tfplan

  apply-production:
    if: github.ref == 'refs/heads/main'
    environment: production  # Required reviewers configured
    steps:
      - run: terraform apply tfplan

flowchart TD
    A["plan file"] --> B["Automation\nchecks"]
    B -->|"pass"| C["Team review"]
    B -->|"fail"| D["Reject"]
    C -->|"approve"| E["Apply"]
    C -->|"reject"| D

    style A fill:#3b82f6,stroke:#1e40af,color:#fff
    style B fill:#8b5cf6,stroke:#6d28d9,color:#fff
    style C fill:#f97316,stroke:#ea580c,color:#fff
    style D fill:#ef4444,stroke:#dc2626,color:#fff
    style E fill:#10b981,stroke:#059669,color:#fff

Automated Approval Gates #

Approval gates memastikan plan direview sebelum apply, bahkan di pipeline yang fully automated.

# GitHub Actions: Environment protection rules
jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - run: terraform plan -out=tfplan
      - uses: actions/upload-artifact@v4
        with:
          name: tfplan
          path: tfplan

  apply:
    needs: plan
    runs-on: ubuntu-latest
    environment: production  # Requires approval!
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: tfplan
      - run: terraform apply tfplan
flowchart LR
    A["Plan"] --> B["Upload
artifact"]
    B --> C["Approval
Gate"]
    C -->|"Approved"| D["Apply"]
    C -->|"Rejected"| E["Cancel"]

    style A fill:#e3f2fd,stroke:#1565c0
    style C fill:#fff3e0,stroke:#e65100
    style D fill:#e8f5e9,stroke:#2e7d32
    style E fill:#ffebee,stroke:#c62828

Approval Audit Trail #

# Pastikan semua approval tercatat untuk compliance

# GitHub Actions: approval events di audit log
# Organization Settings → Audit log → filter: "environment_protection_rule"

# Terraform Cloud: approval di recorded di run history
# Setiap run mencatat: siapa yang approve, kapan, comment

# Custom: kirim approval event ke audit system
# GitHub Actions: log approval
jobs:
  apply:
    environment: production
    steps:
      - name: Log approval
        run: |
          echo "Approved by: ${{ github.actor }}"
          echo "Run ID: ${{ github.run_id }}"
          echo "Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
          # Kirim ke audit system          

Plan Review Checklist #

PLAN REVIEW CHECKLIST:

□ Semua perubahan SESUAI dengan yang diminta?
□ Tidak ada resource yang tidak sengaja terhapus?
□ Tidak ada sensitive value yang ter-ekspos di plan?
□ Cost impact masuk akal? (cek di Terraform Cloud/Infracost)
□ Security group tidak terbuka ke 0.0.0.0/0?
□ Database tidak memiliki deletion_protection = false?
□ Tag naming convention konsisten?
□ Tidak ada breaking change yang bisa downtime?

Auto-Apply Guardrails #

# JANGAN auto-apply di production!
# Tapi boleh auto-apply di dev dengan guardrails

# Terraform Cloud: per-workspace auto-apply setting
# Workspace dev: auto-apply enabled
# Workspace staging: auto-apply disabled
# Workspace production: auto-apply disabled + require approval

# Sentinel policy untuk guardrail
# policy/restrict-auto-apply.sentinel
import "tfplan/v2" as tfplan
import "tfrun" as tfrun

main = rule {
  tfrun.workspace.name is not "production" or
  all tfplan.resource_changes as _, rc {
    not (rc.change.actions contains "delete")
  }
}

Ringkasan #

  • PR-based approval adalah pola yang paling umum — plan otomatis di-post ke PR, reviewer melihat dampak, approval merge = authorization untuk apply.
  • Gunakan tfplan yang sama antara review dan apply — jangan plan ulang saat apply, kondisi infrastruktur bisa berubah di antara keduanya.
  • Environment protection rules di GitHub/GitLab memungkinkan approval di level workflow, bukan hanya di level PR — cocok untuk pipeline yang lebih kompleks.
  • Atlantis adalah solusi yang lebih terintegrasi — seluruh workflow Terraform (plan, review, apply) terjadi melalui PR comment tanpa perlu buka UI lain.
  • Apply otomatis aman untuk dev dan staging, tapi production selalu butuh approval — terutama jika ada operasi destroy atau perubahan security.
  • Audit trail adalah manfaat tersembunyi dari approval strategy yang baik — Git history mencatat siapa yang authorize setiap perubahan infrastruktur.

← Sebelumnya: CI Pipeline   Berikutnya: Automated Apply →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact