Praktik terbaik untuk RBAC GKE


Halaman ini memberikan praktik yang baik untuk merencanakan kebijakan role-based access control (RBAC). Untuk mempelajari cara mengimplementasikan RBAC di Google Kubernetes Engine (GKE), lihat Mengonfigurasi role-based access control.

RBAC adalah fitur keamanan inti di Kubernetes yang memungkinkan Anda membuat izin terperinci untuk mengelola tindakan yang dapat dilakukan pengguna dan workload pada resource dalam cluster Anda. Sebagai administrator platform, Anda membuat peran RBAC dan mengikat peran tersebut ke subjek, yang merupakan pengguna terautentikasi seperti layanan atau Google Grup.

Sebelum memulai

Pastikan Anda sudah memahami konsep berikut:

Untuk checklist panduan ini, lihat Ringkasan checklist.

Cara kerja RBAC

RBAC mendukung jenis peran dan binding berikut:

  • ClusterRole: sekumpulan izin yang dapat diterapkan ke namespace apa pun, atau ke seluruh cluster.
  • Peran: sekumpulan izin yang dibatasi pada satu namespace.
  • ClusterRoleBinding: mengikat ClusterRole ke pengguna atau grup untuk semua namespace di cluster.
  • RoleBinding: mengikat Role atau ClusterRole ke pengguna atau grup dalam namespace tertentu.

Anda menentukan izin sebagai rules dalam Role atau ClusterRole. Setiap kolom rules dalam peran terdiri dari grup API, resource API dalam grup API tersebut, dan verba (tindakan) yang diizinkan pada resource tersebut. Secara opsional, Anda dapat mencakup verba ke instance resource API bernama menggunakan kolom resourceNames. Sebagai contoh, lihat Membatasi akses ke instance resource tertentu.

Setelah menentukan peran, Anda menggunakan RoleBinding atau ClusterRoleBinding untuk mengikat peran ke subjek. Pilih jenis binding berdasarkan apakah Anda ingin memberikan izin dalam satu namespace atau beberapa namespace.

Desain peran RBAC

Menggunakan prinsip hak istimewa terendah

Saat menetapkan izin dalam peran RBAC, gunakan prinsip hak istimewa terendah dan berikan izin minimum yang diperlukan untuk melakukan tugas. Menggunakan prinsip hak istimewa terendah akan mengurangi potensi eskalasi akses jika cluster Anda disusupi, dan mengurangi kemungkinan akses yang berlebihan menyebabkan insiden keamanan.

Saat mendesain peran Anda, pertimbangkan dengan cermat risiko eskalasi akses umum, seperti verba escalate atau bind, akses create untuk PersistentVolumes, atau akses create untuk Permintaan Penandatanganan Sertifikat. Untuk mengetahui daftar risiko, lihat Kubernetes RBAC - risiko eskalasi akses.

Menghindari peran dan grup default

Kubernetes membuat sekumpulan ClusterRoles dan ClusterRoleBindings default yang dapat Anda gunakan untuk penemuan API dan untuk mengaktifkan fungsi komponen terkelola. Izin yang diberikan oleh peran default ini mungkin sangat luas, bergantung pada perannya. Kubernetes juga memiliki sekumpulan pengguna dan grup pengguna default, yang diidentifikasi dengan awalan system:. Secara default, Kubernetes dan GKE secara otomatis mengikat peran ini ke grup default dan ke berbagai subjek. Untuk mengetahui daftar lengkap peran dan binding default yang dibuat Kubernetes, lihat Peran dan binding peran default.

Tabel berikut menjelaskan beberapa peran, pengguna, dan grup default. Sebaiknya hindari berinteraksi dengan peran, pengguna, dan grup ini kecuali jika Anda telah mengevaluasinya dengan cermat, karena berinteraksi dengan resource ini dapat memiliki konsekuensi yang tidak diinginkan terhadap postur keamanan cluster Anda.

Nama Jenis Deskripsi
cluster-admin ClusterRole Memberikan izin subjek untuk melakukan apa pun pada resource apa pun di cluster.
system:anonymous Pengguna

Kubernetes menetapkan pengguna ini ke permintaan server API yang tidak menyediakan informasi autentikasi.

Mengikat peran ke pengguna ini akan memberikan izin kepada setiap pengguna tanpa autentikasi yang diberikan oleh peran tersebut.

system:unauthenticated Grup

Kubernetes menetapkan grup ini ke permintaan server API yang tidak menyediakan informasi autentikasi.

Mengikat peran ke grup ini akan memberikan izin kepada setiap pengguna tanpa autentikasi yang diberikan oleh peran tersebut.

system:authenticated Grup

GKE menetapkan grup ini ke permintaan server API yang dibuat oleh pengguna mana pun yang login dengan Akun Google, termasuk semua akun Gmail. Dalam praktiknya, hal ini tidak berbeda secara signifikan dengan system:unauthenticated karena siapa pun dapat membuat Akun Google.

Mengikat peran ke grup ini akan memberi semua pengguna Akun Google, termasuk semua akun Gmail, izin yang diberikan oleh peran tersebut.

system:masters Grup

Kubernetes menetapkan ClusterRole cluster-admin ke grup ini secara default untuk mengaktifkan fungsi sistem.

Dengan menambahkan subjek Anda sendiri ke grup ini, subjek tersebut akan memiliki akses untuk melakukan apa pun pada resource mana pun dalam cluster Anda.

Jika memungkinkan, hindari membuat binding yang melibatkan pengguna, peran, dan grup default. Hal ini dapat menimbulkan konsekuensi yang tidak diinginkan terhadap postur keamanan cluster Anda. Contoh:

  • Mengikat ClusterRole cluster-admin default ke grup system:unauthenticated akan memberikan akses kepada pengguna tanpa autentikasi ke semua resource dalam cluster (termasuk Secret). Binding dengan hak istimewa tinggi ini secara aktif menjadi target serangan seperti kampanye malware massal.
  • Mengikat Peran khusus ke grup system:unauthenticated akan memberikan izin kepada pengguna tanpa autentikasi yang diberikan oleh peran tersebut.

Jika memungkinkan, gunakan panduan berikut:

  • Jangan tambahkan subjek Anda sendiri ke grup system:masters.
  • Jangan ikat grup system:unauthenticated ke peran RBAC apa pun.
  • Jangan ikat grup system:authenticated ke peran RBAC apa pun.
  • Jangan ikat pengguna system:anonymous ke peran RBAC apa pun.
  • Jangan ikat ClusterRole cluster-admin ke subjek Anda sendiri atau ke pengguna dan grup default mana pun. Jika aplikasi Anda memerlukan banyak izin, tentukan izin yang diperlukan, lalu buat peran khusus untuk tujuan tersebut.
  • Evaluasi izin yang diberikan oleh peran default lain sebelum mengikat subjek.
  • Evaluasi peran yang terikat dengan grup default sebelum mengubah anggota grup tersebut.

Mendeteksi dan mencegah penggunaan peran dan grup default

Anda harus menilai cluster untuk mengidentifikasi apakah Anda telah mengikat pengguna system:anonymous atau grup system:unauthenticated atau system:authenticated menggunakan ClusterRoleBindings dan RoleBindings.

ClusterRoleBindings
  1. Buat daftar nama ClusterRoleBindings dengan subjek system:anonymous, system:unauthenticated, atau system:authenticated:

    kubectl get clusterrolebindings -o json \
      | jq -r '["Name"], ["-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Output hanya akan mencantumkan ClusterRoleBinding berikut:

    Name
    ----
    "system:basic-user"
    "system:discovery"
    "system:public-info-viewer"
    

    Jika output berisi binding non-default tambahan, lakukan hal berikut untuk setiap binding tambahan. Jika output Anda tidak berisi binding non-default, lewati langkah-langkah berikut.

  2. Cantumkan izin peran yang terkait dengan binding:

    kubectl get clusterrolebinding CLUSTER_ROLE_BINDING_NAME -o json \
        | jq ' .roleRef.name +" " + .roleRef.kind' \
        | sed -e 's/"//g' \
        | xargs -l bash -c 'kubectl get $1 $0 -o yaml'
    

    Ganti CLUSTER_ROLE_BINDING_NAME dengan nama ClusterRoleBinding non-default.

    Outputnya mirip dengan hal berikut ini:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
    ...
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - watch
      - list
    

    Jika Anda memutuskan bahwa izin dalam output aman untuk diberikan kepada pengguna atau grup default, Anda tidak perlu melakukan tindakan lebih lanjut. Jika Anda memutuskan bahwa izin yang diberikan oleh binding tidak aman, lanjutkan ke langkah berikutnya.

  3. Hapus binding yang tidak aman dari cluster Anda:

    kubectl delete clusterrolebinding CLUSTER_ROLE_BINDING_NAME
    

    Ganti CLUSTER_ROLE_BINDING_NAME dengan nama ClusterRoleBinding yang akan dihapus.

RoleBindings
  1. Cantumkan namespace dan nama RoleBinding dengan subjek system:anonymous, system:unauthenticated, atau system:authenticated:

    kubectl get rolebindings -A -o json \
      | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Jika cluster Anda dikonfigurasi dengan benar, output-nya harus kosong. Jika output berisi binding non-default, lakukan langkah-langkah berikut untuk setiap binding tambahan. Jika output Anda kosong, lewati langkah-langkah berikut.

    Jika hanya mengetahui nama RoleBinding, Anda dapat menggunakan perintah berikut untuk menemukan rolebinding yang cocok di semua namespace:

    kubectl get rolebindings -A -o json \
      | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(.metadata.name == "ROLE_BINDING_NAME") | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Ganti ROLE_BINDING_NAME dengan nama RoleBinding non-default.

  2. Buat daftar izin Peran yang terkait dengan binding:

    kubectl get rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE -o json \
        | jq ' .roleRef.name +" " + .roleRef.kind' \
        | sed -e 's/"//g' \
        | xargs -l bash -c 'kubectl get $1 $0 -o yaml --namespace ROLE_BINDING_NAMESPACE'
    

    Ganti kode berikut:

    • ROLE_BINDING_NAME: nama RoleBinding non-default.
    • ROLE_BINDING_NAMESPACE: namespace RoleBinding non-default.

    Outputnya mirip dengan hal berikut ini:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    ...
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - watch
      - list
    

    Jika Anda memutuskan bahwa izin dalam output aman untuk diberikan kepada pengguna atau grup default, Anda tidak perlu melakukan tindakan lebih lanjut. Jika Anda memutuskan bahwa izin yang diberikan oleh binding tidak aman, lanjutkan ke langkah berikutnya.

  3. Hapus binding yang tidak aman dari cluster Anda:

    kubectl delete rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE
    

    Ganti kode berikut:

    • ROLE_BINDING_NAME: nama RoleBinding yang akan dihapus.
    • ROLE_BINDING_NAMESPACE: namespace RoleBinding yang akan dihapus.

Membatasi izin ke tingkat namespace

Gunakan binding dan peran sebagai berikut, bergantung pada kebutuhan workload atau pengguna Anda:

  • Untuk memberikan akses ke resource dalam satu namespace, gunakan Role dengan RoleBinding.
  • Untuk memberikan akses ke resource di lebih dari satu namespace, gunakan ClusterRole dengan RoleBinding untuk setiap namespace.
  • Untuk memberikan akses ke resource di setiap namespace, gunakan ClusterRole dengan ClusterRoleBinding.

Berikan izin pada namespace sesedikit mungkin.

Jangan menggunakan karakter pengganti

Karakter * adalah karakter pengganti yang berlaku untuk semua hal. Hindari penggunaan karakter pengganti dalam aturan Anda. Tentukan secara eksplisit grup, resource, dan verba API dalam aturan RBAC. Misalnya, menentukan * di kolom verbs akan menghasilkan izin get, list, watch, patch, update, deletecollection, dan delete pada resource. Tabel berikut menunjukkan contoh cara menghindari karakter pengganti dalam aturan Anda:

Direkomendasikan Tidak direkomendasikan

- rules:
    apiGroups: ["apps","extensions"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

Memberikan verba get, list, dan watch secara khusus ke grup API apps dan extensions.


- rules:
    apiGroups: ["*"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

Memberikan verba ke deployments di grup API apa pun.


- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]

Hanya memberikan verba get, list, dan watch untuk deployment di grup API apps dan extensions.


- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["*"]

Memberikan semua verba, termasuk patch atau delete.

Menggunakan aturan terpisah untuk memberikan akses hak istimewa terendah ke resource tertentu

Saat merencanakan aturan, coba langkah-langkah tingkat tinggi berikut untuk desain aturan dengan hak istimewa terendah yang lebih efisien di setiap peran:

  1. Buat draf aturan RBAC terpisah untuk setiap verba pada setiap resource yang perlu diakses oleh subjek.
  2. Setelah membuat draf aturan, analisis aturan untuk memeriksa apakah beberapa aturan memiliki daftar verbs yang sama atau tidak. Gabungkan aturan tersebut menjadi satu aturan.
  3. Tetap pisahkan semua aturan lainnya.

Pendekatan ini menghasilkan desain aturan yang lebih teratur, dengan aturan yang memberikan verba yang sama ke beberapa resource digabungkan, dan aturan yang memberikan verba yang berbeda ke resource akan terpisah.

Misalnya, jika workload Anda perlu mendapatkan izin untuk resource deployments, tetapi memerlukan list dan watch pada resource daemonsets, Anda harus menggunakan aturan terpisah saat membuat peran tersebut. Ketika Anda mengikat peran RBAC ke workload Anda, peran tersebut tidak akan dapat menggunakan watch di deployments.

Sebagai contoh lain, jika workload Anda memerlukan get dan watch pada resource pods dan resource daemonsets, Anda dapat menggabungkannya menjadi satu aturan, karena workload membutuhkan verba yang sama di kedua resource.

Dalam tabel berikut, kedua desain aturan dapat berfungsi, tetapi aturan pemisahan secara lebih terperinci membatasi akses resource berdasarkan kebutuhan Anda:

Direkomendasikan Tidak direkomendasikan

- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get"]
- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]

Memberikan akses get untuk Deployments, serta akses watch dan list untuk DaemonSets. Subjek tidak dapat mencantumkan Deployment.


- rules:
    apiGroups: ["apps"]
    resources: ["deployments", "daemonsets"]
    verbs: ["get","list","watch"]

Memberikan verba ke Deployment dan DaemonSet. Subjek yang mungkin tidak memerlukan akses list pada objek deployments akan tetap mendapatkan akses tersebut.


- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets", "deployments"]
    verbs: ["list", "watch"]

Menggabungkan dua aturan karena subjek memerlukan verba yang sama untuk resource daemonsets dan deployments.


- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]
- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["list", "watch"]

Aturan terpisah ini akan memiliki hasil yang sama dengan aturan gabungan, tetapi akan menimbulkan kekacauan yang tidak perlu dalam manifes peran Anda

Membatasi akses ke instance resource tertentu

Dengan RBAC, Anda dapat menggunakan kolom resourceNames dalam aturan untuk membatasi akses ke instance resource bernama tertentu. Misalnya, jika Anda menulis peran RBAC yang memerlukan update ConfigMap seccomp-high dan bukan yang lainnya, Anda dapat menggunakan resourceNames untuk menentukan hanya ConfigMap tersebut. Gunakan resourceNames jika memungkinkan.

Direkomendasikan Tidak direkomendasikan

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

Membatasi subjek hanya untuk memperbarui ConfigMap seccomp-high. Subjek tidak dapat memperbarui ConfigMaps lain dalam namespace.


- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update"]

Subjek dapat memperbarui ConfigMap seccomp-high dan ConfigMap lainnya dalam namespace.


- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["list"]
- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

Memberi list akses ke semua ConfigMaps dalam namespace, termasuk seccomp-high. Membatasi akses update hanya ke ConfigMap seccomp-high. Aturan ini dibagi karena Anda tidak dapat memberikan list untuk resource bernama.


- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update", "list"]

Memberi update akses untuk semua ConfigMaps, bersama dengan akses list.

Jangan mengizinkan akun layanan mengubah resource RBAC

Jangan ikat resource Role atau ClusterRole yang memiliki izin bind, escalate, create, update, atau patch pada grup API rbac.authorization.k8s.io ke akun layanan di namespace apa pun. escalate dan bind secara khusus dapat memungkinkan penyerang mengabaikan mekanisme pencegahan eskalasi yang dibuat dalam RBAC.

Akun layanan Kubernetes

Membuat akun layanan Kubernetes untuk setiap workload

Buat akun layanan Kubernetes terpisah untuk setiap workload. Ikat Role atau ClusterRole dengan hak istimewa terendah ke akun layanan tersebut.

Jangan menggunakan akun layanan default

Kubernetes membuat akun layanan bernama default di setiap namespace. Akun layanan default secara otomatis ditetapkan ke Pod yang tidak secara eksplisit menentukan akun layanan dalam manifes. Hindari mengikat Role atau ClusterRole ke akun layanan default. Kubernetes mungkin menetapkan akun layanan default ke Pod yang tidak memerlukan akses yang diberikan dalam peran tersebut.

Jangan memasang token akun layanan secara otomatis

Kolom automountServiceAccountToken dalam spesifikasi Pod memberi tahu Kubernetes untuk memasukkan token kredensial untuk akun layanan Kubernetes ke dalam Pod. Pod dapat menggunakan token ini untuk membuat permintaan terautentikasi ke server Kubernetes API. Nilai default untuk kolom ini adalah true.

Di semua versi GKE, tetapkan automountServiceAccountToken=false dalam spesifikasi Pod jika Pod Anda tidak perlu berkomunikasi dengan server API.

Memilih token efemeral daripada token berbasis Secret

Secara default, proses kubelet pada node mengambil token akun layanan berumur pendek yang dirotasi secara otomatis untuk setiap Pod. kubelet memasang token ini di Pod sebagai volume yang diproyeksikan, kecuali jika Anda menetapkan kolom automountServiceAccountToken ke false di spesifikasi Pod. Setiap panggilan ke Kubernetes API dari Pod akan menggunakan token ini untuk melakukan autentikasi ke server API.

Jika Anda mengambil token akun layanan secara manual, hindari penggunaan Secret Kubernetes untuk menyimpan token tersebut. Token akun layanan berbasis secret adalah kredensial lama yang tidak habis masa berlakunya dan tidak dirotasi secara otomatis. Jika Anda memerlukan kredensial untuk akun layanan, gunakan TokenRequest API untuk mendapatkan token berumur pendek yang dirotasi otomatis.

Meninjau izin RBAC secara terus-menerus

Tinjau peran dan akses RBAC Anda secara rutin untuk mengidentifikasi potensi jalur eskalasi dan aturan yang berlebihan. Misalnya, pertimbangkan situasi saat Anda tidak menghapus RoleBinding yang mengikat Role dengan hak istimewa khusus untuk pengguna yang dihapus. Jika penyerang membuat akun pengguna dalam namespace tersebut dengan nama yang sama seperti pengguna yang dihapus, dia akan terikat dengan Role tersebut dan akan mewarisi akses yang sama. Peninjauan berkala meminimalkan risiko ini.

Ringkasan checklist

Langkah selanjutnya