ABC Keamanan di Kubernetes: Otentikasi, Otorisasi, Audit

ABC Keamanan di Kubernetes: Otentikasi, Otorisasi, Audit

Cepat atau lambat, dalam pengoperasian sistem apa pun, masalah keamanan muncul: memastikan otentikasi, pemisahan hak, audit, dan tugas lainnya. Sudah dibuat untuk Kubernetes banyak solusi, yang memungkinkan Anda mencapai kepatuhan terhadap standar bahkan di lingkungan yang sangat menuntut... Materi yang sama dikhususkan untuk aspek dasar keamanan yang diterapkan dalam mekanisme bawaan K8. Pertama-tama, ini akan berguna bagi mereka yang mulai mengenal Kubernetes - sebagai titik awal untuk mempelajari masalah terkait keamanan.

Otentikasi

Ada dua jenis pengguna di Kubernetes:

  • Akun Layanan — akun yang dikelola oleh Kubernetes API;
  • pengguna — pengguna “normal” yang dikelola oleh layanan eksternal dan independen.

Perbedaan utama antara tipe-tipe ini adalah untuk Akun Layanan terdapat objek khusus di API Kubernetes (disebut demikian - ServiceAccounts), yang terikat pada namespace dan sekumpulan data otorisasi yang disimpan dalam cluster dalam objek bertipe Rahasia. Pengguna tersebut (Akun Layanan) terutama dimaksudkan untuk mengelola hak akses ke API Kubernetes dari proses yang berjalan di cluster Kubernetes.

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

Setiap permintaan API dikaitkan dengan Akun Layanan, Pengguna, atau dianggap anonim.

Data autentikasi pengguna meliputi:

  • Nama Pengguna — nama pengguna (peka huruf besar-kecil!);
  • UID - string identifikasi pengguna yang dapat dibaca mesin yang “lebih konsisten dan unik dibandingkan nama pengguna”;
  • Grup — daftar grup tempat pengguna berada;
  • ekstra — kolom tambahan yang dapat digunakan oleh mekanisme otorisasi.

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

Selain itu, dimungkinkan untuk menggunakan beberapa skema otorisasi secara bersamaan. Secara default, klaster menggunakan:

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

Pertanyaan tentang pengelolaan ServiceAccounts berada di luar cakupan artikel ini, namun bagi mereka yang ingin memahami masalah ini lebih detail, saya sarankan memulai dengan halaman dokumentasi resmi. Kami akan melihat lebih dekat masalah cara kerja sertifikat X509.

Sertifikat untuk pengguna (X.509)

Cara klasik bekerja dengan sertifikat meliputi:

  • pembuatan kunci:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • menghasilkan permintaan sertifikat:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • memproses permintaan sertifikat menggunakan kunci CA cluster Kubernetes, memperoleh sertifikat pengguna (untuk mendapatkan sertifikat, Anda harus menggunakan akun yang memiliki akses ke kunci CA cluster Kubernetes, yang secara default terletak di /etc/kubernetes/pki/ca.key):
    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 untuk instalasi cluster tertentu):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • atau bagaimana tidakopsi yang direkomendasikan - Anda tidak perlu menentukan sertifikat root (maka kubectl tidak akan memeriksa kebenaran server api cluster):
      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, dalam file .kube/config konfigurasi seperti ini akan dibuat:

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 mempermudah mentransfer konfigurasi antara akun dan server, ada gunanya mengedit nilai kunci berikut:

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

Untuk melakukan ini, Anda dapat menyandikan file yang ditentukan di dalamnya menggunakan base64 dan mendaftarkannya di konfigurasi, menambahkan akhiran ke nama kunci -data, yaitu. setelah menerima certificate-authority-data dan lain-lain

Sertifikat dengan kubeadm

Dengan dirilisnya Kubernet 1.15 bekerja dengan sertifikat menjadi lebih mudah berkat dukungan versi alfa di utilitas kubeadm. Misalnya, seperti inilah tampilan pembuatan file konfigurasi dengan kunci pengguna:

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

NB: Diperlukan alamat iklan dapat ditemukan di konfigurasi api-server, yang secara default terletak di /etc/kubernetes/manifests/kube-apiserver.yaml.

Konfigurasi yang dihasilkan akan ditampilkan ke stdout. Itu perlu disimpan ~/.kube/config akun pengguna atau ke file yang ditentukan dalam variabel lingkungan KUBECONFIG.

Menggali lebih dalam

Bagi yang ingin memahami permasalahan yang dijelaskan lebih mendalam:

Otorisasi

Akun resmi default tidak memiliki hak untuk beroperasi di cluster. Untuk memberikan izin, Kubernetes menerapkan mekanisme otorisasi.

Sebelum versi 1.6, Kubernetes menggunakan jenis otorisasi yang disebut ABAC (Kontrol akses berbasis atribut). Detail tentangnya dapat ditemukan di dokumentasi resmi. Pendekatan ini saat ini dianggap warisan, namun Anda masih dapat menggunakannya bersama jenis autentikasi lainnya.

Cara saat ini (dan lebih fleksibel) untuk membagi hak akses ke sebuah cluster disebut RBAC (Kontrol akses berbasis peran). Telah dinyatakan stabil sejak versi Kubernet 1.8. RBAC menerapkan model hak yang melarang segala sesuatu yang tidak diizinkan secara eksplisit.
Untuk mengaktifkan RBAC, Anda perlu memulai server api Kubernetes dengan parameter --authorization-mode=RBAC. Parameter disetel dalam manifes dengan konfigurasi server api, yang secara default terletak di sepanjang jalur /etc/kubernetes/manifests/kube-apiserver.yaml, di bagian command. Namun, RBAC sudah diaktifkan secara default, jadi kemungkinan besar Anda tidak perlu khawatir: Anda dapat memverifikasi ini dengan nilainya authorization-mode (dalam yang telah disebutkan kube-apiserver.yaml). Omong-omong, di antara maknanya mungkin ada jenis otorisasi lain (node, webhook, always allow), tetapi kami akan membiarkan pertimbangannya di luar cakupan materi.

Omong-omong, kami sudah menerbitkannya sebuah artikel dengan penjelasan yang cukup rinci tentang prinsip dan fitur bekerja dengan RBAC, maka selanjutnya saya akan membatasi diri pada daftar singkat dasar-dasar dan contohnya.

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

  • Role и ClusterRole — peran yang berfungsi untuk menjelaskan hak akses:
  • Role memungkinkan Anda menjelaskan hak dalam namespace;
  • ClusterRole - di dalam klaster, termasuk objek spesifik klaster seperti node, url non-sumber daya (yaitu tidak terkait dengan sumber daya Kubernetes - misalnya, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - digunakan untuk mengikat Role и ClusterRole ke pengguna, grup pengguna, atau ServiceAccount.

Entitas Role dan RoleBinding dibatasi oleh namespace, yaitu harus berada dalam namespace yang sama. Namun, RoleBinding dapat mereferensikan ClusterRole, yang memungkinkan Anda membuat sekumpulan izin umum dan mengontrol akses menggunakannya.

Peran menggambarkan hak menggunakan seperangkat aturan yang berisi:

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

Analisis lebih rinci tentang otorisasi di Kubernetes dapat ditemukan di halaman dokumentasi resmi. Sebagai gantinya (atau lebih tepatnya, sebagai tambahan), saya akan memberikan contoh yang menggambarkan karyanya.

Contoh entitas RBAC

Sederhana Role, yang memungkinkan Anda mendapatkan daftar dan status pod serta memantaunya di namespace 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 ClusterRole, yang memungkinkan Anda mendapatkan daftar dan status pod serta memantaunya di seluruh cluster:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # секции "namespace" нет, так как ClusterRole задействует весь кластер
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

Contoh RoleBinding, yang memungkinkan pengguna mynewuser pod "baca" di namespace 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:

ABC Keamanan di Kubernetes: Otentikasi, Otorisasi, Audit

Komponen utama Kubernetes yang bertanggung jawab untuk memproses permintaan adalah server api. Semua operasi di cluster melewatinya. Anda dapat membaca lebih lanjut tentang mekanisme internal ini di artikel “Apa yang terjadi di Kubernetes ketika Anda menjalankan kubectl run?'.

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

Dengan demikian, untuk mengaktifkan audit, kita perlu meneruskan tiga parameter yang diperlukan ke container di api-server, yang dijelaskan lebih detail di bawah:

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

Selain ketiga parameter penting ini, ada banyak pengaturan tambahan terkait audit: dari rotasi log hingga deskripsi webhook. Contoh parameter rotasi log:

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

Namun kami tidak akan membahasnya lebih detail - Anda dapat menemukan semua detailnya di dokumentasi kube-apiserver.

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

  1. audit-policy-file — jalur ke file YAML yang menjelaskan kebijakan audit. Kami akan kembali ke isinya nanti, tetapi untuk saat ini saya perhatikan bahwa file tersebut harus dapat dibaca oleh proses server api. Oleh karena itu, perlu untuk memasangnya di dalam wadah, dan 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 — jalur ke file log. Jalurnya juga harus dapat diakses oleh proses server api, jadi kami menjelaskan pemasangannya dengan cara yang sama:
      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. Standarnya adalah json, namun format teks lawas juga tersedia (legacy).

Kebijakan Audit

Sekarang tentang file yang disebutkan yang menjelaskan kebijakan logging. Konsep pertama dari kebijakan audit adalah level, tingkat pencatatan. Mereka adalah sebagai berikut:

  • None - jangan masuk;
  • Metadata — metadata permintaan log: pengguna, waktu permintaan, sumber daya target (pod, namespace, dll.), jenis tindakan (kata kerja), dll.;
  • Request — mencatat metadata dan isi permintaan;
  • RequestResponse — metadata log, isi permintaan, dan isi respons.

Dua tingkat terakhir (Request и RequestResponse) jangan mencatat permintaan yang tidak mengakses sumber daya (akses ke apa yang disebut url non-sumber daya).

Juga semua permintaan diproses beberapa tahap:

  • RequestReceived — tahap ketika permintaan diterima oleh pemroses dan belum dikirimkan lebih lanjut sepanjang rantai pemroses;
  • ResponseStarted — header respons dikirim, tetapi sebelum isi respons dikirim. Dihasilkan untuk kueri yang berjalan lama (misalnya, watch);
  • ResponseComplete — badan tanggapan telah dikirim, tidak ada informasi lagi yang akan dikirim;
  • Panic — peristiwa dihasilkan ketika situasi abnormal terdeteksi.

Untuk melewati langkah apa pun yang dapat Anda gunakan omitStages.

Dalam file kebijakan, kita dapat menjelaskan beberapa bagian dengan tingkat logging yang berbeda. Aturan pencocokan pertama yang ditemukan dalam deskripsi kebijakan akan diterapkan.

Daemon kubelet memonitor perubahan dalam manifes dengan konfigurasi api-server dan, jika ada yang terdeteksi, restart container dengan api-server. Namun ada detail penting: perubahan dalam file kebijakan akan diabaikan olehnya. Setelah melakukan perubahan pada file kebijakan, Anda perlu me-restart server api secara manual. Sejak api-server dimulai sebagai pod statis, tim kubectl delete tidak akan menyebabkannya dimulai ulang. Anda harus melakukannya secara manual docker stop pada kube-masters, dimana kebijakan auditnya telah diubah:

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

Saat mengaktifkan audit, penting untuk mengingat hal itu beban pada kube-apiserver meningkat. Secara khusus, konsumsi memori untuk menyimpan konteks permintaan meningkat. Pencatatan log dimulai hanya setelah header respons dikirim. Bebannya juga bergantung pada konfigurasi kebijakan audit.

Contoh kebijakan

Mari kita lihat struktur file kebijakan menggunakan contoh.

Ini adalah file sederhana policyuntuk mencatat semuanya di level tersebut Metadata:

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

Dalam kebijakan Anda dapat menentukan daftar pengguna (Users и ServiceAccounts) dan kelompok pengguna. Misalnya, ini adalah cara kita mengabaikan pengguna sistem, tetapi mencatat semua hal lainnya pada level tersebut 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:

  • ruang nama (namespaces);
  • kata kerja (kata kerja: get, update, delete dan lain-lain);
  • sumber daya (sumber dayayaitu: pod, configmaps dll.) dan kelompok sumber daya (apiGroups).

Perhatikan! Sumber daya dan grup sumber daya (grup API, yaitu apiGroups), serta versinya yang diinstal di cluster, dapat diperoleh dengan menggunakan perintah:

kubectl api-resources
kubectl api-versions

Kebijakan audit berikut diberikan sebagai demonstrasi praktik terbaik di Dokumentasi Alibaba Cloud:

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 bagus lainnya dari kebijakan audit adalah profil yang digunakan di GCE.

Untuk merespons peristiwa audit dengan cepat, hal ini dimungkinkan jelaskan webhook. Masalah ini tercakup dalam dokumentasi resmi, saya akan membiarkannya di luar cakupan artikel ini.

Hasil

Artikel ini memberikan gambaran umum tentang mekanisme keamanan dasar di cluster Kubernetes, yang memungkinkan Anda membuat akun pengguna yang dipersonalisasi, memisahkan hak-hak mereka, dan mencatat tindakan mereka. Saya harap ini bermanfaat bagi mereka yang menghadapi masalah seperti itu baik secara teori maupun praktik. Saya juga menyarankan Anda membaca daftar materi lain tentang topik keamanan di Kubernetes, yang diberikan di “PS” - mungkin di antara materi tersebut Anda akan menemukan detail yang diperlukan tentang masalah yang relevan bagi Anda.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komentar