Credential Rotation Strategy #

Credential yang tidak pernah dirotasi adalah credential yang suatu saat akan dikompromikan tanpa ada yang menyadarinya — atau jika ada yang menyadarinya, sudah terlambat. Di ekosistem Terraform, ada dua jenis credential yang perlu strategi rotasi: credentials yang digunakan oleh Terraform sendiri (provider credentials), dan credentials yang dikelola oleh Terraform untuk aplikasi (database password, API key). Kedua jenis ini punya cara rotasi yang berbeda, dan Terraform bisa membantu maupun menghambat proses ini tergantung cara kamu mendesainnya.

Rotasi Provider Credentials (CI/CD) #

Credentials yang digunakan oleh Terraform dan CI/CD pipeline untuk mengakses cloud adalah yang paling kritis untuk dirotasi secara rutin.

STRATEGI ROTASI BERDASARKAN JENIS CREDENTIALS:

OIDC Tokens (GitHub Actions, GitLab CI):
  - Tidak perlu rotasi manual
  - Token di-generate fresh setiap pipeline run
  - Expire otomatis dalam 1 jam
  ✓ Cara ini tidak ada credentials yang perlu dirotasi

AWS SSO / IAM Identity Center:
  - Session token expire otomatis (8-12 jam default)
  - Admin bisa revoke session kapan saja
  - Rotasi efektif hanya perlu ganti SSO assignment
  ✓ Jauh lebih mudah dari rotasi static credentials

Static Access Key (IAM User):
  - Perlu dirotasi secara berkala (minimal tiap 90 hari)
  - Rotasi manual: buat key baru → update secret → hapus key lama
  - Rawan human error dan downtime saat rotasi
  ✗ Hindari penggunaan ini di CI/CD
# Jika masih menggunakan static credentials, ini cara rotasi yang aman:

# 1. Buat access key baru (satu IAM user bisa punya 2 key sekaligus)
aws iam create-access-key --user-name terraform-ci-user
# Simpan key baru, belum hapus key lama

# 2. Update secret di GitHub Actions
gh secret set AWS_ACCESS_KEY_ID --body "NEWKEYID"
gh secret set AWS_SECRET_ACCESS_KEY --body "NEWSECRETKEY"

# 3. Verifikasi pipeline berjalan dengan credentials baru
# Jalankan pipeline dan pastikan berhasil

# 4. Nonaktifkan key lama dulu (belum hapus — masih bisa rollback)
aws iam update-access-key --access-key-id OLDKEYID --status Inactive --user-name terraform-ci-user

# 5. Setelah yakin key baru bekerja, hapus key lama
aws iam delete-access-key --access-key-id OLDKEYID --user-name terraform-ci-user

Rotasi Database Password dengan Zero Downtime #

Rotasi database password adalah salah satu yang paling tricky karena aplikasi yang sedang berjalan menggunakan password lama, dan selama rotasi ada jeda di mana password baru belum tersebar ke semua aplikasi.

MASALAH ROTASI DATABASE PASSWORD:

  Kondisi sebelum rotasi:
  Password lama: "OldP4ssword"
  Aplikasi A: menggunakan "OldP4ssword" ← berjalan normal
  Aplikasi B: menggunakan "OldP4ssword" ← berjalan normal

  Saat rotasi:
  Step 1: Terraform apply — ubah password DB ke "NewP4ssword"
    → Semua koneksi dengan password lama GAGAL
    → Aplikasi A dan B: connection error!

  Step 2: Update Kubernetes secret / SSM Parameter
    → Butuh restart pod untuk aplikasi mendapat password baru
    → Ada downtime selama restart

  Ini adalah masalah "big bang rotation" yang berbahaya.
SOLUSI: DUAL-PASSWORD ROTATION (Zero Downtime)

  AWS Secrets Manager mendukung ini secara native:

  Phase 1: Create new secret
    Password baru dibuat, tapi password lama masih berlaku di DB
    Aplikasi masih pakai password lama

  Phase 2: Set pending
    Password baru sudah ada di Secrets Manager
    Aplikasi belum menggunakannya

  Phase 3: Test new secret
    Verifikasi password baru bisa koneksi ke DB

  Phase 4: Finish rotation
    Password lama dinonaktifkan di DB
    Aplikasi yang refresh credentials akan mendapat password baru

  Kunci: Aplikasi harus mendukung dynamic credential refresh
  (baca dari Secrets Manager setiap request, bukan hanya saat startup)
# Konfigurasi automatic rotation di AWS Secrets Manager via Terraform

resource "aws_secretsmanager_secret" "db_password" {
  name = "prod/database/master-password"

  # Rotasi otomatis setiap 30 hari
  rotation_rules {
    automatically_after_days = 30
  }
}

resource "aws_secretsmanager_secret_rotation" "db_rotation" {
  secret_id           = aws_secretsmanager_secret.db_password.id
  rotation_lambda_arn = aws_lambda_function.db_rotation.arn

  rotation_rules {
    automatically_after_days = 30
  }
}

# Untuk RDS, gunakan managed rotation yang disediakan AWS
# (lebih mudah dari Lambda custom)
resource "aws_db_instance" "main" {
  identifier = "production-db"
  # ...

  manage_master_user_password   = true
  master_user_secret_kms_key_id = aws_kms_key.rds.arn
}

resource "aws_secretsmanager_secret_rotation" "rds_rotation" {
  secret_id           = aws_db_instance.main.master_user_secret[0].secret_arn
  rotate_immediately  = false

  rotation_rules {
    automatically_after_days = 30
    # Atau gunakan schedule_expression untuk rotasi di waktu tertentu:
    # schedule_expression = "cron(0 2 1 * ? *)"  # Jam 2 pagi, tanggal 1 tiap bulan
  }
}

Rotasi API Key untuk Third-Party Services #

# Pola untuk rotasi API key yang digunakan Terraform
# (misalnya: Cloudflare API token, Datadog API key)

# ANTI-PATTERN: API key langsung di provider
provider "cloudflare" {
  api_token = "secret-token-that-never-rotates"
}

# BENAR: Baca dari Secrets Manager, token bisa dirotasi tanpa ubah konfigurasi
data "aws_secretsmanager_secret_version" "cloudflare_token" {
  secret_id = "prod/cloudflare/api-token"
}

provider "cloudflare" {
  api_token = jsondecode(data.aws_secretsmanager_secret_version.cloudflare_token.secret_string)["token"]
}

# Cara rotasi:
# 1. Buat API token baru di Cloudflare
# 2. Update secret di Secrets Manager
#    aws secretsmanager put-secret-value --secret-id prod/cloudflare/api-token --secret-string '{"token":"newtoken"}'
# 3. Jalankan terraform plan/apply — akan menggunakan token baru
# 4. Hapus token lama di Cloudflare setelah verify berhasil

Mencegah Rotasi yang Tidak Perlu via ignore_changes #

Terraform perlu tahu bahwa beberapa credential akan berubah di luar Terraform (dirotasi oleh Secrets Manager atau eksternal), dan tidak perlu mencoba “mengembalikan” ke nilai lama.

resource "aws_db_instance" "main" {
  identifier = "production-db"
  username   = "admin"
  password   = var.initial_db_password

  lifecycle {
    # Abaikan perubahan password — password akan dirotasi di luar Terraform
    # oleh Secrets Manager rotation Lambda
    ignore_changes = [password]
  }
}

# Dengan ignore_changes, Terraform tidak akan:
# - Mendeteksi perubahan password sebagai drift
# - Mencoba mengembalikan password ke nilai awal saat plan
# Password sepenuhnya dikelola di luar Terraform setelah initial setup

Ringkasan #

  • OIDC adalah cara terbaik untuk CI/CD — token di-generate fresh setiap run dan expire otomatis, tidak ada yang perlu dirotasi secara manual.
  • Rotasi static credentials butuh dua langkah: buat key baru → update pipeline → verifikasi → nonaktifkan key lama → hapus. Jangan langsung hapus tanpa verifikasi.
  • “Big bang rotation” database password menyebabkan downtime — gunakan dual-password rotation via AWS Secrets Manager managed rotation yang didukung native oleh RDS.
  • Automatic rotation di Secrets Manager adalah solusi terbaik untuk database dan service credentials — AWS mengelola Lambda rotation function dan timeline.
  • ignore_changes = [password] di lifecycle block mencegah Terraform mencoba “mengembalikan” password yang sudah dirotasi oleh Secrets Manager.
  • Baca credentials dari Secrets Manager di provider config alih-alih hardcode — memungkinkan rotasi credentials provider tanpa mengubah konfigurasi Terraform.

← Sebelumnya: Environment & Secret   Berikutnya: Secret Exposure Risk →

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