ABC bezpečnosti v Kubernetes: autentifikácia, autorizácia, audit

ABC bezpečnosti v Kubernetes: autentifikácia, autorizácia, audit

Skôr či neskôr pri prevádzke akéhokoľvek systému vyvstane otázka bezpečnosti: zabezpečenie autentifikácie, oddelenie práv, audit a iné úlohy. Už vytvorené pre Kubernetes veľa riešení, ktoré umožňujú dosiahnuť súlad s normami aj vo veľmi náročných prostrediach... Rovnaký materiál je venovaný základným aspektom bezpečnosti implementovaným v rámci vstavaných mechanizmov K8s. V prvom rade to bude užitočné pre tých, ktorí sa začínajú zoznamovať s Kubernetes - ako východiskový bod pre štúdium otázok súvisiacich s bezpečnosťou.

overenie pravosti

V Kubernetes existujú dva typy používateľov:

  • Servisné účty — účty spravované pomocou Kubernetes API;
  • užívatelia — „normálnych“ používateľov riadených externými nezávislými službami.

Hlavný rozdiel medzi týmito typmi je v tom, že pre servisné účty existujú špeciálne objekty v Kubernetes API (nazývajú sa tak - ServiceAccounts), ktoré sú viazané na menný priestor a množinu autorizačných údajov uložených v klastri v objektoch typu Tajomstvá. Takíto používatelia (servisné účty) sú primárne určení na správu prístupových práv k Kubernetes API procesov spustených v klastri Kubernetes.

Bežní používatelia nemajú položky v Kubernetes API: musia byť spravovaní externými mechanizmami. Sú určené pre ľudí alebo procesy žijúce mimo klastra.

Každá požiadavka API je spojená buď s účtom služby, s používateľom, alebo sa považuje za anonymnú.

Overovacie údaje používateľa zahŕňajú:

  • užívateľské meno — používateľské meno (rozlišujú sa malé a veľké písmená!);
  • UID - strojovo čitateľný identifikačný reťazec používateľa, ktorý je „konzistentnejší a jedinečný ako používateľské meno“;
  • Skupiny — zoznam skupín, do ktorých používateľ patrí;
  • extra — dodatočné polia, ktoré môže použiť autorizačný mechanizmus.

Kubernetes môže používať veľké množstvo autentifikačných mechanizmov: certifikáty X509, tokeny nosičov, autentifikačný proxy, HTTP Basic Auth. Pomocou týchto mechanizmov môžete implementovať veľké množstvo autorizačných schém: od statického súboru s heslami až po OpenID OAuth2.

Okrem toho je možné súčasne využívať niekoľko autorizačných schém. V predvolenom nastavení klaster používa:

  • tokeny servisných účtov – pre účty služieb;
  • X509 – pre používateľov.

Otázka o správe ServiceAccounts presahuje rámec tohto článku, ale pre tých, ktorí sa chcú s touto problematikou oboznámiť podrobnejšie, odporúčam začať s stránky oficiálnej dokumentácie. Podrobnejšie sa pozrieme na problematiku fungovania certifikátov X509.

Certifikáty pre používateľov (X.509)

Klasický spôsob práce s certifikátmi zahŕňa:

  • generácia kľúča:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • vygenerovanie žiadosti o certifikát:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • spracovanie žiadosti o certifikát pomocou kľúčov CA klastra Kubernetes, získanie používateľského certifikátu (na získanie certifikátu musíte použiť účet, ktorý má prístup ku kľúču CA klastra Kubernetes, ktorý sa štandardne nachádza v /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
  • vytvorenie konfiguračného súboru:
    • popis klastra (uveďte adresu a umiestnenie súboru certifikátu CA pre konkrétnu inštaláciu klastra):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • alebo ako nieodporúčaná možnosť - nemusíte špecifikovať koreňový certifikát (kubectl potom nebude kontrolovať správnosť api-servera klastra):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • pridanie používateľa do konfiguračného súboru:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • pridanie kontextu:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • predvolené priradenie kontextu:
      kubectl config use-context mynewuser-context

Po vyššie uvedených manipuláciách v súbore .kube/config vytvorí sa takáto konfigurácia:

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

Na uľahčenie prenosu konfigurácie medzi účtami a servermi je užitočné upraviť hodnoty nasledujúcich kľúčov:

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

Ak to chcete urobiť, môžete zakódovať súbory v nich špecifikované pomocou base64 a zaregistrovať ich v konfigurácii pridaním prípony k názvu kľúčov -data, t.j. po prijatí certificate-authority-data atď

Certifikáty s kubeadm

S uvoľnením Kubernetes 1.15 práca s certifikátmi sa výrazne zjednodušila vďaka alfa verzii jej podpory v nástroj kubeadm. Takto môže teraz napríklad vyzerať generovanie konfiguračného súboru s používateľskými kľúčmi:

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

NB: Požadovaný inzerovať adresu nájdete v konfigurácii api-server, ktorá sa štandardne nachádza v /etc/kubernetes/manifests/kube-apiserver.yaml.

Výsledná konfigurácia bude odoslaná do stdout. Je potrebné ho uložiť ~/.kube/config používateľský účet alebo do súboru špecifikovaného v premennej prostredia KUBECONFIG.

Kop hlbšie

Pre tých, ktorí chcú podrobnejšie porozumieť popísaným problémom:

Povolenie

Predvolené autorizované konto nemá práva na prevádzku v klastri. Na udelenie povolení Kubernetes implementuje autorizačný mechanizmus.

Pred verziou 1.6 používal Kubernetes typ autorizácie tzv ABAC (riadenie prístupu založené na atribútoch). Podrobnosti o ňom nájdete v oficiálna dokumentácia. Tento prístup sa v súčasnosti považuje za starý, ale stále ho môžete používať spolu s inými typmi autentifikácie.

Súčasný (a flexibilnejší) spôsob rozdelenia prístupových práv do klastra je tzv RBAC (Riadenie prístupu na základe rolí). Od verzie bol vyhlásený za stabilný Kubernetes 1.8. RBAC implementuje model práv, v ktorom je zakázané všetko, čo nie je výslovne povolené.
Ak chcete povoliť RBAC, musíte spustiť Kubernetes api-server s parametrom --authorization-mode=RBAC. Parametre sa nastavujú v manifeste s konfiguráciou api-server, ktorá je štandardne umiestnená pozdĺž cesty /etc/kubernetes/manifests/kube-apiserver.yaml, v sekcii command. RBAC je však už v predvolenom nastavení povolený, takže s najväčšou pravdepodobnosťou by ste sa tým nemali obávať: môžete si to overiť hodnotou authorization-mode (v už spomínanom kube-apiserver.yaml). Mimochodom, medzi jeho významy môžu byť aj iné typy autorizácie (node, webhook, always allow), ale ich zváženie necháme mimo rámca materiálu.

Mimochodom, už sme zverejnili статью s pomerne podrobným popisom princípov a vlastností práce s RBAC, preto sa ďalej obmedzím na stručný zoznam základov a príkladov.

Nasledujúce entity API sa používajú na riadenie prístupu v Kubernetes cez RBAC:

  • Role и ClusterRole — roly, ktoré slúžia na opis prístupových práv:
  • Role umožňuje popísať práva v rámci menného priestoru;
  • ClusterRole - v rámci klastra vrátane objektov špecifických pre klaster, ako sú uzly, adresy URL nesúvisiace so zdrojmi (t. j. nesúvisiace so zdrojmi Kubernetes - napr. /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - používa sa na viazanie Role и ClusterRole používateľovi, skupine používateľov alebo servisnému kontu.

Entity Role a RoleBinding sú obmedzené menným priestorom, t.j. musí byť v rovnakom mennom priestore. RoleBinding však môže odkazovať na ClusterRole, čo vám umožňuje vytvoriť sadu všeobecných povolení a riadiť prístup pomocou nich.

Roly popisujú práva pomocou množín pravidiel, ktoré obsahujú:

  • Skupiny API – viď oficiálna dokumentácia pomocou apiGroups a výstupu kubectl api-resources;
  • zdroje (zdroje: pod, namespace, deployment atď.);
  • Slovesá (slovesá: set, update apod).
  • názvy zdrojov (resourceNames) - pre prípad, keď potrebujete poskytnúť prístup ku konkrétnemu zdroju, a nie ku všetkým zdrojom tohto typu.

Podrobnejšiu analýzu autorizácie v Kubernetes nájdete na stránke oficiálna dokumentácia. Namiesto toho (alebo skôr okrem toho) uvediem príklady, ktoré ilustrujú jej prácu.

Príklady entít RBAC

prostý Role, ktorý vám umožňuje získať zoznam a stav modulov a sledovať ich v mennom priestore 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"]

Príklad ClusterRole, ktorá vám umožňuje získať zoznam a stav modulov a monitorovať ich v rámci klastra:

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

Príklad RoleBinding, čo umožňuje užívateľovi mynewuser „read“ pody v mennom priestore 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 udalosti

Schematicky možno architektúru Kubernetes znázorniť takto:

ABC bezpečnosti v Kubernetes: autentifikácia, autorizácia, audit

Kľúčovým komponentom Kubernetes zodpovedným za spracovanie požiadaviek je api-server. Prechádzajú ním všetky operácie na klastri. Viac o týchto vnútorných mechanizmoch si môžete prečítať v článku “Čo sa stane v Kubernetes, keď spustíte kubectl run?".

Audit systému je zaujímavou funkciou v Kubernetes, ktorá je predvolene vypnutá. Umožňuje vám zaznamenávať všetky hovory do rozhrania Kubernetes API. Ako možno uhádnete, všetky akcie súvisiace s monitorovaním a zmenou stavu klastra sa vykonávajú prostredníctvom tohto rozhrania API. Dobrý popis jeho schopností možno (ako obvykle) nájsť v oficiálna dokumentácia K8s. Ďalej sa pokúsim podať tému v jednoduchšom jazyku.

Takže, na umožnenie auditu, musíme do kontajnera v api-serveri odovzdať tri požadované parametre, ktoré sú podrobnejšie popísané nižšie:

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

Okrem týchto troch nevyhnutných parametrov existuje mnoho ďalších nastavení súvisiacich s auditovaním: od rotácie denníkov až po popisy webhookov. Príklad parametrov rotácie denníka:

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

Nebudeme sa im však podrobnejšie venovať - ​​všetky podrobnosti nájdete v dokumentácia kube-apiserver.

Ako už bolo spomenuté, všetky parametre sú nastavené v manifeste s konfiguráciou api-server (štandardne /etc/kubernetes/manifests/kube-apiserver.yaml), v sekcii command. Vráťme sa k 3 požadovaným parametrom a analyzujeme ich:

  1. audit-policy-file — cesta k súboru YAML s popisom politiky auditu. K jeho obsahu sa vrátime neskôr, ale zatiaľ podotýkam, že súbor musí byť čitateľný procesom api-server. Preto je potrebné ho namontovať do kontajnera, pre ktorý môžete do príslušných sekcií konfigurácie pridať nasledujúci kód:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — cesta k súboru denníka. Cesta musí byť prístupná aj procesu api-server, takže jej pripojenie popisujeme rovnakým spôsobom:
      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 — formát denníka auditu. Predvolená hodnota je json, ale k dispozícii je aj starý textový formát (legacy).

Zásady auditu

Teraz o spomínanom súbore popisujúcom politiku protokolovania. Prvým konceptom politiky auditu je level, úroveň protokolovania. Sú nasledovné:

  • None - neprihlasovať sa;
  • Metadata — metadáta žiadosti o denník: používateľ, čas požiadavky, cieľový zdroj (pod, priestor názvov atď.), typ akcie (sloveso) atď.;
  • Request — metaúdaje denníka a telo žiadosti;
  • RequestResponse — metaúdaje denníka, telo žiadosti a telo odpovede.

Posledné dve úrovne (Request и RequestResponse) nezaprotokolovať požiadavky, ktoré nepristupovali k zdrojom (prístupy k tzv. non-resources url).

Všetky žiadosti tiež prechádzajú niekoľkých etáp:

  • RequestReceived — štádium, keď spracovateľ prijme požiadavku a ešte nebola odoslaná ďalej v reťazci spracovateľov;
  • ResponseStarted — hlavičky odpovede sa odošlú, ale pred odoslaním tela odpovede. Generované pre dlhotrvajúce dopyty (napr. watch);
  • ResponseComplete — telo odpovede bolo zaslané, nebudú sa posielať žiadne ďalšie informácie;
  • Panic — udalosti sa generujú, keď sa zistí abnormálna situácia.

Ak chcete preskočiť všetky kroky, ktoré môžete použiť omitStages.

V súbore politiky môžeme opísať niekoľko sekcií s rôznymi úrovňami protokolovania. Použije sa prvé pravidlo zhody nájdené v popise politiky.

Démon kubelet monitoruje zmeny v manifeste s konfiguráciou api-server a ak sa nejaké zistia, reštartuje kontajner s api-serverom. Ale je tu dôležitý detail: zmeny v súbore politiky budú ignorované. Po vykonaní zmien v súbore politiky budete musieť reštartovať api-server manuálne. Keďže api-server je spustený ako statický pod, tím kubectl delete nespôsobí jeho reštart. Budete to musieť urobiť ručne docker stop na kube-masters, kde boli zmenené zásady auditu:

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

Pri povolení auditovania je dôležité pamätať na to zaťaženie na kube-apiserver sa zvyšuje. Najmä sa zvyšuje spotreba pamäte na ukladanie kontextu požiadavky. Protokolovanie sa začne až po odoslaní hlavičky odpovede. Zaťaženie závisí aj od konfigurácie politiky auditu.

Príklady politík

Pozrime sa na štruktúru súborov politík pomocou príkladov.

Tu je jednoduchý súbor policyzaznamenať všetko na úrovni Metadata:

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

V politike môžete zadať zoznam používateľov (Users и ServiceAccounts) a skupiny používateľov. Napríklad takto budeme ignorovať používateľov systému, ale všetko ostatné logujeme na úrovni 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

Je tiež možné opísať ciele:

  • menné priestory (namespaces);
  • Slovesá (slovesá: get, update, delete a ďalšie);
  • zdroje (zdrojea to: pod, configmaps atď.) a skupiny zdrojov (apiGroups).

Poznámka! Prostriedky a skupiny prostriedkov (skupiny API, t. j. apiGroups), ako aj ich verzie nainštalované v klastri, je možné získať pomocou príkazov:

kubectl api-resources
kubectl api-versions

Nasledujúce zásady auditu sú uvedené ako demonštrácia osvedčených postupov v Dokumentácia 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

Ďalším dobrým príkladom politiky auditu je profil používaný v GCE.

Ak chcete rýchlo reagovať na udalosti auditu, je to možné opísať webhook. Táto problematika je pokrytá v oficiálna dokumentácia, nechám to mimo rámca tohto článku.

Výsledky

Článok poskytuje prehľad základných bezpečnostných mechanizmov v klastroch Kubernetes, ktoré vám umožňujú vytvárať personalizované používateľské účty, oddeľovať ich práva a zaznamenávať ich akcie. Dúfam, že to bude užitočné pre tých, ktorí sa s takýmito problémami stretávajú v teórii alebo v praxi. Odporúčam tiež, aby ste si prečítali zoznam ďalších materiálov na tému bezpečnosti v Kubernetes, ktorý je uvedený v „PS“ - možno medzi nimi nájdete potrebné podrobnosti o problémoch, ktoré sú pre vás relevantné.

PS

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár