External Secret Manager #

Penyimpanan data rahasia (secrets) secara bawaan di Kubernetes memiliki keterbatasan operasional yang serius untuk kebutuhan infrastruktur skala enterprise. Di lingkungan kluster skala besar, kita dituntut untuk mengelola ratusan kredensial yang tersebar di puluhan namespace dan beberapa kluster berbeda. Jika kita hanya mengandalkan Kubernetes Secret native: kita akan kehilangan kemampuan pelacakan audit terpusat, tidak memiliki fitur rotasi kredensial otomatis, tidak ada riwayat versi (secret versioning), serta rentan terhadap kesalahan manusia jika data sensitif ter-commit ke dalam repositori GitOps.

Untuk mengatasi kesenjangan keamanan ini, industri modern mengadopsi pola integrasi dengan External Secret Manager—seperti AWS Secrets Manager, Google Cloud Secret Manager, Azure Key Vault, atau HashiCorp Vault. Sistem eksternal ini dirancang khusus dengan fitur kriptografi perangkat keras (HSM), audit log super ketat, rotasi kredensial otomatis, dan pemisahan wewenang (separation of duties). Artikel ini mengupas tuntas arsitektur pengelola rahasia eksternal, implementasi menggunakan External Secrets Operator (ESO), dan panduan memilih solusi yang tepat untuk kluster produksi kita.


Kebutuhan Integrasi Rahasia Eksternal #

Beralih dari Kubernetes Secret native ke solusi eksternal terkelola memberikan peningkatan keamanan yang signifikan bagi ekosistem produksi.

Mari kita perhatikan tabel perbandingan komparatif di bawah ini untuk melihat perbedaannya secara mendalam:

Fitur Kubernetes Secret Native External Secret Manager
Penyimpanan Utama etcd (Database kluster internal). Database terdedikasi terenkripsi HSM.
Audit Logs Terbatas (Hanya melacak request API Server). Lengkap (Melacak siapa, kapan, dari mana secara detail).
Rotasi Kredensial Manual (Membutuhkan deploy ulang). Otomatis (Terintegrasi fungsi serverless/engine).
Manajemen Lintas Kluster Terisolasi per kluster. Terpusat (Satu sumber data untuk banyak kluster).
Versioning Rahasia Tidak ada versioning native. Mendukung pemulihan riwayat versi sebelumnya.
Dynamic Credentials Static credentials saja. Mendukung pembuatan kredensial sementara (on-demand).

Arsitektur dan Cara Kerja External Secrets Operator (ESO) #

Untuk menghubungkan sumber data dari pengelola rahasia eksternal ke dalam Kubernetes, kita membutuhkan agen sinkronisasi aktif. Standar de facto industri saat ini adalah menggunakan External Secrets Operator (ESO). ESO adalah operator Kubernetes berbasis custom controller yang secara berkala memantau perubahan rahasia di cloud provider, lalu menulis ulang nilainya secara aman ke dalam objek Kubernetes Secret lokal.

Mari kita pelajari alur sinkronisasi data dinamis yang dilakukan oleh ESO di dalam kluster melalui diagram berikut:

flowchart TD
    subgraph ExternalProvider["Cloud Secret Provider"]
        AWS_SM["AWS Secrets Manager / GCP SM / Vault"]
    end

    subgraph K8sCluster["Kubernetes Cluster Boundary"]
        ESO["External Secrets Operator Controller"]
        SecretStore["SecretStore / ClusterSecretStore"]
        ExtSecret["ExternalSecret Resource"]
        K8sSecret["Kubernetes Secret (Target)"]
        Pod["Pod Aplikasi Kontainer"]
        
        SecretStore -.->|"Menyediakan Autentikasi IAM / JWT"| AWS_SM
        ExtSecret -->|"Merujuk Rantai Autentikasi"| SecretStore
        ESO -->|"Watch Perubahan"| ExtSecret
        ESO -->|"1. Tarik Data Rahasia Baru"| AWS_SM
        ESO -->|"2. Tulis & Sinkronkan Data"| K8sSecret
        K8sSecret -->|"3. Dikonsumsi Runtime"| Pod
    end

ESO menggunakan dua Custom Resource Definitions (CRD) utama:

  1. SecretStore / ClusterSecretStore: Mendefinisikan koneksi dan metode autentikasi ke cloud provider. SecretStore terikat pada namespace tertentu, sedangkan ClusterSecretStore bersifat global dan dapat digunakan oleh semua namespace di kluster.
  2. ExternalSecret: Mendefinisikan pemetaan kunci (key mapping) rahasia mana yang ingin ditarik dari cloud provider dan nama objek Kubernetes Secret target yang ingin dihasilkan.

Integrasi Mendalam dengan AWS Secrets Manager #

Bagi kluster yang berjalan di AWS (EKS), kita dapat memanfaatkan metode autentikasi IAM Roles for Service Accounts (IRSA) untuk menghubungkan ESO ke AWS Secrets Manager tanpa perlu menyimpan kredensial statis (AWS Access Key ID / Secret Access Key) di dalam kluster.

Perbandingan Autentikasi Sinkronisasi AWS #

Berikut adalah perbedaan antara mengonfigurasi koneksi menggunakan kunci statis yang berbahaya (anti-pattern) dengan autentikasi berbasis peran IAM Role dinamis (solusi):

# ANTI-PATTERN: Menggunakan AWS Access Keys statis di dalam manifest
# ✗ Sangat berbahaya karena kunci akses admin AWS terekspos di dalam kluster
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-store-unsafe
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-southeast-1
      auth:
        secretRef:
          awsAccessKeyID:
            name: static-aws-creds  # Kunci statis yang berisiko bocor
            key: access_key
          awsSecretAccessKey:
            name: static-aws-creds
            key: secret_key
---
# BENAR: Terapkan autentikasi IRSA (IAM Roles for Service Accounts)
# ✓ Tanpa kunci statis, akses diotorisasi melalui federasi token OIDC dinamis
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secrets-manager-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-southeast-1
      auth:
        jwt:
          # Menggunakan token dinamis ServiceAccount yang terikat Peran IAM AWS
          serviceAccountRef:
            name: external-secrets-operator-sa
            namespace: external-secrets

Setelah ClusterSecretStore terbentuk, kita dapat membuat objek ExternalSecret untuk memetakan parameter database rahasia dari AWS Secrets Manager ke dalam namespace aplikasi:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: billing-db-secret
  namespace: billing
spec:
  refreshInterval: "1h"  # Lakukan kueri sinkronisasi setiap 1 jam
  secretStoreRef:
    name: aws-secrets-manager-store
    kind: ClusterSecretStore
  target:
    name: billing-postgres-creds  # Nama Kubernetes Secret lokal yang akan dibuat
    creationPolicy: Owner
  data:
  - secretKey: username
    remoteRef:
      key: production/billing/db
      property: db_username
  - secretKey: password
    remoteRef:
      key: production/billing/db
      property: db_password

Integrasi Mendalam dengan HashiCorp Vault #

HashiCorp Vault merupakan salah satu pengelola rahasia yang paling populer karena dukungannya yang matang terhadap arsitektur multi-cloud. Integrasi ESO dengan Vault biasanya menggunakan metode autentikasi Kubernetes Auth Method di mana Vault memverifikasi token JWT milik ServiceAccount Kubernetes.

Manifest Konfigurasi SecretStore untuk HashiCorp Vault #

Berikut adalah contoh manifest SecretStore yang dikonfigurasi untuk terhubung ke kluster Vault eksternal:

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: vault-backend-store
  namespace: production
spec:
  provider:
    vault:
      server: "https://vault.internal.example.com:8200"
      path: "secret"  # Mount path KV secrets engine di Vault
      version: "v2"   # Menggunakan KV version 2 (dengan versioning)
      auth:
        kubernetes:
          mountPath: "kubernetes"  # Path auth method di Vault
          role: "production-app-role"  # Role yang dicocokkan di Vault
          serviceAccountRef:
            name: app-service-account  # ServiceAccount lokal Pod

Fitur Unggulan: Dynamic Secrets Engine #

Salah satu keunggulan terbesar HashiCorp Vault dibandingkan cloud-native secret manager adalah kemampuannya untuk menghasilkan kredensial dinamis (Dynamic Secrets).

Ketika kontainer meminta akses database melalui Vault, Vault tidak mengembalikan kata sandi database admin yang statis. Vault akan secara otomatis membuat pengguna (user) database baru dengan kata sandi acak di server PostgreSQL target, memberikan hak akses minimal, dan menetapkan batas waktu aktif (TTL / Time to Live, misalnya 1 jam). Begitu TTL berakhir, Vault akan secara otomatis menghapus pengguna tersebut dari server database.

# Manifes ESO untuk mengambil Dynamic Credentials dari Vault
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: dynamic-db-creds
  namespace: production
spec:
  refreshInterval: "45m"  # Tarik ulang kredensial baru sebelum TTL 1 jam berakhir
  secretStoreRef:
    name: vault-backend-store
    kind: SecretStore
  target:
    name: dynamic-db-secret
  data:
  - secretKey: db-username
    remoteRef:
      key: database/creds/read-only-role  # Path dynamic database engine
      property: username
  - secretKey: db-password
    remoteRef:
      key: database/creds/read-only-role
      property: password

Pola ini sangat tangguh dalam menekan risiko peretasan, karena tidak ada kata sandi database permanen yang tersimpan di dalam berkas konfigurasi kluster kita.


Integrasi dengan Google Cloud (GCP) Secret Manager #

Di lingkungan Google Kubernetes Engine (GKE), kita mengintegrasikan sinkronisasi menggunakan metode Workload Identity. Workload Identity memetakan Kubernetes ServiceAccount secara langsung ke Google Service Account (GSA) tingkat GCP IAM.

1. ClusterSecretStore untuk GCP Secret Manager #

Berikut adalah manifes konfigurasi integrasi GCP Secret Manager menggunakan Workload Identity:

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: gcp-secret-store
spec:
  provider:
    gcpsm:
      projectID: "my-gcp-production-project"
      auth:
        workloadIdentity:
          clusterLocation: asia-southeast1
          clusterName: gke-prod-cluster
          serviceAccountRef:
            name: eso-gcp-sync-sa
            namespace: external-secrets

2. ExternalSecret untuk GCP Secret Manager #

Setelah ClusterSecretStore aktif, kita dapat menarik data rahasia dari GCP Secret Manager menggunakan manifes berikut:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: gcp-db-secret
  namespace: production
spec:
  refreshInterval: "1h"
  secretStoreRef:
    name: gcp-secret-store
    kind: ClusterSecretStore
  target:
    name: gcp-db-secret  # Nama Kubernetes Secret lokal yang dihasilkan
  data:
  - secretKey: db-password
    remoteRef:
      key: production-db-password  # Nama rahasia di GCP Secret Manager
      version: "latest"            # Versi rahasia (bisa ditentukan spesifik angka versi)

Integrasi dengan Azure Key Vault #

Bagi organisasi yang mengoperasikan infrastruktur di Microsoft Azure (AKS), kita dapat menyinkronkan data sensitif dari Azure Key Vault menggunakan metode autentikasi Azure AD Workload Identity.

1. SecretStore untuk Azure Key Vault #

Berikut adalah manifes SecretStore yang dikonfigurasi untuk menghubungkan namespace kita ke layanan Azure Key Vault:

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: azure-key-vault-store
  namespace: production
spec:
  provider:
    azurekv:
      tenantId: "12345678-abcd-1234-abcd-1234567890ab"  # Tenant ID Azure Directory Anda
      vaultUrl: "https://my-prod-key-vault.vault.azure.net"  # URL Azure Key Vault Anda
      auth:
        workloadIdentity:
          serviceAccountRef:
            name: eso-azure-sync-sa  # ServiceAccount lokal yang terikat dengan Azure Managed Identity

2. ExternalSecret untuk Azure Key Vault #

Gunakan manifes berikut untuk menarik rahasia (secrets) atau kunci (keys) dari Azure Key Vault dan mengubahnya menjadi Kubernetes Secret:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: azure-app-secret
  namespace: production
spec:
  refreshInterval: "1h"
  secretStoreRef:
    name: azure-key-vault-store
    kind: SecretStore
  target:
    name: local-azure-secret
  data:
  - secretKey: api-token
    remoteRef:
      key: production-api-token  # Nama rahasia di Azure Key Vault

Panduan Pemilihan Solusi Terbaik Berdasarkan Kebutuhan #

Setiap pengelola rahasia eksternal memiliki karakteristik performa, integrasi, dan biaya yang berbeda. Memilih solusi yang tidak sesuai dengan kebutuhan infrastruktur dapat meningkatkan kompleksitas operasional secara tidak perlu.

Mari kita pelajari pohon keputusan (decision tree) di bawah ini untuk menentukan pilihan solusi terbaik:

flowchart TD
    Start{"Mulai Evaluasi Pilihan"} --> IsMultiCloud{"Apakah Menggunakan Multi-Cloud / On-Premise?"}
    
    IsMultiCloud -- "Ya" --> UseVault["Pilihan Utama: HashiCorp Vault"]
    
    IsMultiCloud -- "Tidak" --> CloudProvider{"Di Mana Cluster Kubernetes Berjalan?"}
    CloudProvider -- "AWS (EKS)" --> UseAWS["Pilihan: AWS Secrets Manager"]
    CloudProvider -- "GCP (GKE)" --> UseGCP["Pilihan: GCP Secret Manager"]
    CloudProvider -- "Azure (AKS)" --> UseAzure["Pilihan: Azure Key Vault"]
    
    UseVault --> FeaturesVault["Kelebihan: Dynamic Secrets, PKI engine, Multi-Cloud"]
    UseAWS --> FeaturesAWS["Kelebihan: Auto-rotation RDS, KMS native integration"]
    UseGCP --> FeaturesGCP["Kelebihan: Workload Identity integration, hemat biaya"]

Berikut adalah ringkasan perbandingan karakteristik teknis untuk membantu proses pengambilan keputusan tim platform engineer:

  1. HashiCorp Vault:
    • Kelebihan: Sangat portabel, mendukung dynamic secrets, manajemen PKI otomatis, kontrol RBAC sangat kaya.
    • Kekurangan: Membutuhkan biaya operasional tinggi untuk instalasi, pemeliharaan backup cluster, dan operasional tim security policy.
  2. AWS Secrets Manager:
    • Kelebihan: Terkelola penuh (fully managed), integrasi bawaan dengan sistem rotasi otomatis database RDS, otorisasi native KMS.
    • Kekurangan: Vendor lock-in AWS, biaya per kueri API (API calls cost) cukup mahal jika refreshInterval ESO disetel terlalu agresif.
  3. GCP Secret Manager:
    • Kelebihan: Sangat sederhana, autentikasi tanpa password menggunakan Workload Identity, integrasi audit logging Cloud Logging.
    • Kekurangan: Fitur rotasi otomatis tidak sekaya AWS, vendor lock-in GCP.

Ringkasan #

  • Gunakan ESO sebagai standar sinkronisasi: Terapkan External Secrets Operator untuk menyinkronkan data sensitif dari luar ke dalam objek Secret kluster secara transparan dan konsisten.
  • Wajib gunakan autentikasi IRSA/Workload Identity: Hindari penulisan access keys statis di manifest YAML; gunakan token JWT dinamis yang diotorisasi oleh OIDC cloud provider.
  • Manfaatkan dynamic secrets untuk proteksi database: Gunakan fitur Dynamic Secrets Engine milik Vault untuk meminimalkan risiko pencurian kredensial database permanen.
  • Pilih solusi berdasarkan lingkungan kluster: Gunakan AWS Secrets Manager jika berjalan penuh di EKS, GCP Secret Manager di GKE, dan gunakan HashiCorp Vault untuk kebutuhan multi-cloud.
  • Atur parameter refreshInterval secara bijaksana: Jangan setel waktu sinkronisasi terlalu sering (misalnya setiap 5 detik) pada cloud-managed secrets manager untuk menghindari tagihan API calls cloud yang membengkak.
  • Pelihara prinsip separation of duties: Tim developer hanya boleh membuat manifes ExternalSecret, sedangkan konfigurasi koneksi ClusterSecretStore dikelola khusus oleh tim platform security.

← Sebelumnya: Secret Management Best Practice   Berikutnya: ConfigMap vs Secret →

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