Secret #

Secret adalah resource Kubernetes untuk menyimpan data sensitif — password, token, certificate, SSH key. Secara struktural mirip dengan ConfigMap, tapi Secret dirancang khusus untuk data yang tidak boleh muncul di log, tidak boleh ter-ekspos sembarangan, dan idealnya dienkripsi saat disimpan. Memahami cara kerja Secret dan batasannya penting untuk menghindari false sense of security.

Perbedaan Secret dan ConfigMap #

ConfigMap:
  → Data konfigurasi non-sensitif
  → Disimpan sebagai plaintext di Etcd
  → Tampil sebagai plaintext di kubectl get/describe
  → Cocok untuk: URL, hostname, feature flags, app settings

Secret:
  → Data sensitif
  → Disimpan sebagai base64 di Etcd (bukan terenkripsi secara default!)
  → Tidak tampil di kubectl describe (hanya tampil ukuran)
  → Cocok untuk: password, API key, token, TLS certificate, SSH key
Base64 bukan enkripsi. Data dalam Secret hanya di-encode base64, bukan dienkripsi. Siapapun yang bisa akses Etcd atau punya permission kubectl get secret bisa membaca nilai Secret. Untuk keamanan yang sesungguhnya, aktifkan enkripsi at-rest dan batasi akses via RBAC.

Tipe Secret #

Kubernetes mendefinisikan beberapa tipe Secret dengan validasi masing-masing:

# Opaque (default) — key-value bebas, paling umum
type: Opaque

# TLS certificate dan private key
type: kubernetes.io/tls

# Docker registry credentials
type: kubernetes.io/dockerconfigjson

# Service account token
type: kubernetes.io/service-account-token

# Basic authentication
type: kubernetes.io/basic-auth

# SSH authentication
type: kubernetes.io/ssh-auth

Membuat Secret #

# Dari literal (nilai otomatis di-encode base64)
kubectl create secret generic db-credentials \
  --from-literal=username=appuser \
  --from-literal=password=S3cur3P@ssw0rd

# Dari file (berguna untuk certificate)
kubectl create secret tls tls-cert \
  --cert=server.crt \
  --key=server.key

# Dari file credentials Docker registry
kubectl create secret docker-registry registry-cred \
  --docker-server=registry.example.com \
  --docker-username=myuser \
  --docker-password=mypassword
# Dari manifest (nilai harus di-encode base64 manual)
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: production
type: Opaque
data:
  username: YXBwdXNlcg==        # base64("appuser")
  password: UzNjdXIzUEBzc3cwcmQ=  # base64("S3cur3P@ssw0rd")
# Encode nilai ke base64
echo -n "appuser" | base64
# -n penting untuk menghindari newline yang ikut ter-encode

Menggunakan Secret sebagai Environment Variable #

spec:
  containers:
  - name: api
    image: my-api:v2
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-credentials
          key: password

    # Atau inject semua key sekaligus
    envFrom:
    - secretRef:
        name: db-credentials

Menggunakan Secret sebagai Volume #

spec:
  volumes:
  - name: tls-certs
    secret:
      secretName: tls-cert
      defaultMode: 0400      # read-only untuk owner, tidak untuk group/others

  containers:
  - name: nginx
    image: nginx:1.25
    volumeMounts:
    - name: tls-certs
      mountPath: /etc/ssl/certs
      readOnly: true

File Secret di dalam container disimpan di tmpfs (memory filesystem), bukan di disk node — lebih aman karena tidak ada jejak di disk.


Secret untuk Image Pull #

Untuk pull image dari private registry:

spec:
  imagePullSecrets:
  - name: registry-cred   # nama Secret tipe docker-registry

  containers:
  - name: app
    image: registry.example.com/myapp:v2

Enkripsi at-Rest #

Secara default, Secret di Etcd hanya di-encode base64, bukan dienkripsi. Untuk mengaktifkan enkripsi sesungguhnya:

# EncryptionConfiguration — konfigurasi di API Server
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:          # enkripsi AES-CBC
      keys:
      - name: key1
        secret: <base64-encoded-32-byte-key>
  - identity: {}     # fallback untuk baca secret lama yang belum terenkripsi

Di cloud managed Kubernetes, enkripsi at-rest biasanya tersedia sebagai fitur yang bisa diaktifkan:

# GKE: aktifkan Application-layer Secret encryption
gcloud container clusters update CLUSTER_NAME \
  --database-encryption-key projects/PROJECT/locations/REGION/keyRings/RING/cryptoKeys/KEY

# EKS: aktifkan envelope encryption
aws eks update-cluster-config \
  --name CLUSTER_NAME \
  --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws:kms:......"}}]'

Risiko Keamanan yang Sering Diabaikan #

1. Secret di environment variable bisa bocor via:
   → Crash dump / core dump yang menyertakan env var
   → Debug endpoint yang expose process environment
   → Log aplikasi yang secara tidak sengaja print env var
   → `kubectl exec` ke Pod dan jalankan `env`

2. Secret di volume lebih aman, tapi:
   → Aplikasi yang meng-cache nilai masih expose di memory
   → Log yang print nilai file konfigurasi tetap berbahaya

3. Secret dalam source code atau Git:
   → JANGAN pernah commit Secret ke Git, meskipun di-encode base64
   → Gunakan .gitignore untuk file yang berisi Secret
   → Tools seperti git-secrets atau truffleHog untuk scan

4. RBAC yang longgar:
   → Siapapun dengan permission get/list secrets bisa baca semua Secret
   → Batasi permission Secret via RBAC yang ketat

Praktik Terbaik #

Untuk Secret management di produksi:

1. Aktifkan enkripsi at-rest (via KMS atau EncryptionConfiguration)

2. Batasi akses via RBAC:
   → Principle of least privilege
   → Service account Pod hanya bisa akses Secret yang benar-benar dibutuhkan
   → Audit siapa yang bisa kubectl get secrets

3. Rotasi Secret secara berkala:
   → Terutama untuk database password dan API key
   → Otomatisasi dengan external secret manager

4. Gunakan external secret manager untuk produksi kritikal:
   → AWS Secrets Manager + External Secrets Operator
   → HashiCorp Vault + Vault Agent Injector
   → GCP Secret Manager + External Secrets Operator
   → Secret value dikelola di luar cluster, disync ke Kubernetes Secret

5. Jangan log nilai Secret:
   → Pastikan konfigurasi logging aplikasi tidak print env var atau config file
   → Redact sensitive fields di log aggregation pipeline

Ringkasan #

  • Base64 bukan enkripsi — Secret hanya di-encode, bukan dilindungi; untuk keamanan nyata aktifkan enkripsi at-rest dan batasi akses via RBAC.
  • Volume mount lebih aman dari env var — file Secret disimpan di tmpfs (memory), tidak ada jejak di disk; env var bisa bocor via log atau debug endpoint.
  • Tipe Secret untuk validasi yang tepat — gunakan kubernetes.io/tls untuk certificate, kubernetes.io/dockerconfigjson untuk registry; Kubernetes validasi format sesuai tipe.
  • Enkripsi at-rest wajib untuk produksi kritikal — aktifkan via KMS di cloud managed cluster; untuk on-premise, konfigurasi EncryptionConfiguration di API Server.
  • External secret manager untuk produksi skala besar — AWS Secrets Manager, HashiCorp Vault, atau GCP Secret Manager dikelola lebih professional untuk rotasi, audit, dan akses control.
  • Jangan commit Secret ke Git meski dalam base64 — base64 mudah di-decode; gunakan git-secrets atau truffleHog untuk scan repository dari kebocoran Secret.

← Sebelumnya: ConfigMap   Berikutnya: Environment Variable Pattern →

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