Kubernetese turvalisuse ABC: autentimine, autoriseerimine, auditeerimine

Kubernetese turvalisuse ABC: autentimine, autoriseerimine, auditeerimine

Varem või hiljem kerkib iga süsteemi töös üles turvalisuse küsimus: autentimise tagamine, õiguste eraldamine, auditeerimine ja muud ülesanded. Kubernetese jaoks juba loodud palju lahendusi, mis võimaldavad saavutada vastavust standarditele ka väga nõudlikes keskkondades... Sama materjal on pühendatud K8-de sisseehitatud mehhanismide raames rakendatavatele turvalisuse põhiaspektidele. Esiteks on see kasulik neile, kes alustavad Kubernetesega tutvust - turvalisusega seotud küsimuste uurimise lähtepunktina.

Autentimine

Kubernetesis on kahte tüüpi kasutajaid:

  • Teenusekontod — Kubernetes API hallatavad kontod;
  • kasutajad — "tavalised" kasutajad, mida haldavad välised sõltumatud teenused.

Peamine erinevus nende tüüpide vahel seisneb selles, et teenusekontode jaoks on Kubernetes API-s spetsiaalsed objektid (neid nimetatakse nii - ServiceAccounts), mis on seotud nimeruumi ja autoriseerimisandmete kogumiga, mis on salvestatud klastris tüüpi Saladused objektides. Sellised kasutajad (teenusekontod) on mõeldud peamiselt Kubernetese klastris töötavate protsesside Kubernetes API-le juurdepääsuõiguste haldamiseks.

Tavakasutajatel pole Kubernetes API-s kirjeid: neid peavad haldama välised mehhanismid. Need on mõeldud väljaspool klastrit elavatele inimestele või protsessidele.

Iga API päring on seotud kas teenusekonto või kasutajaga või loetakse anonüümseks.

Kasutaja autentimisandmed hõlmavad järgmist:

  • kasutajanimi — kasutajanimi (tõutundlik!);
  • UID - masinloetav kasutaja identifitseerimisstring, mis on "ühtsam ja ainulaadsem kui kasutajanimi";
  • grupid — rühmade loetelu, kuhu kasutaja kuulub;
  • lisatasu — täiendavad väljad, mida autoriseerimismehhanism saab kasutada.

Kubernetes saab kasutada suurt hulka autentimismehhanisme: X509 sertifikaadid, kandja märgid, autentimispuhverserver, HTTP põhiautentimine. Neid mehhanisme kasutades saate rakendada suurt hulka autoriseerimisskeeme: alates staatilisest paroolidega failist kuni OpenID OAuth2-ni.

Lisaks on võimalik kasutada korraga mitut autoriseerimisskeemi. Vaikimisi kasutab klaster järgmist:

  • teenusekonto märgid – teenusekontode jaoks;
  • X509 - kasutajatele.

Küsimus ServiceAccountsi haldamise kohta ei kuulu selle artikli raamidesse, kuid neile, kes soovivad selle probleemiga lähemalt tutvuda, soovitan alustada ametlikud dokumentatsioonilehed. Vaatame lähemalt, kuidas X509 sertifikaadid töötavad.

Sertifikaadid kasutajatele (X.509)

Klassikaline sertifikaatidega töötamise viis hõlmab järgmist:

  • võtme genereerimine:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • sertifikaaditaotluse genereerimine:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • sertifikaadipäringu töötlemine Kubernetese klastri CA võtmete abil, kasutaja sertifikaadi hankimine (sertifikaadi saamiseks tuleb kasutada kontot, millel on juurdepääs Kubernetese klastri CA võtmele, mis vaikimisi asub /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
  • konfiguratsioonifaili loomine:
    • klastri kirjeldus (määrake CA sertifikaadi faili aadress ja asukoht konkreetse klastri installi jaoks):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • või kuidas eisoovitatav valik - te ei pea juursertifikaati määrama (siis ei kontrolli kubectl klastri api-serveri õigsust):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • kasutaja lisamine konfiguratsioonifaili:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • konteksti lisamine:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • vaikekonteksti määramine:
      kubectl config use-context mynewuser-context

Pärast ülaltoodud manipuleerimisi failis .kube/config luuakse selline konfiguratsioon:

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

Kontode ja serverite vahel konfiguratsiooni ülekandmise hõlbustamiseks on kasulik redigeerida järgmiste võtmete väärtusi:

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

Selleks saab base64 abil kodeerida neis määratud failid ja registreerida need konfiguratsioonis, lisades klahvide nimele järelliide -data, st. olles saanud certificate-authority-data jne

Sertifikaadid kubeadmiga

Koos vabastamisega Kubernetes 1.15 sertifikaatidega töötamine on muutunud palju lihtsamaks tänu selle toe alfaversioonile kubeadm utiliit. Näiteks võib kasutajavõtmete abil konfiguratsioonifaili genereerimine nüüd välja näha selline:

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

NB: Nõutud reklaami aadress leiate api-serveri konfiguratsioonist, mis vaikimisi asub /etc/kubernetes/manifests/kube-apiserver.yaml.

Saadud konfiguratsioon väljastatakse stdout-i. See tuleb sisse salvestada ~/.kube/config kasutajakontole või keskkonnamuutujas määratud failile KUBECONFIG.

Kaeva sügavamale

Neile, kes soovivad kirjeldatud probleemidest põhjalikumalt aru saada:

luba

Vaikimisi volitatud kontol ei ole klastris tegutsemiseks õigusi. Lubade andmiseks rakendab Kubernetes autoriseerimismehhanismi.

Enne versiooni 1.6 kasutas Kubernetes autoriseerimistüüpi nimega ABAC (Atribuudipõhine juurdepääsukontroll). Üksikasjad selle kohta leiate aadressilt ametlik dokumentatsioon. Seda lähenemisviisi peetakse praegu pärandiks, kuid saate seda siiski kasutada koos teiste autentimistüüpidega.

Praegust (ja paindlikumat) viisi klastri juurdepääsuõiguste jagamiseks nimetatakse RBAC (Rollipõhine juurdepääsu kontroll). Alates versioonist on see stabiilseks kuulutatud Kubernetes 1.8. RBAC rakendab õiguste mudelit, milles kõik, mis pole selgesõnaliselt lubatud, on keelatud.
RBAC lubamiseks, peate parameetriga käivitama Kubernetes api-serveri --authorization-mode=RBAC. Parameetrid määratakse manifestis api-serveri konfiguratsiooniga, mis vaikimisi asub tee ääres /etc/kubernetes/manifests/kube-apiserver.yaml, jaotises command. RBAC on aga vaikimisi juba lubatud, nii et tõenäoliselt ei peaks te selle pärast muretsema: saate seda kontrollida väärtusega authorization-mode (juba mainitud kube-apiserver.yaml). Muide, selle tähenduste hulgas võib olla ka muud tüüpi volitusi (node, webhook, always allow), kuid jätame nende käsitlemise materjalist väljapoole.

Muide, oleme juba avaldanud artiklit üsna üksikasjaliku kirjeldusega RBAC-iga töötamise põhimõtetest ja omadustest, nii et edaspidi piirdun lühidalt põhitõdede ja näidetega.

Kubernetesis RBAC-i kaudu juurdepääsu juhtimiseks kasutatakse järgmisi API-üksusi:

  • Role и ClusterRole — rollid, mis kirjeldavad juurdepääsuõigusi:
  • Role võimaldab kirjeldada õigusi nimeruumis;
  • ClusterRole - klastri sees, sealhulgas klastrispetsiifiliste objektide jaoks, nagu sõlmed, mitteressursside URL-id (st ei ole seotud Kubernetese ressurssidega - näiteks /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - kasutatakse köitmiseks Role и ClusterRole kasutajale, kasutajarühmale või teenusekontole.

Olemid Role ja RoleBinding on piiratud nimeruumiga, st. peab asuma samas nimeruumis. Kuid RoleBinding võib viidata ClusterRole'ile, mis võimaldab teil luua üldiste õiguste komplekti ja juhtida juurdepääsu nende abil.

Rollid kirjeldavad õigusi, kasutades reeglite komplekte, mis sisaldavad:

  • API rühmad – vt ametlik dokumentatsioon apiGroupsi ja väljundi järgi kubectl api-resources;
  • ressursid (ressursid: pod, namespace, deployment ja nii edasi.);
  • Tegusõnad (tegusõnad: set, update jne).
  • ressursside nimed (resourceNames) - juhuks, kui peate võimaldama juurdepääsu konkreetsele ressursile, mitte kõigile seda tüüpi ressurssidele.

Täpsema Kubernetes autoriseerimise analüüsi leiate lehelt ametlik dokumentatsioon. Selle asemel (õigemini, lisaks sellele) toon näiteid, mis illustreerivad tema tööd.

Näited RBAC-üksustest

Lihtne Role, mis võimaldab hankida kaunade loendit ja olekut ning jälgida neid nimeruumis 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"]

Näide ClusterRole, mis võimaldab teil saada kaunade loendit ja olekut ning jälgida neid kogu klastris:

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

Näide RoleBinding, mis võimaldab kasutajal mynewuser "lugeda" kaunasid nimeruumis 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

Ürituse audit

Skemaatiliselt saab Kubernetese arhitektuuri kujutada järgmiselt:

Kubernetese turvalisuse ABC: autentimine, autoriseerimine, auditeerimine

Päringute töötlemise eest vastutav Kubernetese põhikomponent on api-server. Kõik klastri toimingud läbivad selle. Lisateavet nende sisemiste mehhanismide kohta saate lugeda artiklist "Mis juhtub Kubernetesis, kui käivitate kubectl run?'.

Süsteemi auditeerimine on Kubernetese huvitav funktsioon, mis on vaikimisi keelatud. See võimaldab teil logida kõik Kubernetes API kõned. Nagu võite arvata, tehakse kõik klastri oleku jälgimise ja muutmisega seotud toimingud selle API kaudu. Selle võimaluste hea kirjelduse leiate (nagu tavaliselt). ametlik dokumentatsioon K8s. Järgmisena püüan teemat lihtsamas keeles esitada.

Niisiis, auditeerimise võimaldamiseks, peame api-serveris olevale konteinerile edastama kolm nõutavat parameetrit, mida kirjeldatakse üksikasjalikumalt allpool:

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

Lisaks nendele kolmele vajalikule parameetrile on auditeerimisega seotud palju lisaseadeid: logi pööramisest veebihaagi kirjeldusteni. Näide logi pööramise parameetritest:

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

Kuid me ei peatu neil üksikasjalikumalt - kõik üksikasjad leiate siit kube-apiserveri dokumentatsioon.

Nagu juba mainitud, määratakse kõik parameetrid manifestis api-serveri konfiguratsiooniga (vaikimisi /etc/kubernetes/manifests/kube-apiserver.yaml), jaotises command. Pöördume tagasi 3 nõutava parameetri juurde ja analüüsime neid:

  1. audit-policy-file — auditipoliitikat kirjeldava YAML-faili tee. Tuleme selle sisu juurde hiljem tagasi, kuid praegu märgin, et fail peab olema api-serveri protsessi jaoks loetav. Seetõttu on vaja see paigaldada konteinerisse, mille jaoks saate konfiguratsiooni vastavatesse jaotistesse lisada järgmise koodi:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — logifaili tee. Tee peab olema juurdepääsetav ka api-serveri protsessile, seega kirjeldame selle paigaldamist samal viisil:
      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 — auditi logi formaat. Vaikimisi on json, kuid saadaval on ka pärandtekstivorming (legacy).

Auditipoliitika

Nüüd mainitud logimispoliitikat kirjeldavast failist. Auditipoliitika esimene kontseptsioon on level, logimise tase. Need on järgmised:

  • None - ära logi;
  • Metadata — logi päringu metaandmed: kasutaja, päringu aeg, sihtressurss (pod, nimeruum jne), toimingu tüüp (verb) jne;
  • Request — logi metaandmed ja päringu keha;
  • RequestResponse — logi metaandmed, päringu keha ja vastuse keha.

Viimased kaks taset (Request и RequestResponse) ärge logige päringuid, mis ei pääsenud ligi ressurssidele (juurdepääsud nn mitteressursside URL-idele).

Ka kõik taotlused lähevad läbi mitu etappi:

  • RequestReceived — etapp, mil töötleja saab päringu kätte ja seda ei ole veel töötlejate ahelas edasi edastatud;
  • ResponseStarted — vastuse päised saadetakse, kuid enne vastuse keha saatmist. Loodud pikaajaliste päringute jaoks (näiteks watch);
  • ResponseComplete — vastusorgan on saadetud, rohkem teavet ei saadeta;
  • Panic — sündmused genereeritakse ebatavalise olukorra tuvastamisel.

Kõigi sammude vahelejätmiseks, mida saate kasutada omitStages.

Poliitikafailis saame kirjeldada mitut erineva logimistasemega jaotist. Rakendatakse esimene eeskirjade kirjeldusest leitud sobiv reegel.

Kubeleti deemon jälgib manifesti muudatusi api-serveri konfiguratsiooniga ja kui neid tuvastatakse, taaskäivitab konteineri api-serveriga. Kuid on oluline detail: see ignoreerib poliitikafailis tehtud muudatusi. Pärast poliitikafailis muudatuste tegemist peate api-serveri käsitsi taaskäivitama. Kuna api-server on käivitatud kui staatiline pod, meeskond kubectl delete ei põhjusta selle taaskäivitamist. Peate seda käsitsi tegema docker stop kube-mastersil, kus auditipoliitikat on muudetud:

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

Auditi lubamisel on oluline seda meeles pidada kube-apiserveri koormus suureneb. Eelkõige suureneb mälutarbimine päringu konteksti salvestamiseks. Logimine algab alles pärast vastuse päise saatmist. Koormus sõltub ka auditipoliitika konfiguratsioonist.

Näited poliitikast

Vaatame näidete abil poliitikafailide struktuuri.

Siin on lihtne fail policyet kõik tasemel logida Metadata:

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

Reeglites saate määrata kasutajate loendi (Users и ServiceAccounts) ja kasutajarühmad. Näiteks nii eirame süsteemi kasutajaid, kuid logime kõik muu tasemel 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

Samuti on võimalik kirjeldada sihtmärke:

  • nimeruumid (namespaces);
  • Tegusõnad (tegusõnad: get, update, delete ja teised);
  • ressursid (ressursidJärgmiselt: pod, configmaps jne) ja ressursirühmad (apiGroups).

Pöörake tähelepanu! Klastris installitud ressursse ja ressursirühmi (API-rühmad, st apiGroups) ning nende versioone saab hankida käskude abil:

kubectl api-resources
kubectl api-versions

Järgmine auditipoliitika on esitatud parimate tavade demonstreerimiseks Alibaba pilve dokumentatsioon:

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

Teine hea näide auditipoliitikast on GCE-s kasutatav profiil.

Auditisündmustele kiiresti reageerida on võimalik kirjeldage veebihaagi. Seda teemat käsitletakse ametlik dokumentatsioon, jätan selle sellest artiklist välja.

Tulemused

Artiklis antakse ülevaade Kubernetese klastrite põhilistest turvamehhanismidest, mis võimaldavad luua isikupärastatud kasutajakontosid, eraldada nende õigused ja salvestada nende toiminguid. Loodan, et see on kasulik neile, kes on selliste probleemidega teoreetiliselt või praktikas silmitsi seisnud. Samuti soovitan teil lugeda Kubernetese muude turvateemaliste materjalide loendit, mis on toodud "PS-is" - võib-olla leiate nende hulgast vajalikke üksikasju teie jaoks oluliste probleemide kohta.

PS

Loe ka meie blogist:

Allikas: www.habr.com

Lisa kommentaar