ABC Keselamatan dalam Kubernetes: Pengesahan, Kebenaran, Pengauditan

ABC Keselamatan dalam Kubernetes: Pengesahan, Kebenaran, Pengauditan

Cepat atau lambat, dalam pengendalian mana-mana sistem, isu keselamatan timbul: memastikan pengesahan, pengasingan hak, pengauditan dan tugas lain. Sudah dibuat untuk Kubernetes banyak penyelesaian, yang membolehkan anda mencapai pematuhan piawaian walaupun dalam persekitaran yang sangat mencabar... Bahan yang sama ditumpukan kepada aspek asas keselamatan yang dilaksanakan dalam mekanisme terbina dalam K8. Pertama sekali, ia akan berguna kepada mereka yang mula berkenalan dengan Kubernetes - sebagai titik permulaan untuk mengkaji isu berkaitan keselamatan.

Pengesahan

Terdapat dua jenis pengguna dalam Kubernetes:

  • Akaun Perkhidmatan — akaun yang diuruskan oleh API Kubernetes;
  • pengguna — pengguna “biasa” yang diuruskan oleh perkhidmatan bebas luaran.

Perbezaan utama antara jenis ini ialah untuk Akaun Perkhidmatan terdapat objek khas dalam API Kubernetes (ia dipanggil - ServiceAccounts), yang terikat pada ruang nama dan satu set data kebenaran yang disimpan dalam kelompok dalam objek jenis Rahsia. Pengguna sedemikian (Akaun Perkhidmatan) bertujuan terutamanya untuk mengurus hak akses kepada API Kubernetes bagi proses yang dijalankan dalam kelompok Kubernetes.

Pengguna Biasa tidak mempunyai entri dalam API Kubernetes: ia mesti diuruskan oleh mekanisme luaran. Ia bertujuan untuk orang atau proses yang tinggal di luar kelompok.

Setiap permintaan API dikaitkan dengan sama ada Akaun Perkhidmatan, Pengguna, atau dianggap tanpa nama.

Data pengesahan pengguna termasuk:

  • Nama pengguna — nama pengguna (sensitif huruf besar-kecil!);
  • UID - rentetan pengenalan pengguna yang boleh dibaca mesin yang "lebih konsisten dan unik daripada nama pengguna";
  • kumpulan — senarai kumpulan yang menjadi milik pengguna;
  • tambahan — medan tambahan yang boleh digunakan oleh mekanisme kebenaran.

Kubernetes boleh menggunakan sejumlah besar mekanisme pengesahan: sijil X509, token pembawa, proksi pengesahan, Pengesahan Asas HTTP. Menggunakan mekanisme ini, anda boleh melaksanakan sejumlah besar skim kebenaran: daripada fail statik dengan kata laluan kepada OpenID OAuth2.

Selain itu, adalah mungkin untuk menggunakan beberapa skim kebenaran secara serentak. Secara lalai, kluster menggunakan:

  • token akaun perkhidmatan - untuk Akaun Perkhidmatan;
  • X509 - untuk Pengguna.

Persoalan tentang mengurus ServiceAccounts adalah di luar skop artikel ini, tetapi bagi mereka yang ingin membiasakan diri dengan isu ini dengan lebih terperinci, saya cadangkan bermula dengan halaman dokumentasi rasmi. Kami akan melihat dengan lebih dekat isu cara sijil X509 berfungsi.

Sijil untuk pengguna (X.509)

Cara klasik bekerja dengan sijil melibatkan:

  • penjanaan utama:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • menghasilkan permintaan sijil:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • memproses permintaan sijil menggunakan kunci CA kelompok Kubernetes, mendapatkan sijil pengguna (untuk mendapatkan sijil, anda mesti menggunakan akaun yang mempunyai akses kepada kunci CA kelompok Kubernetes, yang secara lalainya 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
  • mencipta fail konfigurasi:
    • perihalan kluster (nyatakan alamat dan lokasi fail sijil CA untuk pemasangan kluster tertentu):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • atau bagaimana tiadapilihan yang disyorkan - anda tidak perlu menentukan sijil akar (maka kubectl tidak akan menyemak ketepatan pelayan api kluster):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • menambah pengguna pada fail konfigurasi:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • menambah konteks:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • penugasan konteks lalai:
      kubectl config use-context mynewuser-context

Selepas manipulasi di atas, dalam fail .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 memudahkan pemindahan konfigurasi antara akaun dan pelayan, adalah berguna untuk mengedit nilai kekunci berikut:

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

Untuk melakukan ini, anda boleh mengekod fail yang dinyatakan di dalamnya menggunakan base64 dan mendaftarkannya dalam konfigurasi, menambah akhiran pada nama kunci -data, iaitu setelah menerima certificate-authority-data dan lain-lain

Sijil dengan kubeadm

Dengan pelepasan Kubernetes 1.15 bekerja dengan sijil telah menjadi lebih mudah terima kasih kepada versi alfa sokongannya dalam utiliti kubeadm. Sebagai contoh, inilah yang mungkin kelihatan seperti penjanaan fail konfigurasi dengan kunci pengguna:

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

NB: Diperlukan alamat iklan boleh didapati dalam konfigurasi pelayan-api, yang secara lalai terletak di /etc/kubernetes/manifests/kube-apiserver.yaml.

Konfigurasi yang terhasil akan menjadi output kepada stdout. Ia perlu disimpan dalam ~/.kube/config akaun pengguna atau ke fail yang ditentukan dalam pembolehubah persekitaran KUBECONFIG.

Gali Lebih Dalam

Bagi mereka yang ingin memahami isu yang diterangkan dengan lebih teliti:

Kebenaran

Akaun dibenarkan lalai tidak mempunyai hak untuk beroperasi pada kluster. Untuk memberikan kebenaran, Kubernetes melaksanakan mekanisme kebenaran.

Sebelum versi 1.6, Kubernetes menggunakan jenis kebenaran yang dipanggil ABAC (Kawalan capaian berasaskan atribut). Butiran mengenainya boleh didapati di dokumentasi rasmi. Pendekatan ini pada masa ini dianggap warisan, tetapi anda masih boleh menggunakannya bersama jenis pengesahan lain.

Cara semasa (dan lebih fleksibel) membahagikan hak akses kepada kluster dipanggil RBAC (Kawalan capaian berasaskan peranan). Ia telah diisytiharkan stabil sejak versi Kubernetes 1.8. RBAC melaksanakan model hak di mana semua yang tidak dibenarkan secara jelas adalah dilarang.
Untuk mendayakan RBAC, anda perlu memulakan pelayan api Kubernetes dengan parameter --authorization-mode=RBAC. Parameter ditetapkan dalam manifes dengan konfigurasi pelayan api, yang secara lalai terletak di sepanjang laluan /etc/kubernetes/manifests/kube-apiserver.yaml, dalam bahagian command. Walau bagaimanapun, RBAC sudah didayakan secara lalai, jadi kemungkinan besar anda tidak perlu risau tentangnya: anda boleh mengesahkan ini dengan nilai authorization-mode (dalam yang telah disebutkan kube-apiserver.yaml). Ngomong-ngomong, di antara maknanya mungkin terdapat jenis kebenaran lain (node, webhook, always allow), tetapi kami akan meninggalkan pertimbangan mereka di luar skop bahan.

By the way, kami telah pun menerbitkan artikel dengan penerangan yang agak terperinci tentang prinsip dan ciri bekerja dengan RBAC, jadi selanjutnya saya akan menghadkan diri saya kepada penyenaraian ringkas asas dan contoh.

Entiti API berikut digunakan untuk mengawal akses dalam Kubernetes melalui RBAC:

  • Role и ClusterRole — peranan yang berfungsi untuk menerangkan hak akses:
  • Role membolehkan anda menerangkan hak dalam ruang nama;
  • ClusterRole - dalam kluster, termasuk kepada objek khusus kluster seperti nod, url bukan sumber (iaitu tidak berkaitan dengan sumber Kubernetes - contohnya, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - digunakan untuk mengikat Role и ClusterRole kepada pengguna, kumpulan pengguna atau ServiceAccount.

Entiti Peranan dan Pengikat Peranan dihadkan oleh ruang nama, i.e. mesti berada dalam ruang nama yang sama. Walau bagaimanapun, RoleBinding boleh merujuk ClusterRole, yang membolehkan anda membuat set kebenaran generik dan mengawal akses menggunakannya.

Peranan menerangkan hak menggunakan set peraturan yang mengandungi:

  • Kumpulan API - lihat dokumentasi rasmi oleh apiGroups dan output kubectl api-resources;
  • sumber (sumber: pod, namespace, deployment dan sebagainya.);
  • Kata kerja (kata kerja: set, update dan sebagainya).
  • nama sumber (resourceNames) - untuk kes apabila anda perlu menyediakan akses kepada sumber tertentu, dan bukan kepada semua sumber jenis ini.

Analisis kebenaran yang lebih terperinci dalam Kubernetes boleh didapati di halaman dokumentasi rasmi. Sebaliknya (atau sebaliknya, sebagai tambahan kepada ini), saya akan memberikan contoh yang menggambarkan kerjanya.

Contoh entiti RBAC

Mudah Role, yang membolehkan anda mendapatkan senarai dan status pod dan memantaunya dalam ruang nama 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 membolehkan anda mendapatkan senarai dan status pod dan memantaunya di seluruh kelompok:

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 membolehkan pengguna mynewuser pod "baca" dalam ruang nama 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 skematik, seni bina Kubernetes boleh diwakili seperti berikut:

ABC Keselamatan dalam Kubernetes: Pengesahan, Kebenaran, Pengauditan

Komponen utama Kubernetes yang bertanggungjawab untuk memproses permintaan ialah pelayan api. Semua operasi pada kluster melaluinya. Anda boleh membaca lebih lanjut mengenai mekanisme dalaman ini dalam artikel "Apakah yang berlaku dalam Kubernetes apabila anda menjalankan kubectl run?'.

Pengauditan sistem ialah ciri menarik dalam Kubernetes, yang dilumpuhkan secara lalai. Ia membolehkan anda log semua panggilan ke API Kubernetes. Seperti yang anda fikirkan, semua tindakan yang berkaitan dengan pemantauan dan mengubah keadaan kluster dilakukan melalui API ini. Penerangan yang baik tentang keupayaannya boleh (seperti biasa) ditemui dalam dokumentasi rasmi K8s. Seterusnya, saya akan cuba menyampaikan topik dalam bahasa yang lebih mudah.

Oleh itu, untuk membolehkan pengauditan, kita perlu menghantar tiga parameter yang diperlukan kepada bekas dalam api-server, yang diterangkan dengan lebih terperinci 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 tiga parameter yang diperlukan ini, terdapat banyak tetapan tambahan yang berkaitan dengan pengauditan: daripada penggiliran log kepada penerangan webhook. Contoh parameter putaran log:

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

Tetapi kami tidak akan membincangkannya dengan lebih terperinci - anda boleh mendapatkan semua butiran di dalamnya dokumentasi kube-apiserver.

Seperti yang telah disebutkan, semua parameter ditetapkan dalam manifes dengan konfigurasi pelayan api (secara lalai /etc/kubernetes/manifests/kube-apiserver.yaml), dalam bahagian command. Mari kembali kepada 3 parameter yang diperlukan dan menganalisisnya:

  1. audit-policy-file — laluan ke fail YAML yang menerangkan dasar audit. Kami akan kembali kepada kandungannya kemudian, tetapi buat masa ini saya akan ambil perhatian bahawa fail mesti boleh dibaca oleh proses pelayan api. Oleh itu, adalah perlu untuk melekapkannya di dalam bekas, yang mana anda boleh menambah kod berikut pada bahagian 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 — laluan ke fail log. Laluan itu juga mesti boleh diakses kepada proses pelayan api, jadi kami menerangkan 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. Lalainya ialah json, tetapi format teks lama juga tersedia (legacy).

Dasar Audit

Sekarang mengenai fail yang disebutkan yang menerangkan dasar pembalakan. Konsep pertama dasar audit ialah level, tahap pembalakan. Mereka adalah seperti berikut:

  • None - jangan log;
  • Metadata — metadata permintaan log: pengguna, masa permintaan, sumber sasaran (pod, ruang nama, dsb.), jenis tindakan (kata kerja), dsb.;
  • Request — log metadata dan badan permintaan;
  • RequestResponse — log metadata, badan permintaan dan badan tindak balas.

Dua peringkat terakhir (Request и RequestResponse) jangan log permintaan yang tidak mengakses sumber (akses kepada apa yang dipanggil url bukan sumber).

Juga semua permintaan dilalui beberapa peringkat:

  • RequestReceived — peringkat apabila permintaan diterima oleh pemproses dan belum dihantar lebih jauh di sepanjang rangkaian pemproses;
  • ResponseStarted — pengepala respons dihantar, tetapi sebelum badan respons dihantar. Dijana untuk pertanyaan jangka panjang (contohnya, watch);
  • ResponseComplete — badan respons telah dihantar, tiada lagi maklumat akan dihantar;
  • Panic — peristiwa dijana apabila keadaan tidak normal dikesan.

Untuk melangkau mana-mana langkah yang boleh anda gunakan omitStages.

Dalam fail dasar, kami boleh menerangkan beberapa bahagian dengan tahap pengelogan yang berbeza. Peraturan padanan pertama yang terdapat dalam perihalan dasar akan digunakan.

Daemon kubelet memantau perubahan dalam manifes dengan konfigurasi pelayan api dan, jika ada yang dikesan, mulakan semula bekas dengan pelayan api. Tetapi ada butiran penting: perubahan dalam fail dasar akan diabaikan olehnya. Selepas membuat perubahan pada fail dasar, anda perlu memulakan semula pelayan api secara manual. Memandangkan api-server dimulakan sebagai pod statik, pasukan kubectl delete tidak akan menyebabkan ia dimulakan semula. Anda perlu melakukannya secara manual docker stop pada kube-masters, di mana dasar audit telah diubah:

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

Apabila mendayakan pengauditan, adalah penting untuk diingati beban pada kube-apiserver bertambah. Khususnya, penggunaan memori untuk menyimpan konteks permintaan meningkat. Pengelogan bermula hanya selepas pengepala respons dihantar. Beban juga bergantung pada konfigurasi dasar audit.

Contoh dasar

Mari kita lihat struktur fail dasar menggunakan contoh.

Berikut ialah fail ringkas policyuntuk mencatat segala-galanya di peringkat Metadata:

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

Dalam dasar anda boleh menentukan senarai pengguna (Users и ServiceAccounts) dan kumpulan pengguna. Sebagai contoh, ini adalah cara kami akan mengabaikan pengguna sistem, tetapi log semua yang lain pada tahap 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

Ia juga mungkin untuk menerangkan sasaran:

  • ruang nama (namespaces);
  • Kata kerja (kata kerja: get, update, delete dan lain lain);
  • sumber (sumber, Seperti berikut: pod, configmaps dsb.) dan kumpulan sumber (apiGroups).

Perhatikan! Sumber dan kumpulan sumber (kumpulan API, iaitu apiGroups), serta versi mereka yang dipasang dalam kelompok, boleh diperoleh menggunakan arahan:

kubectl api-resources
kubectl api-versions

Dasar audit berikut disediakan sebagai demonstrasi amalan terbaik dalam Dokumentasi Awan 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

Satu lagi contoh dasar audit yang baik ialah profil yang digunakan dalam GCE.

Untuk bertindak balas dengan cepat kepada acara audit, adalah mungkin terangkan webhook. Isu ini diliputi dalam dokumentasi rasmi, saya akan meninggalkannya di luar skop artikel ini.

Keputusan

Artikel ini memberikan gambaran keseluruhan mekanisme keselamatan asas dalam kelompok Kubernetes, yang membolehkan anda membuat akaun pengguna yang diperibadikan, memisahkan hak mereka dan merekodkan tindakan mereka. Saya harap ia akan berguna kepada mereka yang berhadapan dengan isu-isu sebegini secara teori atau praktikal. Saya juga mengesyorkan agar anda membaca senarai bahan lain mengenai topik keselamatan di Kubernetes, yang diberikan dalam "PS" - mungkin di antara mereka anda akan menemui butiran yang diperlukan mengenai masalah yang berkaitan dengan anda.

PS

Baca juga di blog kami:

Sumber: www.habr.com

Tambah komen