Pod tidak datang ke API server sebagai pengguna manusia, tetapi membawa identitas sendiri yang disebut ServiceAccount. Topik ini membahas perbedaan ServiceAccount dengan akun pengguna, objek Role dan ClusterRole yang menyimpan aturan izin, objek RoleBinding dan ClusterRoleBinding yang menghubungkan aturan dengan identitas, serta prinsip hak akses minimum (least privilege) yang menjadi alasan seluruh model ini ada. Evaluasi akses pada bagian akhir membaca dua manifest dari bundle dan menjawab lima pertanyaan izin secara deterministik.
ServiceAccount, identitas untuk proses di dalam Pod#
Kubernetes membedakan dua jenis akun. Akun pengguna dikelola di luar kluster, misalnya melalui sertifikat yang ditandatangani CA atau penyedia identitas OIDC, sedangkan ServiceAccount adalah objek API yang dibuat dan diberi izin di dalam sebuah Namespace. Proses di dalam Pod mengidentifikasi diri dengan ServiceAccount melalui token yang dipasang otomatis pada volume Pod, sehingga aplikasi dapat membacanya dan menyertakannya pada setiap permintaan ke API server.
Setiap Namespace otomatis memiliki ServiceAccount bernama default, dan Pod yang tidak menyebut akun mana pun menjalankan prosesnya dengan akun tersebut. Bidang serviceAccountName pada spec Pod memilih akun lain yang sudah dibuat. Kebiasaan yang disarankan adalah membuat ServiceAccount khusus untuk setiap aplikasi dan menonaktifkan pemasangan token otomatis pada Pod yang tidak berbicara dengan API server, sehingga permukaan kredensial yang dapat dicuri berkurang.
Role dan ClusterRole#
Role adalah objek yang menyimpan sekumpulan aturan izin dalam satu namespace, sedangkan ClusterRole menyimpan aturan yang berlaku di seluruh kluster. Setiap aturan berisi tiga bidang, yaitu apiGroups yang menyebut kelompok API, resources yang menyebut jenis objek, dan verbs yang menyebut tindakan yang boleh dilakukan. Kelompok API inti ditulis dengan string kosong, sehingga aturan untuk pods menggunakan apiGroups: [""].
Manifest berikut memberikan izin baca untuk aplikasi pembaca catatan di namespace aplikasi-catatan:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: lihat-catatan
namespace: aplikasi-catatan
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]Aturan pertama memberikan get, list, dan watch terhadap pods pada kelompok API inti. Aturan kedua menyentuh subresource pods/log, yaitu resource yang berdiri terpisah dari pods di mata otorisator, sehingga izin baca pods tidak otomatis mencakup izin baca log-nya. Aturan ketiga menyentuh deployments pada kelompok apps. Perhatikan bahwa Role sama sekali tidak menyebut identitas penerimanya, karena pemberian izin kepada identitas menjadi tugas objek binding.
Kebutuhan yang sama pada tingkat kluster ditulis dengan ClusterRole, misalnya izin membaca Node yang tidak pernah berada di dalam namespace tertentu. ClusterRole juga lazim digunakan sebagai kumpulan aturan umum yang diikat berulang kali ke banyak namespace melalui binding terpisah.
RoleBinding dan ClusterRoleBinding#
Binding menghubungkan aturan dengan identitas. RoleBinding memberikan aturan kepada identitas di dalam satu namespace, sedangkan ClusterRoleBinding memberikan aturan di seluruh kluster. Identitas penerima disebut pada daftar subjects, yang dapat berupa ServiceAccount, pengguna, atau grup, sedangkan aturannya dirujuk melalui bidang roleRef. Manifest berikut mengikat ServiceAccount pembaca-catatan kepada Role yang ditulis sebelumnya:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: lihat-catatan-binding
namespace: aplikasi-catatan
subjects:
- kind: ServiceAccount
name: pembaca-catatan
namespace: aplikasi-catatan
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: lihat-catatanPerintah berikut membuat akunnya, menerapkan kedua manifest, lalu menanyakan izin akun tersebut:
# tidak-dijalankan
# buat ServiceAccount pembaca-catatan di namespace aplikasi-catatan
kubectl create serviceaccount pembaca-catatan -n aplikasi-catatan
# terapkan Role dan RoleBinding dari bundle
kubectl apply -f role.yaml
kubectl apply -f rolebinding.yaml
# tanyakan izin list pods untuk identitas ServiceAccount tersebut
kubectl auth can-i list pods -n aplikasi-catatan --as system:serviceaccount:aplikasi-catatan:pembaca-catatanserviceaccount/pembaca-catatan created
role.rbac.authorization.k8s.io/lihat-catatan created
rolebinding.rbac.authorization.k8s.io/lihat-catatan-binding created
yesKombinasi yang sah antara jenis aturan dan jenis binding diatur secara ketat, dan tabel berikut merangkumnya:
| Aturan | Binding yang sah | Cakupan izin |
|---|---|---|
| Role | RoleBinding | satu namespace tempat Role dibuat |
| ClusterRole | RoleBinding | satu namespace tempat RoleBinding dibuat |
| ClusterRole | ClusterRoleBinding | seluruh kluster |
RoleBinding yang merujuk ClusterRole digunakan untuk memberikan sekumpulan aturan bawaan, misalnya ClusterRole view atau edit, kepada identitas pada satu namespace saja, sedangkan ClusterRoleBinding tidak dapat merujuk Role sama sekali.
Simulasi kubectl auth can-i dengan skrip#
Skrip berikut membaca role.yaml dan rolebinding.yaml dari bundle, mengambil daftar aturan dari Role, lalu menjawab lima pertanyaan izin untuk identitas yang diikat RoleBinding. Logikanya meniru keputusan otorisator RBAC, termasuk pemeriksaan apiGroup, resource, verb, dan batas namespace milik Role:
"""Evaluasi pasangan verb, resource, dan namespace terhadap Role dan RoleBinding."""
import yaml
with open("role.yaml", encoding="utf-8") as f:
role = yaml.safe_load(f)
with open("rolebinding.yaml", encoding="utf-8") as f:
binding = yaml.safe_load(f)
subjek = ", ".join(s["name"] for s in binding["subjects"])
print(f"Role {role['metadata']['name']} di namespace {role['metadata']['namespace']}")
print(f"RoleBinding {binding['metadata']['name']} mengikat ServiceAccount {subjek}")
print()
def diizinkan(verb, grup_api, resource, namespace):
# Role hanya berlaku pada namespace tempat ia dibuat
if namespace != role["metadata"]["namespace"]:
return False
# default deny: tanpa aturan yang cocok, permintaan langsung ditolak
for aturan in role["rules"]:
if grup_api not in aturan["apiGroups"] and "*" not in aturan["apiGroups"]:
continue
if resource not in aturan["resources"] and "*" not in aturan["resources"]:
continue
if verb not in aturan["verbs"] and "*" not in aturan["verbs"]:
continue
return True
return False
# kasus uji meniru kubectl auth can-i: (verb, apiGroup, resource, namespace)
kasus = [
("list", "", "pods", "aplikasi-catatan"),
("get", "", "pods/log", "aplikasi-catatan"),
("list", "apps", "deployments", "aplikasi-catatan"),
("delete", "", "pods", "aplikasi-catatan"),
("list", "", "pods", "operasi"),
]
for verb, grup, resource, namespace in kasus:
hasil = "DIIZINKAN" if diizinkan(verb, grup, resource, namespace) else "DITOLAK"
label_grup = "core" if grup == "" else grup
print(f" {verb} {label_grup}/{resource} -n {namespace} : {hasil}")Role lihat-catatan di namespace aplikasi-catatan
RoleBinding lihat-catatan-binding mengikat ServiceAccount pembaca-catatan
list core/pods -n aplikasi-catatan : DIIZINKAN
get core/pods/log -n aplikasi-catatan : DIIZINKAN
list apps/deployments -n aplikasi-catatan : DIIZINKAN
delete core/pods -n aplikasi-catatan : DITOLAK
list core/pods -n operasi : DITOLAKTiga pertanyaan pertama diizinkan masing-masing oleh aturan pods, pods/log, dan deployments, sedangkan pertanyaan keempat ditolak karena Role tidak memuat verb delete. Pertanyaan kelima ditolak meskipun resource dan verbnya cocok, karena Role hanya berlaku pada namespace tempat ia dibuat, sedangkan namespace operasi berada di luar cakupannya. Lima jawaban ini sama dengan keputusan kubectl auth can-i untuk ServiceAccount pembaca-catatan pada kluster yang menerapkan kedua manifest tersebut, dan sifat gabungan aturan berarti tidak ada aturan yang saling meniadakan.
Kasus keempat dan kelima juga memperlihatkan pola diagnosis yang lazim ketika aplikasi gagal mengakses API. Perbaikan dimulai dari memastikan identitas yang menanyakan izin sama dengan identitas yang membawa permintaan Pod, dilanjutkan dengan memeriksa apiGroup dan subresource yang disebut aturan, karena resource dan verb yang tepat tetap ditolak apabila kelompok API-nya keliru.
Kesalahan umum#
Tiga kesalahan berikut paling sering muncul saat model izin ini mulai ditulis untuk aplikasi nyata. Ketiganya muncul karena izin dipikirkan dari sisi aturan, sedangkan kegagalan selalu terlihat dari sisi aplikasi yang ditolak, dan pesan error yang ditampilkan tidak selalu menunjuk aturan yang kurang:
- Membuat RoleBinding di namespace yang berbeda dari Role-nya. RoleBinding hanya melihat Role pada namespace yang sama, sehingga pembuatan di namespace operasi berakhir dengan error
not found. Gejala yang sama juga muncul ketikaroleRefmenyebut nama Role yang salah ketik. Perbaikannya adalah memindahkan binding ke namespace aplikasi-catatan atau menjadikan aturannya ClusterRole. - Memberikan izin kepada ServiceAccount default dan berbagi satu akun untuk semua aplikasi. Pod yang disusupi membawa kredensial akun tersebut dan mewarisi seluruh izinnya. Perbaikannya adalah membuat ServiceAccount per aplikasi dengan izin minimum yang memang dibutuhkan.
- Mengabaikan subresource saat menulis aturan. Izin baca pods tidak mencakup
pods/logataupods/execkarena keduanya resource terpisah. Perbaikannya adalah menyebut subresource secara eksplisit pada bidangresources.
Ringkasan#
- ServiceAccount adalah identitas API untuk proses di dalam Pod, sedangkan akun pengguna dikelola di luar kluster melalui sertifikat atau penyedia identitas.
- Role dan ClusterRole menyimpan aturan
apiGroups,resources, danverbs, dengan Role dibatasi satu namespace dan ClusterRole berlaku lintas namespace. - RoleBinding mengikat aturan kepada identitas dalam satu namespace, ClusterRoleBinding mengikat di seluruh kluster, dan Role hanya dapat dirujuk RoleBinding.
- Izin bersifat gabungan tanpa aturan yang saling meniadakan, sehingga keamanan bertumpu pada penulisan aturan minimum per identitas.
Referensi#
- Using RBAC Authorization — Kubernetes — Referensi lengkap Role, ClusterRole, RoleBinding, dan ClusterRoleBinding beserta contoh aturannya.
- Service Accounts — Kubernetes — Konsep ServiceAccount, penerbitan token otomatis, dan perannya sebagai identitas Pod.