ABC Keamanan di Kubernetes: Otentikasi, Otorisasi, Audit



Cepat atau lambat, pengoperasian sistem apa pun menimbulkan pertanyaan tentang keamanan: memastikan otentikasi, pemisahan hak, audit, dan tugas lainnya. Banyak solusi yang telah dibuat untuk Kubernetes yang dapat mencapai kepatuhan dengan standar bahkan dalam lingkungan yang sangat menuntut ... Materi yang sama dikhususkan untuk aspek keamanan dasar yang diimplementasikan dalam kerangka mekanisme built-in K8. Pertama-tama, ini akan berguna bagi mereka yang mulai berkenalan dengan Kubernetes, sebagai titik awal untuk mempelajari masalah-masalah yang berkaitan dengan keamanan.

Otentikasi


Kubernetes memiliki dua jenis pengguna:

  • Akun Layanan - akun yang dikelola oleh Kubernetes API;
  • Pengguna - pengguna "normal" yang dikendalikan oleh layanan eksternal dan independen.

Perbedaan utama antara jenis-jenis ini adalah bahwa untuk Akun Layanan ada objek khusus di API Kubernetes (mereka disebut ServiceAccounts ) yang terkait dengan namespace dan kumpulan data otorisasi yang disimpan dalam cluster di objek-objek tipe Rahasia. Pengguna tersebut (Akun Layanan) dimaksudkan terutama untuk mengelola hak akses ke proses API Kubernetes yang berjalan di cluster Kubernetes.

Pengguna Biasa tidak memiliki entri dalam Kubernetes API: mereka harus dikelola oleh mekanisme eksternal. Mereka dimaksudkan untuk orang atau proses yang hidup di luar cluster.

Setiap permintaan ke API terikat baik ke Akun Layanan, atau ke Pengguna, atau dianggap anonim.

Data otentikasi pengguna meliputi:

  • Nama pengguna - nama pengguna (peka huruf besar kecil!);
  • UID adalah string identifikasi pengguna yang dapat dibaca mesin yang "lebih konsisten dan unik daripada nama pengguna";
  • Grup - daftar grup yang menjadi milik pengguna;
  • Ekstra - bidang tambahan yang dapat digunakan oleh mekanisme otorisasi.

Kubernetes dapat menggunakan sejumlah besar mekanisme otentikasi: sertifikat X509, Bearer token, proxy otentikasi, HTTP Basic Auth. Dengan menggunakan mekanisme ini, sejumlah besar skema otorisasi dapat diimplementasikan: dari file statis dengan kata sandi ke OpenID OAuth2.

Selain itu, beberapa skema otorisasi diizinkan pada saat bersamaan. Secara default, kluster menggunakan:

  • token akun layanan - untuk Akun Layanan;
  • X509 - untuk Pengguna.

Pertanyaan tentang pengelolaan ServiceAccount berada di luar cakupan artikel ini, tetapi saya sarankan mulai mempelajari lebih lanjut tentang masalah ini dari halaman dokumentasi resmi . Kami akan mempertimbangkan secara lebih rinci masalah pekerjaan sertifikat X509.

Sertifikat untuk pengguna (X.509)


Cara klasik untuk bekerja dengan sertifikat melibatkan:

  • generasi kunci:

     mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/.certs/mynewuser.key 2048 
  • pembuatan permintaan sertifikat:

     openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company" 
  • memproses permintaan sertifikat menggunakan kunci CA kluster Kubernetes, memperoleh sertifikat pengguna (untuk mendapatkan sertifikat, Anda perlu menggunakan akun yang memiliki akses ke kunci otoritas sertifikat klaster Kubernetes, yang terletak di /etc/kubernetes/pki/ca.key secara default):

     openssl x509 -req -in ~/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/.certs/mynewuser.crt -days 500 
  • membuat file konfigurasi:
    • deskripsi cluster (tentukan alamat dan lokasi file sertifikat CA dari instalasi cluster tertentu):

       kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 
    • atau - jika bukan opsi yang disarankan - Anda dapat menghilangkan sertifikat root (maka kubectl tidak akan memeriksa kebenaran cluster api-server):

       kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 
    • menambahkan pengguna ke file konfigurasi:

       kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key 
    • menambahkan konteks:

       kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser 
    • penetapan konteks default:

       kubectl config use-context mynewuser-context 

Setelah manipulasi di atas, konfigurasi bentuk akan dibuat dalam file .kube/config :

 apiVersion: v1 clusters: - cluster: certificate-authority: /etc/kubernetes/pki/ca.crt server: https://192.168.100.200:6443 name: kubernetes contexts: - context: cluster: kubernetes namespace: target-namespace user: mynewuser name: mynewuser-context current-context: mynewuser-context kind: Config preferences: {} users: - name: mynewuser user: client-certificate: /home/mynewuser/.certs/mynewuser.crt client-key: /home/mynewuser/.certs/mynewuser.key 

Untuk memfasilitasi transfer konfigurasi antara akun dan server, penting untuk mengedit nilai-nilai kunci berikut:

  • certificate-authority
  • client-certificate
  • client-key

Untuk melakukan ini, Anda bisa menyandikan file yang ditunjukkan di dalamnya menggunakan base64 dan mendaftarkannya di konfigurasi dengan menambahkan akhiran -data ke nama kunci, mis. mendapatkan certificate-authority-data , dll.

Sertifikat dengan kubeadm


Dengan rilis Kubernetes 1.15, bekerja dengan sertifikat menjadi lebih mudah berkat versi alfa dukungannya dalam utilitas kubeadm . Sebagai contoh, inilah tampilan generasi file konfigurasi dengan kunci pengguna sekarang:

 kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 

NB : Alamat iklan yang diperlukan dapat dilihat di konfigurasi api-server, yang terletak di /etc/kubernetes/manifests/kube-apiserver.yaml secara default.

Konfigurasi yang dihasilkan akan menjadi output ke stdout. Itu harus disimpan dalam ~/.kube/config akun pengguna atau dalam file yang ditentukan dalam KUBECONFIG lingkungan KUBECONFIG .

Gali lebih dalam


Bagi mereka yang ingin sepenuhnya memahami masalah yang dijelaskan:


Login


Akun terotentikasi tidak memiliki izin untuk bertindak dalam gugus secara default. Kubernetes memiliki mekanisme otorisasi untuk memberikan izin.

Sebelum versi 1.6, Kubernetes menggunakan tipe otentikasi yang disebut ABAC (Kontrol akses berbasis atribut). Rincian tentang itu dapat ditemukan di dokumentasi resmi . Pendekatan ini saat ini dianggap sebagai warisan, tetapi Anda masih dapat menggunakannya bersamaan dengan jenis otorisasi lainnya.

Cara aktual (dan lebih fleksibel) untuk membagi hak akses cluster disebut RBAC ( Role-based access control ). Telah dinyatakan stabil sejak Kubernetes 1.8 . RBAC mengimplementasikan model hak yang melarang apa pun yang tidak diizinkan secara eksplisit.
Untuk mengaktifkan RBAC , Anda perlu menjalankan server api Kubernetes dengan opsi --authorization-mode=RBAC . Parameter diatur dalam manifes dengan konfigurasi api-server, yang secara default terletak di path /etc/kubernetes/manifests/kube-apiserver.yaml , di bagian command . Namun, RBAC sudah diaktifkan secara default, jadi Anda mungkin tidak perlu khawatir tentang ini: Anda dapat memverifikasi ini dengan nilai authorization-mode (dalam kube-apiserver.yaml telah disebutkan). Ngomong-ngomong, di antara nilainya, mungkin ada jenis otorisasi lain ( node , webhook , always allow ), tetapi kami akan membiarkannya di luar ruang lingkup materi.

Ngomong-ngomong, kami telah menerbitkan sebuah artikel dengan cerita yang cukup terperinci tentang prinsip dan fitur bekerja dengan RBAC, jadi saya akan membatasi diri pada daftar dasar dan contoh singkat.

Entitas API berikut digunakan untuk mengontrol akses ke Kubernetes melalui RBAC:

  • Role dan ClusterRole adalah peran yang menggambarkan hak istimewa:
  • Role memungkinkan Anda untuk mendeskripsikan hak dalam ruang nama;
  • ClusterRole - di dalam cluster, termasuk objek khusus-cluster seperti node, url non-sumber daya (mis. Tidak terkait dengan sumber daya Kubernetes - misalnya, /version , /logs , /api* );
  • RoleBinding dan ClusterRoleBinding - berfungsi untuk mengikat Role dan ClusterRole ke pengguna, grup pengguna, atau ServiceAccount.

Peran Entitas dan RoleBinding dibatasi oleh namespace, mis. harus berada dalam namespace yang sama. Namun, RoleBinding dapat merujuk ke ClusterRole, yang memungkinkan Anda membuat seperangkat izin standar dan mengontrol akses menggunakannya.

Peran menjelaskan hak menggunakan set aturan yang mengandung:

  • Grup API - lihat dokumentasi resmi untuk apiGroups dan output dari kubectl api-resources ;
  • sumber daya ( sumber daya : pod , namespace , deployment , dll.);
  • kata kerja ( kata kerja : set , update , dll.)
  • nama sumber daya ( resourceNames ) - untuk kasus ketika Anda perlu memberikan akses ke sumber daya tertentu, dan bukan untuk semua sumber daya jenis ini.

Diskusi yang lebih rinci tentang otorisasi di Kubernetes dapat ditemukan di halaman dokumentasi resmi . Sebaliknya (atau lebih tepatnya, selain ini) saya akan memberikan contoh yang menggambarkan pekerjaannya.

Contoh Entitas RBAC


Role sederhana yang memungkinkan Anda untuk mendapatkan daftar dan status pod dan memonitornya di target-namespace :

 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: target-namespace name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 

Contoh dari ClusterRole , yang memungkinkan Anda untuk mendapatkan daftar dan status pod dan memonitor mereka di seluruh cluster:

 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: #  "namespace" ,   ClusterRole    name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 

Contoh RoleBinding , yang memungkinkan pengguna mynewuser "membaca" pod di my-namespace :

 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: target-namespace subjects: - kind: User name: mynewuser #     ! apiGroup: rbac.authorization.k8s.io roleRef: kind: Role #    “Role”  “ClusterRole” name: pod-reader #  Role,      namespace, #   ClusterRole,   #    apiGroup: rbac.authorization.k8s.io 

Audit Acara


Secara skematis, arsitektur Kubernetes dapat direpresentasikan sebagai berikut:

gambar

Komponen utama Kubernetes, yang bertanggung jawab untuk memproses permintaan, adalah api-server . Semua operasi pada cluster melewatinya. Baca lebih lanjut tentang mekanisme internal ini di artikel “ Apa yang terjadi di Kubernetes ketika menjalankan kubectl dimulai? ".

Audit sistem adalah fitur yang menarik di Kubernetes, yang dinonaktifkan secara default. Ini memungkinkan Anda untuk mencatat semua panggilan ke API Kubernetes. Seperti yang dapat Anda tebak dengan mudah, melalui API ini semua tindakan yang terkait dengan pemantauan dan perubahan status cluster dilakukan. Deskripsi yang baik tentang fitur-fiturnya dapat (seperti biasa) ditemukan dalam dokumentasi resmi K8s. Selanjutnya, saya akan mencoba menyajikan topik dalam bahasa yang lebih sederhana.

Jadi, untuk mengaktifkan audit , kita perlu memberikan tiga parameter yang diperlukan ke kontainer di server api, lebih lanjut tentang yang dijelaskan di bawah ini:

  • --audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml
  • --audit-log-path=/var/log/kube-audit/audit.log
  • --audit-log-format=json

Selain tiga parameter yang diperlukan ini, ada banyak pengaturan tambahan yang terkait dengan audit: dari rotasi log ke deskripsi webhook. Contoh parameter rotasi log:

  • --audit-log-maxbackup=10
  • --audit-log-maxsize=100
  • --audit-log-maxage=7

Tetapi kami tidak akan membahasnya lebih detail - Anda dapat menemukan semua detail dalam dokumentasi untuk apachever kube .

Seperti yang telah disebutkan, semua parameter diatur dalam manifes dengan konfigurasi api-server (secara default /etc/kubernetes/manifests/kube-apiserver.yaml ), di bagian command . Mari kita kembali ke 3 parameter yang diperlukan dan menganalisisnya:

  1. audit-policy-file - path ke file YAML dengan deskripsi kebijakan audit. Kami akan kembali ke isinya, tetapi untuk saat ini saya perhatikan bahwa file tersebut harus dapat diakses untuk dibaca oleh proses server api. Oleh karena itu, perlu untuk memasangnya di dalam wadah, di mana Anda dapat menambahkan kode berikut ke bagian konfigurasi yang sesuai:

      volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies 
  2. audit-log-path - path ke file log. Path juga harus dapat diakses ke proses server api, oleh karena itu, kami juga menjelaskan pemasangannya:

      volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs 
  3. audit-log-format - format log audit. Secara default, ini json , tetapi format teks lawas juga tersedia.

Kebijakan audit


Sekarang tentang file yang disebutkan dengan deskripsi kebijakan logging. Konsep pertama kebijakan audit adalah level , level logging . Mereka adalah sebagai berikut:

  • None - jangan login;
  • Metadata - log permintaan metadata: pengguna, waktu permintaan, sumber daya target (pod, namespace, dll.), Jenis tindakan (kata kerja), dll;
  • Request - log metadata dan body permintaan;
  • RequestResponse - RequestResponse metadata, badan permintaan dan badan respons.

Dua level terakhir ( Request dan RequestResponse ) tidak mencatat permintaan yang tidak mengakses sumber daya (panggilan ke apa yang disebut url non-sumber daya).

Juga, semua permintaan melalui beberapa tahap :

  • RequestReceived - tahap ketika permintaan diterima oleh pawang dan belum dipindahkan lebih jauh di sepanjang rantai pawang;
  • ResponseStarted - header respons dikirim, tetapi sebelum mengirim badan respons. Dihasilkan untuk kueri panjang (mis. watch );
  • ResponseComplete - badan respons dikirim, lebih banyak informasi tidak akan dikirim;
  • Panic - events dihasilkan ketika keadaan darurat terdeteksi.

Anda dapat menggunakan omitStages untuk melewati tahapan apa pun.

Dalam file kebijakan, kami dapat menjelaskan beberapa bagian dengan tingkat pencatatan yang berbeda. Aturan pencocokan pertama yang ditemukan dalam uraian kebijakan akan berlaku.

Daemon kubelet memonitor perubahan manifes dengan konfigurasi api-server, dan jika ada yang terdeteksi, ia me-restart wadah dengan api-server. Tetapi ada detail penting: mereka akan mengabaikan perubahan pada file kebijakan . Setelah membuat perubahan pada file kebijakan, Anda perlu me-restart api-server secara manual. Karena api-server berjalan sebagai pod statis , perintah kubectl delete tidak kubectl delete memulai ulang. Anda harus secara manual membuat docker stop di kube-master di mana kebijakan audit telah diubah:

 docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}') 

Saat Anda mengaktifkan audit, penting untuk diingat bahwa kube-apiserver memiliki muatan yang lebih tinggi . Secara khusus, konsumsi memori untuk menyimpan konteks permintaan meningkat. Logging dimulai hanya setelah mengirim header respons. Selain itu, beban tergantung pada konfigurasi kebijakan audit.

Contoh Kebijakan


Mari kita menganalisis struktur file kebijakan menggunakan contoh.

Berikut ini adalah file policy sederhana untuk mencatat segala sesuatu di tingkat Metadata :

 apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata 

Anda dapat menentukan daftar pengguna ( Users dan ServiceAccounts ) dan grup pengguna dalam kebijakan. Sebagai contoh, ini adalah bagaimana kami akan mengabaikan pengguna sistem, tetapi mencatat segala sesuatu yang lain di tingkat Request :

 apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: None userGroups: - "system:serviceaccounts" - "system:nodes" users: - "system:anonymous" - "system:apiserver" - "system:kube-controller-manager" - "system:kube-scheduler" - level: Request 

Dimungkinkan juga untuk menggambarkan target:

  • namespaces
  • kata kerja ( kata kerja : get , update , delete dan lainnya);
  • sumber daya ( sumber daya , yaitu: pod , configmaps , dll.) dan grup sumber daya ( apiGroups ).

Perhatikan! Sumber daya dan grup sumber daya (grup API, mis. ApiGroups), serta versinya yang dipasang di cluster, dapat diperoleh dengan menggunakan perintah:

 kubectl api-resources kubectl api-versions 

Kebijakan audit berikut disediakan sebagai peragaan praktik terbaik dalam dokumentasi Cloud Alibaba :

 apiVersion: audit.k8s.io/v1beta1 kind: Policy #    RequestReceived omitStages: - "RequestReceived" rules: #   ,     : - level: None users: ["system:kube-proxy"] verbs: ["watch"] resources: - group: "" #  api group   ,    #   Kubernetes,  “core” resources: ["endpoints", "services"] - level: None users: ["system:unsecured"] namespaces: ["kube-system"] verbs: ["get"] resources: - group: "" # core resources: ["configmaps"] - level: None users: ["kubelet"] verbs: ["get"] resources: - group: "" # core resources: ["nodes"] - level: None userGroups: ["system:nodes"] verbs: ["get"] resources: - group: "" # core resources: ["nodes"] - level: None users: - system:kube-controller-manager - system:kube-scheduler - system:serviceaccount:kube-system:endpoint-controller verbs: ["get", "update"] namespaces: ["kube-system"] resources: - group: "" # core resources: ["endpoints"] - level: None users: ["system:apiserver"] verbs: ["get"] resources: - group: "" # core resources: ["namespaces"] #     read-only URLs: - level: None nonResourceURLs: - /healthz* - /version - /swagger* #   ,     “”: - level: None resources: - group: "" # core resources: ["events"] #   Secret, ConfigMap  TokenReview    , #         - level: Metadata resources: - group: "" # core resources: ["secrets", "configmaps"] - group: authentication.k8s.io resources: ["tokenreviews"] #   get, list  watch   ;    - level: Request verbs: ["get", "list", "watch"] resources: - group: "" # core - group: "admissionregistration.k8s.io" - group: "apps" - group: "authentication.k8s.io" - group: "authorization.k8s.io" - group: "autoscaling" - group: "batch" - group: "certificates.k8s.io" - group: "extensions" - group: "networking.k8s.io" - group: "policy" - group: "rbac.authorization.k8s.io" - group: "settings.k8s.io" - group: "storage.k8s.io" #        API - level: RequestResponse resources: - group: "" # core - group: "admissionregistration.k8s.io" - group: "apps" - group: "authentication.k8s.io" - group: "authorization.k8s.io" - group: "autoscaling" - group: "batch" - group: "certificates.k8s.io" - group: "extensions" - group: "networking.k8s.io" - group: "policy" - group: "rbac.authorization.k8s.io" - group: "settings.k8s.io" - group: "storage.k8s.io" #         - level: Metadata 


Contoh kebijakan audit yang baik lainnya adalah profil yang digunakan dalam GCE .

Untuk respons cepat terhadap peristiwa audit, dimungkinkan untuk menggambarkan webhook . Masalah ini diungkapkan dalam dokumentasi resmi , saya akan meninggalkannya di luar ruang lingkup artikel ini.

Ringkasan


Artikel ini memberikan ikhtisar mekanisme keamanan dasar di kluster Kubernetes yang memungkinkan Anda membuat akun pengguna yang dipersonalisasi, membagikan hak-hak mereka, dan mencatat tindakan mereka. Saya harap ini berguna bagi mereka yang dihadapkan dengan pertanyaan-pertanyaan seperti itu dalam teori atau sudah dalam praktik. Saya juga merekomendasikan agar Anda melihat daftar bahan-bahan lain tentang topik keamanan di Kubernetes, yang tercantum dalam "PS" - mungkin di antara mereka Anda akan menemukan rincian yang diperlukan tentang masalah yang relevan bagi Anda.

PS


Baca juga di blog kami:

Source: https://habr.com/ru/post/id468679/


All Articles