A biztonság ABC-je a Kubernetesben: hitelesítés, engedélyezés, auditálás

A biztonság ABC-je a Kubernetesben: hitelesítés, engedélyezés, auditálás

Előbb-utóbb minden rendszer működése során felmerül a biztonság kérdése: a hitelesítés biztosítása, a jogok szétválasztása, az auditálás és egyéb feladatok. Már létrehozva a Kubernetes számára sok megoldás, amelyek lehetővé teszik a szabványoknak való megfelelést még nagyon igényes környezetben is... Ugyanezt az anyagot szenteljük a K8-ak beépített mechanizmusain belül megvalósított biztonság alapvető szempontjainak. Mindenekelőtt azoknak lesz hasznos, akik kezdik ismerkedni a Kubernetes-szel - kiindulópontként a biztonsággal kapcsolatos kérdések tanulmányozásához.

Hitelesítés

A Kubernetesben kétféle felhasználó létezik:

  • Szolgáltatási fiókok — a Kubernetes API által kezelt fiókok;
  • felhasználók — külső, független szolgáltatások által kezelt „normál” felhasználók.

A fő különbség ezen típusok között az, hogy a szolgáltatásfiókokhoz speciális objektumok vannak a Kubernetes API-ban (ezeket így hívják - ServiceAccounts), amelyek egy névtérhez és a Titkok típusú objektumokban a fürtben tárolt jogosultsági adatok halmazához vannak kötve. Az ilyen felhasználók (szolgáltatásfiókok) elsősorban a Kubernetes-fürtben futó folyamatok Kubernetes API-jához való hozzáférési jogok kezelésére szolgálnak.

Az átlagos felhasználóknak nincsenek bejegyzései a Kubernetes API-ban: ezeket külső mechanizmusoknak kell kezelniük. A klaszteren kívül élő emberek vagy folyamatok számára készültek.

Minden API-kérelem vagy szolgáltatásfiókhoz, vagy felhasználóhoz van társítva, vagy névtelennek minősül.

A felhasználói hitelesítési adatok a következőket tartalmazzák:

  • Felhasználónév — felhasználónév (a kis- és nagybetűk megkülönböztetése!);
  • UID - géppel olvasható felhasználóazonosító karakterlánc, amely „konzisztensebb és egyedibb, mint a felhasználónév”;
  • Csoportok — azon csoportok listája, amelyekhez a felhasználó tartozik;
  • külön — további mezők, amelyeket az engedélyezési mechanizmus használhat.

A Kubernetes számos hitelesítési mechanizmust használhat: X509-tanúsítványok, hordozójogkivonatok, hitelesítő proxy, HTTP Basic Auth. Ezekkel a mechanizmusokkal számos engedélyezési sémát valósíthat meg: a jelszavas statikus fájloktól az OpenID OAuth2-ig.

Ezenkívül lehetőség van több engedélyezési séma egyidejű használatára is. Alapértelmezés szerint a fürt a következőket használja:

  • szolgáltatási fiók tokenek – szolgáltatásfiókokhoz;
  • X509 - felhasználóknak.

A ServiceAccounts kezelésével kapcsolatos kérdés túlmutat e cikk keretein, de azoknak, akik szeretnének részletesebben megismerkedni ezzel a kérdéssel, javasoljuk, hogy kezdje hivatalos dokumentációs oldalakon. Részletesebben megvizsgáljuk az X509 tanúsítványok működésének kérdését.

Tanúsítványok felhasználóknak (X.509)

A tanúsítványokkal való munka klasszikus módja a következőket tartalmazza:

  • kulcsgenerálás:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • tanúsítványkérés generálása:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • tanúsítványkérés feldolgozása a Kubernetes-fürt CA-kulcsok használatával, felhasználói tanúsítvány beszerzése (tanúsítvány megszerzéséhez olyan fiókot kell használnia, amely hozzáfér a Kubernetes-fürt CA-kulcsához, amely alapértelmezés szerint /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
  • konfigurációs fájl létrehozása:
    • fürt leírása (adja meg a CA tanúsítványfájl címét és helyét egy adott fürttelepítéshez):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • vagy hogyan nincsajánlott opció - nem kell megadnia a gyökértanúsítványt (akkor a kubectl nem ellenőrzi a fürt api-szerverének helyességét):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • felhasználó hozzáadása a konfigurációs fájlhoz:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • kontextus hozzáadása:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • alapértelmezett kontextus hozzárendelés:
      kubectl config use-context mynewuser-context

A fenti manipulációk után a fájlban .kube/config egy ehhez hasonló konfiguráció jön létre:

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

A konfigurációk fiókok és szerverek közötti átvitelének megkönnyítése érdekében érdemes szerkeszteni a következő kulcsok értékeit:

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

Ehhez a bennük megadott fájlokat a base64 segítségével kódolhatja és regisztrálhatja a konfigurációban, hozzáadva az utótagot a kulcsok nevéhez -data, azaz miután megkapta certificate-authority-data stb

Tanúsítványok kubeadm-mel

A kiadással Kubernetes 1.15 A tanúsítványokkal való munka sokkal könnyebbé vált a támogatás alfa verziójának köszönhetően kubeadm segédprogram. Például így nézhet ki egy konfigurációs fájl létrehozása felhasználói kulcsokkal:

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

NB: Kötelező hirdetési címet megtalálható az api-server konfigurációjában, amely alapértelmezés szerint itt található /etc/kubernetes/manifests/kube-apiserver.yaml.

Az eredményül kapott konfiguráció az stdout-ba kerül. Be kell menteni ~/.kube/config felhasználói fiókba vagy egy környezeti változóban megadott fájlba KUBECONFIG.

Mélyebbre ásni

Azoknak, akik szeretnék alaposabban megérteni a leírt problémákat:

Meghatalmazás

Az alapértelmezett jogosult fióknak nincs joga a fürtön való működéshez. Az engedélyek megadásához a Kubernetes engedélyezési mechanizmust valósít meg.

Az 1.6-os verzió előtt a Kubernetes az elnevezésű engedélyezési típust használta ABAC (Attribútum alapú hozzáférés-vezérlés). Részletek az oldalon találhatók hivatalos dokumentáció. Ez a megközelítés jelenleg örököltnek számít, de továbbra is használhatja más hitelesítési típusokkal együtt.

A fürthöz való hozzáférési jogok felosztásának jelenlegi (és rugalmasabb) módját ún RBAC (Szerepalapú hozzáférés-vezérlés). A verzió óta stabilnak nyilvánították Kubernetes 1.8. Az RBAC olyan jogmodellt valósít meg, amelyben minden, ami nem kifejezetten engedélyezett, tiltott.
Az RBAC engedélyezéséhez, el kell indítania a Kubernetes api-servert a paraméterrel --authorization-mode=RBAC. A paraméterek a jegyzékben az api-szerver konfigurációjával vannak beállítva, amely alapértelmezés szerint az útvonal mentén található /etc/kubernetes/manifests/kube-apiserver.yaml, szakaszban command. Az RBAC azonban már alapértelmezés szerint engedélyezve van, ezért valószínűleg nem kell aggódnia: ezt az értékkel ellenőrizheti authorization-mode (a már említettben kube-apiserver.yaml). A jelentései között egyébként más típusú felhatalmazások is szerepelhetnek (node, webhook, always allow), de ezek megfontolását az anyag keretein kívül hagyjuk.

Egyébként már publikáltunk статью az RBAC-val végzett munka alapelveinek és jellemzőinek meglehetősen részletes leírásával, így a továbbiakban az alapok és a példák rövid felsorolására szorítkozom.

A következő API-entitások használatosak a Kubernetes hozzáférésének szabályozására RBAC-n keresztül:

  • Role и ClusterRole — a hozzáférési jogok leírására szolgáló szerepek:
  • Role lehetővé teszi a jogok leírását egy névtéren belül;
  • ClusterRole - a fürtön belül, beleértve a fürtspecifikus objektumokat, például csomópontokat, nem erőforrás-url-eket (azaz nem Kubernetes-erőforrásokhoz kapcsolódnak - pl. /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - kötéshez használják Role и ClusterRole felhasználóhoz, felhasználói csoporthoz vagy ServiceAccounthoz.

A Role és RoleBinding entitásokat névtér korlátozza, pl. ugyanabban a névtérben kell lennie. A RoleBinding azonban hivatkozhat egy ClusterRole-ra, amely lehetővé teszi általános engedélyek készletének létrehozását és a hozzáférés szabályozását ezek segítségével.

A szerepkörök a következőket tartalmazó szabályokkal írják le a jogokat:

  • API csoportok – lásd hivatalos dokumentáció az apiGroups és a kimenet által kubectl api-resources;
  • erőforrások (erőforrás: pod, namespace, deployment stb.);
  • Igék (igék: set, update és hasonlók).
  • erőforrás nevek (resourceNames) - arra az esetre, ha hozzáférést kell biztosítania egy adott erőforráshoz, és nem az összes ilyen típusú erőforráshoz.

A Kubernetes engedélyezésének részletesebb elemzése a oldalon található hivatalos dokumentáció. Ehelyett (vagy inkább e mellett) példákat hozok, amelyek illusztrálják munkásságát.

Példák RBAC entitásokra

egyszerű Role, amely lehetővé teszi, hogy megkapja a pod-ok listáját és állapotát, és figyelje azokat a névtérben 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"]

Példa ClusterRole, amely lehetővé teszi a tömbök listájának és állapotának lekérését, valamint azok nyomon követését a fürtben:

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

Példa RoleBinding, amely lehetővé teszi a felhasználó számára mynewuser "olvasni" sorokat a névtérben 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

Rendezvény audit

Sematikusan a Kubernetes architektúra a következőképpen ábrázolható:

A biztonság ABC-je a Kubernetesben: hitelesítés, engedélyezés, auditálás

A kérések feldolgozásáért felelős Kubernetes kulcsfontosságú összetevője api-szerver. A fürt összes művelete ezen megy keresztül. Ezekről a belső mechanizmusokról bővebben a " cikkben olvashatMi történik a Kubernetesben a kubectl run futtatásakor?".

A rendszernaplózás egy érdekes funkció a Kubernetesben, amely alapértelmezés szerint le van tiltva. Lehetővé teszi a Kubernetes API összes hívásának naplózását. Ahogy sejtheti, a fürt állapotának figyelésével és módosításával kapcsolatos összes művelet ezen az API-n keresztül történik. Képességeinek jó leírása (szokás szerint) a következő helyen található hivatalos dokumentáció K8s. A továbbiakban megpróbálom egyszerűbb nyelven bemutatni a témát.

Így hogy lehetővé tegye az auditálást, három szükséges paramétert kell átadnunk a konténernek az api-szerverben, amelyeket az alábbiakban részletesebben ismertetünk:

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

Ezen a három szükséges paraméteren kívül számos további beállítás is kapcsolódik az auditáláshoz: a naplóforgatástól a webhook leírásokig. Példa a napló forgatási paramétereire:

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

De nem foglalkozunk velük részletesebben - minden részletet megtalálhat kube-apiserver dokumentáció.

Mint már említettük, az összes paraméter a jegyzékben az api-szerver konfigurációjával van beállítva (alapértelmezés szerint /etc/kubernetes/manifests/kube-apiserver.yaml), a szakaszban command. Térjünk vissza a 3 kötelező paraméterhez, és elemezzük őket:

  1. audit-policy-file — az ellenőrzési szabályzatot leíró YAML-fájl elérési útja. Tartalmára később visszatérünk, de egyelőre megjegyzem, hogy a fájlnak olvashatónak kell lennie az api-server folyamatnak. Ezért szükséges a konténer belsejébe illeszteni, amelyhez a következő kódot adhatja hozzá a konfiguráció megfelelő részeihez:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — a naplófájl elérési útja. Az elérési útnak az api-szerver folyamat számára is elérhetőnek kell lennie, ezért a beszerelését ugyanúgy írjuk le:
      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 — ellenőrzési napló formátuma. Az alapértelmezett a json, de elérhető az örökölt szövegformátum is (legacy).

Ellenőrzési politika

Most az említett fájlról, amely leírja a naplózási szabályzatot. Az ellenőrzési politika első fogalma az level, naplózási szint. Ezek a következők:

  • None - ne jelentkezzen;
  • Metadata — naplókérés metaadatai: felhasználó, kérés ideje, cél erőforrás (pod, névtér stb.), művelet típusa (ige) stb.;
  • Request — a napló metaadatok és a kérelem törzse;
  • RequestResponse — naplózza a metaadatokat, a kérelem törzsét és a válasz törzsét.

Az utolsó két szint (Request и RequestResponse) ne naplózza azokat a kéréseket, amelyek nem fértek hozzá az erőforrásokhoz (az úgynevezett nem erőforrás-url-ekhez való hozzáférés).

Ezenkívül minden kérés átmegy több szakaszban:

  • RequestReceived — az a szakasz, amikor a kérelmet a feldolgozó megkapja, és még nem továbbították a feldolgozók láncán;
  • ResponseStarted — a válaszfejlécek elküldésre kerülnek, de a választörzs elküldése előtt. Hosszan futó lekérdezésekhez generálva (pl. watch);
  • ResponseComplete — a válaszadó szervet elküldték, több információt nem küldenek;
  • Panic — események generálódnak, ha rendellenes helyzetet észlelnek.

Bármely lépés kihagyásához használhatja omitStages.

Egy házirendfájlban több szakaszt is leírhatunk különböző naplózási szintekkel. Az irányelv leírásában található első egyező szabály kerül alkalmazásra.

A kubelet démon az api-szerver konfigurációjával figyeli a jegyzékben bekövetkezett változásokat, és ha ilyeneket észlel, újraindítja a tárolót az api-szerverrel. De van egy fontos részlet: a házirend-fájl módosításait figyelmen kívül hagyja. A házirendfájl módosítása után manuálisan újra kell indítania az api-kiszolgálót. Mivel az api-szerver a következővel indul statikus pod, csapat kubectl delete nem indítja újra. Ezt manuálisan kell megtennie docker stop a kube-masters-en, ahol az ellenőrzési szabályzat megváltozott:

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

Az auditálás engedélyezésekor fontos emlékezni erre a kube-apiserver terhelése nő. Különösen a kéréskörnyezet tárolására szolgáló memóriafelhasználás növekszik. A naplózás csak a válaszfejléc elküldése után kezdődik. A terhelés az ellenőrzési házirend konfigurációjától is függ.

Példák irányelvekre

Nézzük meg a házirend-fájlok szerkezetét példák segítségével.

Itt van egy egyszerű fájl policyszinten naplózni mindent Metadata:

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

A szabályzatban megadhatja a felhasználók listáját (Users и ServiceAccounts) és felhasználói csoportok. Például így figyelmen kívül hagyjuk a rendszerfelhasználókat, de minden mást szinten naplózunk 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

Lehetőség van a célok leírására is:

  • névterek (namespaces);
  • Igék (igék: get, update, delete és mások);
  • erőforrások (erőforrás, nevezetesen: pod, configmaps stb.) és erőforráscsoportok (apiGroups).

Figyelj! Az erőforrások és erőforráscsoportok (API csoportok, azaz apiGroupok), valamint a fürtbe telepített verzióik a következő parancsokkal érhetők el:

kubectl api-resources
kubectl api-versions

Az alábbi könyvvizsgálati politika a legjobb gyakorlatok bemutatásaként szolgál Alibaba Cloud dokumentáció:

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

Az ellenőrzési politika másik jó példája az a GCE-ben használt profil.

Az audit eseményekre való gyors reagálás lehetséges írja le a webhookot. Ezzel a kérdéssel foglalkozik hivatalos dokumentáció, ezt a cikk keretein kívül hagyom.

Eredményei

A cikk áttekintést nyújt a Kubernetes-fürtök alapvető biztonsági mechanizmusairól, amelyek lehetővé teszik személyre szabott felhasználói fiókok létrehozását, jogaik elkülönítését és tevékenységeik rögzítését. Remélem, hasznos lesz azoknak, akik elméletben vagy a gyakorlatban ilyen problémákkal szembesülnek. Azt is javaslom, hogy olvassa el a Kubernetes biztonsági témájával kapcsolatos egyéb anyagok listáját, amely a „PS”-ben található - talán ezek között megtalálja az Ön számára releváns problémákra vonatkozó szükséges részleteket.

PS

Olvassa el blogunkon is:

Forrás: will.com

Hozzászólás