RBAC (Role-Based Access Control) #
Dalam ekosistem Kubernetes, keamanan kluster sangat bergantung pada kemampuan kita untuk mengontrol siapa saja yang dapat berinteraksi dengan API Server dan tindakan apa saja yang diizinkan untuk mereka lakukan. Setelah sebuah permintaan (request) berhasil melewati tahap autentikasi (pembuktian identitas), permintaan tersebut harus melalui tahap otorisasi (pemeriksaan hak akses). Kubernetes menyediakan sistem otorisasi berbasis peran yang sangat tangguh dan granular, yaitu RBAC (Role-Based Access Control).
Menerapkan RBAC yang aman bukan sekadar masalah fungsionalitas agar aplikasi kita dapat berjalan, melainkan bagian dari fondasi zero-trust cluster. Konfigurasi RBAC yang terlalu permisif sering kali menjadi celah keamanan nomor satu yang dieksploitasi penyerang untuk melakukan pergerakan lateral (lateral movement) dan eskalasi hak istimewa (privilege escalation) setelah berhasil membobol satu Pod aplikasi. Artikel ini membedah arsitektur objek RBAC, perbedaan subjek akses, taktik merancang hak akses minimal (principle of least privilege), serta mitigasi risiko eskalasi hak akses di produksi.
Arsitektur Alur Request API Server #
Sebelum kita mempelajari objek-objek RBAC secara detail, mari kita pahami bagaimana API Server memproses setiap permintaan HTTP yang masuk melalui diagram urutan berikut:
sequenceDiagram
participant Client as Pengguna / Pod ServiceAccount
participant API as kube-apiserver
participant AuthN as Authentication Filter
participant AuthZ as Authorization Filter (RBAC)
participant Admin as Admission Controller
participant etcd as Cluster Storage (etcd)
Client->>API: HTTP Request (e.g., GET /api/v1/pods)
API->>AuthN: Verifikasi Kredensial (Token/Cert)
AuthN-->>API: Identitas Terverifikasi (User/Group/SA)
API->>AuthZ: Periksa Izin Akses (RBAC Engine)
Note over AuthZ: Evaluasi RoleBinding & Roles<br>terhadap Subject, Resource, & Verb
AuthZ-->>API: Akses Diizinkan (Allowed)
API->>Admin: Jalankan Admission Control (Mutating/Validating)
Admin-->>API: Request Diterima & Valid
API->>etcd: Tulis/Baca Data
etcd-->>API: Kembalikan Data
API-->>Client: HTTP Response 200 OK
Membedah Empat Komponen Utama RBAC #
Sistem RBAC Kubernetes dideklarasikan melalui hubungan relasional antara empat objek API utama: Subjects, Roles, ClusterRoles, RoleBindings, dan ClusterRoleBindings.
1. Subjects (Siapa yang Meminta Akses?) #
Subjek adalah entitas yang meminta akses ke API Server. Ada tiga kategori subjek di Kubernetes:
- ServiceAccount: Akun identitas yang dibuat di dalam kluster Kubernetes untuk digunakan oleh Pod aplikasi yang sedang berjalan. Ini adalah subjek yang paling sering kita kelola dalam penulisan manifest.
- User (Pengguna Manusia): Diidentifikasi menggunakan sertifikat eksternal (X.509 Client Certs) atau integrasi Identity Provider (OIDC/SSO). Kubernetes tidak memiliki database internal untuk menyimpan objek User.
- Group: Kumpulan subjek yang dikelompokkan secara logis, misalnya
system:serviceaccounts(seluruh ServiceAccount di kluster) atau grup LDAP perusahaan.
2. Roles vs ClusterRoles (Hak Akses Apa yang Diberikan?) #
Objek ini mendefinisikan daftar aturan izin (rules) yang memuat kombinasi API Groups, Resources, dan Verbs (tindakan seperti get, list, create, update, delete).
- Role: Bersifat lokal dan terisolasi pada satu namespace spesifik. Role hanya dapat digunakan untuk membatasi akses ke resource yang berada di dalam namespace tersebut (misalnya Pod, Service, ConfigMap).
- ClusterRole: Bersifat global tingkat cluster (non-namespaced). ClusterRole dapat digunakan untuk mengontrol akses ke resource tingkat cluster (seperti Node, PersistentVolume, Namespace) atau mengontrol akses ke resource namespaced di seluruh namespace yang ada di cluster secara seragam.
3. RoleBindings vs ClusterRoleBindings (Bagaimana Menghubungkannya?) #
Objek binding bertindak sebagai jembatan yang menghubungkan Subjek dengan Role/ClusterRole.
- RoleBinding: Menempelkan Role (atau ClusterRole) ke Subjek di dalam namespace tertentu. Jika kita menempelkan ClusterRole menggunakan RoleBinding, Subjek hanya akan mendapatkan akses pada namespace tempat RoleBinding tersebut dideploy.
- ClusterRoleBinding: Menempelkan ClusterRole ke Subjek di tingkat global cluster. Subjek mendapatkan akses ke resource tersebut di seluruh namespace tanpa batasan.
flowchart TD
subgraph Subjects ["Subjects (Siapa?)"]
SA["ServiceAccount"]
US["User / Group"]
end
subgraph Bindings ["Bindings (Hubungan)"]
RB["RoleBinding (Namespaced)"]
CRB["ClusterRoleBinding (Global)"]
end
subgraph Access ["Access Definition (Hak Akses)"]
R["Role (Lokasi Terbatas)"]
CR["ClusterRole (Global / Cluster-wide)"]
end
SA --> RB
US --> CRB
RB --> R
RB -.->|"Membatasi Akses ke Namespace"| CR
CRB --> CR
Implementasi Praktis: Perancangan Hak Akses Minimal (Least Privilege) #
Untuk menjaga keamanan cluster, kita harus selalu menerapkan Principle of Least Privilege (Prinsip Hak Akses Minimal). Jangan pernah menggunakan ClusterRole bawaan admin atau cluster-admin untuk Pod aplikasi kita jika aplikasi tersebut hanya membutuhkan akses baca sederhana.
Mari kita pelajari contoh implementasi konkret untuk microservice log-archiver yang membutuhkan hak akses untuk membaca (get, list, watch) data log Pod di namespace logging.
1. Manifes ServiceAccount Khusus Aplikasi #
apiVersion: v1
kind: ServiceAccount
metadata:
name: log-archiver-sa
namespace: logging
2. Manifes Role (Membatasi Izin Hanya untuk Baca Pod) #
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader-role
namespace: logging # Terisolasi di dalam namespace ini
rules:
- apiGroups: [""] # "" menandakan core API group
resources: ["pods", "pods/log"] # Hanya izinkan akses ke resource Pod dan sub-resource log
verbs: ["get", "list", "watch"] # Hanya tindakan baca, dilarang 'create', 'update', atau 'delete'
3. Manifes RoleBinding (Menghubungkan ServiceAccount dengan Role) #
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: log-archiver-binding
namespace: logging
subjects:
- kind: ServiceAccount
name: log-archiver-sa
namespace: logging
roleRef:
kind: Role
name: pod-reader-role
apiGroup: rbac.authorization.k8s.io
4. Manifes Deployment (Mengonsumsi ServiceAccount) #
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-archiver
namespace: logging
spec:
replicas: 1
selector:
matchLabels:
app: log-archiver
template:
metadata:
labels:
app: log-archiver
spec:
# Suntikkan identitas ServiceAccount khusus ke dalam Pod
serviceAccountName: log-archiver-sa
containers:
- name: archiver
image: company/log-archiver:v1.0.0
Verifikasi dan Audit Izin Akses RBAC #
Sebagai operator kluster, kita harus sering melakukan audit untuk memastikan tidak ada deviasi hak akses. Kubernetes menyediakan perintah CLI bawaan kubectl auth can-i yang sangat kuat untuk menguji coba aturan RBAC tanpa perlu berpindah konteks akun.
1. Menguji Akses untuk Diri Sendiri #
# Apakah saya diizinkan membuat deployment di namespace default?
kubectl auth can-i create deployments --namespace default
# Output: yes atau no
2. Menguji Akses Atas Nama ServiceAccount Tertentu (Impersonation) #
Sangat berguna untuk memvalidasi apakah ServiceAccount yang kita rancang sudah benar-benar dibatasi hak aksesnya.
# Uji apakah ServiceAccount log-archiver-sa bisa menghapus Pod di namespace logging
kubectl auth can-i delete pods \
--as=system:serviceaccount:logging:log-archiver-sa \
--namespace logging
# Output yang diharapkan: no (karena hanya diberi izin get/list/watch)
# Uji apakah ServiceAccount tersebut bisa membaca log Pod
kubectl auth can-i get pods/log \
--as=system:serviceaccount:logging:log-archiver-sa \
--namespace logging
# Output yang diharapkan: yes
3. Audit Izin Menggunakan Tooling Eksternal #
Untuk cluster produksi besar, melakukan audit manual satu per satu sangat melelahkan. Kita dapat memanfaatkan tools open-source seperti rakess (Access Matrix Visualizer) atau krane untuk memetakan hubungan RBAC dan mendeteksi adanya ServiceAccount yang memiliki izin terlalu luas secara otomatis.
Mitigasi Risiko Eskalasi Hak Akses (Privilege Escalation) #
Kubernetes memiliki sistem pengamanan internal untuk mencegah subjek memanipulasi aturan RBAC guna menaikkan hak akses mereka sendiri. Pengamanan ini diatur oleh dua aturan utama:
1. Aturan Validasi Eskalasi (No Escalation Rule) #
API Server tidak akan mengizinkan seorang pengguna membuat atau memperbarui Role/ClusterRole yang memuat izin di atas izin yang dimiliki oleh pengguna tersebut saat itu.
- Skenario: Pengembang A hanya memiliki izin mengelola ConfigMap. Pengembang A tidak akan bisa membuat Role baru yang berisi izin membuat Pod, meskipun Pengembang A memiliki akses tulis ke objek Role. Jika ia mencoba melakukannya, API Server akan menolak dengan error
403 Forbidden: privilege escalation is not allowed.
2. Aturan Izin Khusus bind dan escalate
#
Jika sebuah aplikasi (seperti CI/CD Controller atau Operator) memang didesain untuk membuat dan menempelkan Role baru ke ServiceAccount lain, ServiceAccount aplikasi tersebut harus diberi izin verb bind atau escalate secara eksplisit pada resource roles di dalam ClusterRole-nya.
# Contoh memberikan izin terbatas bagi CI/CD controller untuk menempelkan Role
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cicd-role-binder
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "rolebindings"]
verbs: ["get", "list", "create", "update"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
verbs: ["bind"] # ← Izinkan menempelkan Role tanpa memicu pemblokiran privilege escalation
Anti-Pattern vs Solusi Terbaik #
Mari kita pelajari kesalahan-kesalahan fatal yang sering dilakukan tim pengembang saat mengonfigurasi RBAC di Kubernetes beserta perbaikannya.
Anti-Pattern 1: Menggunakan Wildcard * pada Verbs dan Resources
#
Tindakan malas dengan menggunakan tanda bintang (*) pada bagian resources atau verbs untuk mempercepat deployment tanpa memikirkan aspek keamanan. Hal ini memberikan izin administrator penuh pada objek terkait.
# ✗ ANTI-PATTERN: Penggunaan wildcard yang memberikan akses tanpa batas
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-manager-role
namespace: billing
rules:
- apiGroups: ["*"] # Mengizinkan seluruh API groups
resources: ["*"] # Mengizinkan seluruh resources (Pod, Secrets, PV, dll)
verbs: ["*"] # Mengizinkan seluruh tindakan (create, delete, dll)
Solusi Terbaik #
Tulis daftar resource dan verb secara eksplisit dan granular. Hanya cantumkan apa yang benar-benar dibutuhkan oleh kode aplikasi saat beroperasi.
# ✓ SOLUSI: Deklarasikan resource dan verb secara terperinci
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: app-manager-role
namespace: billing
rules:
- apiGroups: [""]
resources: ["configmaps", "services"] # Hanya batasi pada dua objek ini
verbs: ["get", "list", "update"] # Batasi tindakan manipulasi data, dilarang 'delete'
Anti-Pattern 2: Menggunakan ClusterRoleBinding untuk Resource Namespaced #
Menghubungkan ClusterRole bawaan (seperti view atau edit) ke ServiceAccount menggunakan ClusterRoleBinding, padahal aplikasi tersebut hanya berjalan dan berinteraksi di dalam satu namespace tertentu.
Konsekuensi #
Jika aplikasi kita mengalami kebocoran keamanan (exploited), penyerang dapat menggunakan token ServiceAccount tersebut untuk membaca atau memodifikasi data sensitif di seluruh namespace lain yang ada di cluster, merusak isolasi keamanan lingkungan (blast radius meluas ke seluruh cluster).
Solusi Terbaik #
Selalu gunakan RoleBinding (bukan ClusterRoleBinding) untuk membatasi ruang lingkup operasional ClusterRole tersebut hanya pada namespace target aplikasi.
# ✓ SOLUSI: Mengikat ClusterRole secara terbatas menggunakan RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: api-viewer-binding
namespace: payment # Izin hanya berlaku di dalam namespace 'payment'
subjects:
- kind: ServiceAccount
name: payment-api-sa
namespace: payment
roleRef:
# Merujuk ke ClusterRole bawaan Kubernetes, tetapi terikat secara lokal
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
Anti-Pattern 3: Memberikan Izin get, list, watch Secrets Tanpa Filter
#
Memberikan akses baca penuh ke seluruh objek Secrets di satu namespace kepada aplikasi yang sebenarnya hanya membutuhkan akses ke satu Secret spesifik miliknya sendiri.
Konsekuensi #
Jika kontainer aplikasi berhasil dieksploitasi, penyerang dapat menarik seluruh Secrets di namespace tersebut, termasuk kredensial milik database utama, token Slack, atau kunci pihak ketiga lainnya.
Solusi Terbaik #
Gunakan fitur resourceNames pada manifes Role untuk membatasi akses baca ServiceAccount secara eksklusif hanya pada nama objek Secret yang telah ditentukan.
# ✓ SOLUSI: Batasi akses Secret menggunakan resourceNames
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: payment-secret-reader
namespace: payment
rules:
- apiGroups: [""]
resources: ["secrets"]
# Membatasi akses baca hanya untuk objek yang bernama di bawah ini
resourceNames: ["payment-db-secret", "stripe-keys"]
verbs: ["get"] # Hanya izinkan 'get' (dilarang 'list' atau 'watch' untuk mencegah scraping)
Manifes RBAC Produksi Terbaik (Audit-Hardened) #
Berikut adalah contoh manifes gabungan siap produksi yang menerapkan standar keamanan RBAC tinggi, dilengkapi pembatasan namespace, penggunaan resourceNames untuk Secret, dan isolasi ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
name: user-portal-sa
namespace: user-management
labels:
app.kubernetes.io/name: user-portal
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: user-portal-role
namespace: user-management
labels:
app.kubernetes.io/name: user-portal
rules:
# 1. Izinkan akses baca metadata Pod miliknya sendiri untuk clustering
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
# 2. Izinkan akses baca Secret secara terarah (hanya untuk database credentials)
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-user-portal-secret"]
verbs: ["get"]
# 3. Izinkan update status ConfigMap konfigurasi dinamis
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["user-portal-dynamic-flags"]
verbs: ["get", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: user-portal-binding
namespace: user-management
labels:
app.kubernetes.io/name: user-portal
subjects:
- kind: ServiceAccount
name: user-portal-sa
namespace: user-management
roleRef:
kind: Role
name: user-portal-role
apiGroup: rbac.authorization.k8s.io
Checklist Audit Izin Akses RBAC #
Pastikan konfigurasi RBAC di cluster kita memenuhi standar audit keamanan berikut sebelum melakukan perilisan produksi:
ISOLASI SERVICEACCOUNT:
□ Setiap microservice memiliki ServiceAccount uniknya sendiri (tidak menggunakan 'default' ServiceAccount).
□ Properti 'automountServiceAccountToken: false' diaktifkan pada Pod yang tidak membutuhkan komunikasi ke API Server.
□ Izin akses ServiceAccount diuji kelayakannya menggunakan perintah 'kubectl auth can-i --as=...'.
GRANULARITAS IJIN AKSES:
□ Seluruh manifes Role bebas dari penggunaan wildcard '*' pada verbs dan resources.
□ Akses ke objek Secrets dibatasi secara ketat menggunakan properti 'resourceNames'.
□ Aturan verbs baca dibatasi hanya ke 'get' (hindari 'list' atau 'watch' jika tidak dibutuhkan).
CAKUPAN BINDING:
□ RoleBinding digunakan (bukan ClusterRoleBinding) untuk resource namespaced guna memperkecil blast radius.
□ ClusterRoleBinding hanya digunakan untuk operator sistem atau controller cluster-wide (e.g. Ingress Controller, Prometheus).
□ Izin akses tingkat ClusterRoleAdmin dibatasi hanya untuk tim platform administrator.
Ringkasan #
- Hormati prinsip least privilege — Selalu batasi izin akses ServiceAccount kontainer hanya pada objek dan tindakan yang benar-benar dibutuhkan oleh kode aplikasi.
- Gunakan RoleBinding untuk namespaced resources — Batasi ruang lingkup kekuasaan ClusterRole bawaan menggunakan RoleBinding agar hak akses hanya berlaku lokal di dalam satu namespace target.
- Kunci akses Secret dengan resourceNames Mencegah penyerang melakukan pembacaan massal (scraping) seluruh Secrets di namespace dengan membatasi kueri hanya ke nama objek spesifik.
- Buat ServiceAccount unik per aplikasi — Jangan pernah membagi satu ServiceAccount global untuk banyak aplikasi yang berbeda guna menghindari pencemaran hak akses.
- Hindari wildcard
*di produksi — Deklarasikan resource API groups, resources, dan verbs secara eksplisit dan terperinci dalam manifes Role/ClusterRole.- Lakukan audit berkala — Manfaatkan perintah
kubectl auth can-idengan parameter impersonasi--asuntuk mensimulasikan dan memverifikasi ketajaman RBAC.
← Sebelumnya: Anti-Pattern Deployment Berikutnya: Pod Security →