Belajar Secret Management - Integrasi OpenBao dengan Kubernetes
Episode 12 of 21

Belajar Secret Management - Integrasi OpenBao dengan Kubernetes

Menggabungkan OpenBao dengan Kubernetes: otentikasi ServiceAccount lewat auth/kubernetes, injeksi sidecar otomatis melalui mutation webhook, serta sinkronisasi rahasia menjadi native Kubernetes Secrets.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 11 kalian berkenalan dengan OpenBao Agent dan template-nya untuk merender file konfigurasi berisi rahasia. Episode 12 membawa Agent ke lingkungan yang paling sering menghuninya, yaitu Kubernetes. Kita membahas tiga hal: bagaimana Pod mengautentikasi dirinya ke OpenBao lewat auth/kubernetes, bagaimana mutation webhook menginjeksi sidecar Agent secara otomatis, dan bagaimana rahasia disinkronkan menjadi native Kubernetes Secrets.

Kubernetes Authentication Method (auth/kubernetes)

Pada dasarnya, auth/kubernetes adalah metode yang memungkinkan sebuah Pod membuktikan identitasnya tanpa password manusia. Identitas itu diambil dari ServiceAccount yang melekat pada Pod.

Bagaimana Otentikasi ServiceAccount JWT Bekerja

Setiap ServiceAccount di Kubernetes memiliki JWT yang dipasang di dalam Pod pada /var/run/secrets/kubernetes.io/serviceaccount/token. Alur otentikasinya seperti ini:

  1. Aplikasi di dalam Pod mengirimkan JWT ServiceAccount ke endpoint login OpenBao.
  2. OpenBao memvalidasi JWT tersebut ke Kubernetes API server menggunakan mekanisme TokenReview.
  3. Setelah valid, OpenBao memetakan kombinasi ServiceAccount dan namespace ke sebuah role.
  4. Role tersebut menentukan policy yang berlaku, sehingga Pod hanya memperoleh akses yang disetujui.

Karena validasi dilakukan oleh API server, OpenBao perlu tahu bagaimana menghubungi API server dan otoritas yang dipercaya. Informasi inilah yang dikonfigurasi pada mount auth method.

Mengaktifkan auth/kubernetes

Pertama, aktifkan metode autentikasi:

Mengaktifkan kubernetes auth method
bao auth enable kubernetes

Kemudian hubungkan metode ini dengan klaster:

Konfigurasi koneksi ke Kubernetes API server
bao write auth/kubernetes/config \
  kubernetes_host=https://kubernetes.default.svc \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
  token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token

kubernetes_host adalah alamat API server klaster, kubernetes_ca_cert adalah sertifikat CA untuk memverifikasi koneksi TLS, dan token_reviewer_jwt adalah JWT milik ServiceAccount yang memiliki izin untuk melakukan TokenReview.

Menyusun Role dan Policy

Role menjadi jembatan antara identitas Pod dan policy. Perintah berikut membuat role yang mengikat ServiceAccount bernama app di namespace default ke policy app-readonly:

Membuat role untuk ServiceAccount aplikasi
bao write auth/kubernetes/role/app \
  bound_service_account_names=app \
  bound_service_account_namespaces=default \
  policies=app-readonly \
  ttl=1h

Tip

Semua perintah di atas cukup dijalankan sekali oleh administrator. Saat Pod login, OpenBao hanya perlu menerima JWT ServiceAccount — misalnya bao login -method=kubernetes — dan token aplikasi keluar secara otomatis. Tidak ada kredensial permanen yang disimpan di gambar container.

OpenBao Agent Sidecar Injector

Menjalankan Agent secara manual di tiap Pod itu merepotkan dan mudah terlewat. Sidecar Injector mengotomatiskan seluruh proses melalui mutation webhook: cukup tambahkan beberapa annotation, dan webhook menyisipkan container Agent saat Pod diciptakan.

Prinsip Mutation Webhook

Injector memasang mutating webhook yang mendengarkan peristiwa pembuatan Pod. Saat menemukan annotation openbao.org/agent-inject: "true", webhook memodifikasi spec Pod secara transparan: menambahkan container Agent, menambahkan volume bersama, lalu memasang init container yang mengambil token. Dari sudut pandang aplikasi, tidak ada yang berubah — aplikasi hanya melihat file rahasia muncul di direktori yang disepakati.

Konfigurasi Melalui Annotations

KubernetesDeployment dengan annotation agent injector
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  template:
    metadata:
      annotations:
        openbao.org/agent-inject: "true"
        openbao.org/agent-inject-secret-config: "secret/data/app"
        openbao.org/role: "app"
        openbao.org/agent-inject-template-config: |
          {{- with secret "secret/data/app" -}}
          DB_PASSWORD={{ .Data.data.db_password }}
          {{- end }}

Annotation pertama menyalakan injeksi, openbao.org/agent-inject-secret-config menunjuk path rahasia yang dimuat, dan template ditulis lewat annotation yang nama akhiran -template-config. Untuk role, tulis nama role auth Kubernetes yang sudah dibuat sebelumnya.

Rahasia di Shared Volume In-Memory

Hasil render disimpan di shared volume berbasis emptyDir dengan medium Memory. Pathnya mengikuti nama annotation rahasia, yaitu /bao/secrets/config. Karena volume ini berada di memori, rahasia tidak pernah ditulis ke disk dan otomatis hilang saat Pod berhenti. Saat rahasia di OpenBao berubah, Agent memperbarui file dan memberi tanda; aplikasi yang membaca file cukup menunggu pembaruan berikutnya.

Important

Pastikan token ServiceAccount yang dipakai aplikasi hanya memiliki policy seperlunya. Sidecar in-memory memang aman dari sisi disk, tetapi policy yang terlalu longgar tetap membuka pintu bagi Pod lain yang diretas. Prinsip least privilege berlaku di lapisan mana pun, termasuk di sini.

Sidecar Injector vs Native Secret Sync

AspekSidecar InjectorNative Kubernetes Secrets Sync
MekanismeMutation webhook menambahkan container AgentKomponen sink menulis objek Secret
Media rahasiaVolume in-memory /bao/secrets/configObjek Secret yang disimpan di etcd
Siklus hidupHilang otomatis saat Pod matiTetap ada sampai dihapus
RotasiFile di-update langsung oleh AgentSecret perlu di-update dan Pod perlu reload
Kebutuhan ekstraWebhook injector terpasang di klasterKontroller sink berjalan di klaster

Keduanya sah, tetapi untuk kasus di mana aplikasi tidak bisa diubah, sidecar in-memory lebih unggul karena aplikasi tetap membaca file biasa. Sinkronisasi native dipilih saat ekosistem di sekitar kalian bergantung pada objek Secret standar Kubernetes, misalnya Helm chart atau operator lain.

Sinkronisasi ke Native Kubernetes Secrets

Jika sebagian komponen hanya memahami objek Secret standar, sinkronisasi menjadi jalan keluarnya. Rahasia dibaca dari OpenBao lalu ditulis sebagai objek Secret:

Native Kubernetes Secret hasil sinkronisasi
apiVersion: v1
kind: Secret
metadata:
  name: app-db
type: Opaque
stringData:
  db_password: "nilai-rahasia-dari-openbao"

Perhatikan trade-off-nya: begitu rahasia masuk ke objek Secret, ia disimpan di etcd dan tidak lagi "hidup" mengikuti rotasi di OpenBao, kecuali sink terus memperbaruinya. Untuk keamanan paling ketat, utamakan sidecar in-memory; gunakan sink native hanya ketika memang diperlukan oleh ekosistem.

Penutup

Pada episode 12 ini, kalian memahami otentikasi ServiceAccount JWT lewat auth/kubernetes, konfigurasi kubernetes_host dan token_reviewer_jwt, penyusunan role yang menghubungkan Pod dengan policy, injeksi sidecar Agent via mutation webhook dengan annotation openbao.org/agent-inject, rahasia pada volume in-memory /bao/secrets/config, serta sinkronisasi ke native Kubernetes Secrets.

Inti yang harus dibawa pulang:

  • Pod membuktikan identitasnya dengan ServiceAccount JWT, bukan password manusia.
  • Mutation webhook mengubah spec Pod secara transparan; aplikasi tidak perlu diubah.
  • Rahasia sidecar hidup di memori dan hilang bersama Pod — paling aman untuk disk.
  • Sink native memudahkan ekosistem yang memakai objek Secret, tetapi menambah tanggung jawab rotasi.

Di episode 13 berikutnya, kita keluar dari klaster dan masuk ke dunia pipeline: integrasi OpenBao dengan GitHub Actions dan GitLab CI untuk menghapus long-lived secrets dari repository.

Belajar Secret Management - Integrasi OpenBao dengan Kubernetes | Belajar Secret Management dengan OpenBao