Kubernetes drošības ABC: autentifikācija, autorizācija, audits

Kubernetes drošības ABC: autentifikācija, autorizācija, audits

Agri vai vēlu jebkuras sistēmas darbībā rodas drošības jautājums: autentifikācijas nodrošināšana, tiesību nodalīšana, audits un citi uzdevumi. Jau izveidots priekš Kubernetes daudz risinājumu, kas ļauj sasniegt atbilstību standartiem pat ļoti prasīgās vidēs... Tas pats materiāls ir veltīts K8s iebūvēto mehānismu ietvaros īstenotajiem drošības pamataspektiem. Pirmkārt, tas noderēs tiem, kas sāk iepazīties ar Kubernetes - kā atspēriena punktu ar drošību saistītu jautājumu izpētei.

Autentifikācija

Kubernetes ir divu veidu lietotāji:

  • Pakalpojumu konti — Kubernetes API pārvaldītie konti;
  • Lietotāji — “parastie” lietotāji, kurus pārvalda ārēji neatkarīgi pakalpojumi.

Galvenā atšķirība starp šiem veidiem ir tāda, ka pakalpojumu kontiem Kubernetes API ir īpaši objekti (tos sauc par - ServiceAccounts), kas ir piesaistīti nosaukumvietai un autorizācijas datu kopai, kas glabājas klasterī noslēpumu tipa objektos. Šādi lietotāji (pakalpojumu konti) galvenokārt ir paredzēti, lai pārvaldītu Kubernetes klasterī darbināmo procesu piekļuves tiesības Kubernetes API.

Parastajiem lietotājiem nav ierakstu Kubernetes API: tie ir jāpārvalda ar ārējiem mehānismiem. Tie ir paredzēti cilvēkiem vai procesiem, kas dzīvo ārpus klastera.

Katrs API pieprasījums ir saistīts ar pakalpojuma kontu, lietotāju vai tiek uzskatīts par anonīmu.

Lietotāja autentifikācijas dati ietver:

  • Lietotājvārds — lietotājvārds (reģistrjutīgs!);
  • UID - mašīnlasāma lietotāja identifikācijas virkne, kas ir “konsekventāka un unikālāka par lietotājvārdu”;
  • grupas — to grupu saraksts, kurām lietotājs pieder;
  • Papildus — papildu lauki, ko var izmantot autorizācijas mehānisms.

Kubernetes var izmantot lielu skaitu autentifikācijas mehānismu: X509 sertifikāti, nesēja marķieri, autentifikācijas starpniekserveris, HTTP pamata autentifikācija. Izmantojot šos mehānismus, varat ieviest lielu skaitu autorizācijas shēmu: no statiska faila ar parolēm līdz OpenID OAuth2.

Turklāt ir iespējams vienlaikus izmantot vairākas autorizācijas shēmas. Pēc noklusējuma klasteris izmanto:

  • pakalpojumu kontu marķieri - Pakalpojumu kontiem;
  • X509 - lietotājiem.

Jautājums par ServiceAccounts pārvaldību ir ārpus šī raksta, taču tiem, kas vēlas iepazīties ar šo problēmu sīkāk, iesaku sākt ar oficiālās dokumentācijas lapas. Mēs sīkāk aplūkosim jautājumu par to, kā darbojas X509 sertifikāti.

Sertifikāti lietotājiem (X.509)

Klasiskais veids, kā strādāt ar sertifikātiem, ietver:

  • atslēgu ģenerēšana:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • ģenerējot sertifikāta pieprasījumu:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • sertifikāta pieprasījuma apstrāde, izmantojot Kubernetes klastera CA atslēgas, lietotāja sertifikāta iegūšana (lai iegūtu sertifikātu, ir jāizmanto konts, kuram ir piekļuve Kubernetes klastera CA atslēgai, kas pēc noklusējuma atrodas /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
  • izveidojot konfigurācijas failu:
    • klastera apraksts (norādiet CA sertifikāta faila adresi un atrašanās vietu konkrētai klastera instalācijai):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • vai kā ieteicamā opcija - jums nav jānorāda saknes sertifikāts (tad kubectl nepārbaudīs klastera api-servera pareizību):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • lietotāja pievienošana konfigurācijas failam:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • pievienojot kontekstu:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • noklusējuma konteksta piešķiršana:
      kubectl config use-context mynewuser-context

Pēc iepriekš minētajām manipulācijām failā .kube/config tiks izveidota šāda konfigurācija:

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

Lai atvieglotu konfigurācijas pārsūtīšanu starp kontiem un serveriem, ir lietderīgi rediģēt šādu atslēgu vērtības:

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

Lai to izdarītu, tajos norādītos failus var iekodēt, izmantojot base64, un reģistrēt tos konfigurācijā, pievienojot atslēgu nosaukumam sufiksu -data, t.i. saņemot certificate-authority-data uc

Sertifikāti ar kubeadm

Ar atbrīvošanu Kubernetes 1.15 darbs ar sertifikātiem ir kļuvis daudz vienkāršāks, pateicoties tā atbalsta alfa versijai kubeadm utilīta. Piemēram, konfigurācijas faila ģenerēšana ar lietotāja atslēgām tagad varētu izskatīties šādi:

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

NB: Obligāti reklamēt adresi var atrast api-servera konfigurācijā, kas pēc noklusējuma atrodas /etc/kubernetes/manifests/kube-apiserver.yaml.

Iegūtā konfigurācija tiks izvadīta uz stdout. Tas ir jāsaglabā ~/.kube/config lietotāja kontam vai failam, kas norādīts vides mainīgajā KUBECONFIG.

Rakt dziļāk

Tiem, kas vēlas sīkāk izprast aprakstītos jautājumus:

Atļauja

Noklusējuma autorizētajam kontam nav tiesību darboties klasterī. Lai piešķirtu atļaujas, Kubernetes ievieš autorizācijas mehānismu.

Pirms versijas 1.6 Kubernetes izmantoja autorizācijas veidu, ko sauc ABAC (Uz atribūtiem balstīta piekļuves kontrole). Sīkāku informāciju par to var atrast oficiālā dokumentācija. Šī pieeja pašlaik tiek uzskatīta par mantotu, taču jūs joprojām varat to izmantot kopā ar citiem autentifikācijas veidiem.

Tiek saukts pašreizējais (un elastīgāks) veids, kā sadalīt piekļuves tiesības klasterim RBAC (Uz lomu balstīta piekļuves kontrole). Kopš versijas tas ir pasludināts par stabilu Kubernetes 1.8. RBAC ievieš tiesību modeli, kurā viss, kas nav tieši atļauts, ir aizliegts.
Lai iespējotu RBAC, jums ir jāstartē Kubernetes api-server ar parametru --authorization-mode=RBAC. Parametri tiek iestatīti manifestā ar api-servera konfigurāciju, kas pēc noklusējuma atrodas ceļā /etc/kubernetes/manifests/kube-apiserver.yaml, sadaļā command. Tomēr RBAC jau ir iespējots pēc noklusējuma, tāpēc, visticamāk, jums par to nevajadzētu uztraukties: varat to pārbaudīt pēc vērtības authorization-mode (jau minētajā kube-apiserver.yaml). Starp citu, starp tā nozīmēm var būt arī citi autorizācijas veidi (node, webhook, always allow), taču mēs to izskatīšanu atstāsim ārpus materiāla tvēruma.

Starp citu, mēs jau esam publicējuši raksts ar diezgan detalizētu aprakstu par darba ar RBAC principiem un iezīmēm, tāpēc turpmāk aprobežošos ar īsu pamatu un piemēru uzskaitījumu.

Lai kontrolētu piekļuvi Kubernetes, izmantojot RBAC, tiek izmantotas šādas API entītijas:

  • Role и ClusterRole — lomas, kas kalpo, lai aprakstītu piekļuves tiesības:
  • Role ļauj aprakstīt tiesības nosaukumvietā;
  • ClusterRole - klasterī, tostarp uz klasteriem raksturīgiem objektiem, piemēram, mezgliem, neresursiem URL (t.i., kas nav saistīti ar Kubernetes resursiem, piemēram, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - izmanto iesiešanai Role и ClusterRole lietotājam, lietotāju grupai vai ServiceAccount.

Entītijas Role un RoleBinding ierobežo nosaukumvieta, t.i. jāatrodas tajā pašā nosaukumvietā. Tomēr RoleBinding var atsaukties uz ClusterRole, kas ļauj izveidot vispārīgu atļauju kopu un kontrolēt piekļuvi, izmantojot tās.

Lomas apraksta tiesības, izmantojot noteikumu kopas, kas ietver:

  • API grupas - sk oficiālā dokumentācija pēc apiGroups un izvades kubectl api-resources;
  • resursi (resursi: pod, namespace, deployment un tā tālāk.);
  • Darbības vārdi (darbības vārdi: set, update uc).
  • resursu nosaukumi (resourceNames) - gadījumam, kad jums ir jānodrošina piekļuve konkrētam resursam, nevis visiem šāda veida resursiem.

Detalizētāku Kubernetes autorizācijas analīzi var atrast lapā oficiālā dokumentācija. Tā vietā (vai drīzāk, papildus tam) es sniegšu piemērus, kas ilustrē viņas darbu.

RBAC entītiju piemēri

Vienkāršs Role, kas ļauj iegūt pākstu sarakstu un statusu un pārraudzīt tos nosaukumvietā 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"]

Piemērs ClusterRole, kas ļauj iegūt pākstu sarakstu un statusu un pārraudzīt tos visā klasterī:

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

Piemērs RoleBinding, kas ļauj lietotājam mynewuser "lasīt" pākstis nosaukumvietā 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

Pasākuma audits

Shematiski Kubernetes arhitektūru var attēlot šādi:

Kubernetes drošības ABC: autentifikācija, autorizācija, audits

Galvenais Kubernetes komponents, kas atbild par pieprasījumu apstrādi, ir api-serveris. Visas klastera darbības tiek veiktas caur to. Vairāk par šiem iekšējiem mehānismiem varat lasīt rakstā “Kas notiek Kubernetes, kad palaižat kubectl run?'.

Sistēmas audits ir interesanta Kubernetes funkcija, kas pēc noklusējuma ir atspējota. Tas ļauj reģistrēt visus Kubernetes API zvanus. Kā jūs varētu nojaust, visas darbības, kas saistītas ar klastera stāvokļa uzraudzību un maiņu, tiek veiktas, izmantojot šo API. Labu tā iespēju aprakstu (kā parasti) var atrast oficiālā dokumentācija K8s. Tālāk es mēģināšu tēmu izklāstīt vienkāršākā valodā.

Tātad, lai iespējotu auditu, mums ir jānodod trīs nepieciešamie parametri api-servera konteineram, kas sīkāk aprakstīti tālāk:

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

Papildus šiem trim nepieciešamajiem parametriem ir daudz papildu iestatījumu, kas saistīti ar auditēšanu: no žurnāla rotācijas līdz tīmekļa aizķeres aprakstiem. Žurnāla rotācijas parametru piemērs:

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

Bet mēs par tiem sīkāk nepakavēsimies - jūs varat atrast visu informāciju kube-apiserver dokumentācija.

Kā jau minēts, visi parametri tiek iestatīti manifestā ar api-servera konfigurāciju (pēc noklusējuma /etc/kubernetes/manifests/kube-apiserver.yaml), sadaļā command. Atgriezīsimies pie 3 nepieciešamajiem parametriem un analizēsim tos:

  1. audit-policy-file — ceļš uz YAML failu, kurā aprakstīta audita politika. Mēs atgriezīsimies pie tā satura vēlāk, taču pagaidām atzīmēšu, ka failam jābūt lasāmam api-servera procesam. Tāpēc tas ir jāmontē konteinera iekšpusē, kuram attiecīgajās konfigurācijas sadaļās varat pievienot šādu kodu:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — ceļš uz žurnāla failu. Ceļam jābūt pieejamam arī api-servera procesam, tāpēc mēs aprakstam tā montāžu tādā pašā veidā:
      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 — audita žurnāla formāts. Noklusējums ir json, taču ir pieejams arī mantotais teksta formāts (legacy).

Revīzijas politika

Tagad par minēto failu, kas apraksta reģistrēšanas politiku. Pirmā revīzijas politikas koncepcija ir level, mežizstrādes līmenis. Tie ir šādi:

  • None - nereģistrēties;
  • Metadata — žurnāla pieprasījuma metadati: lietotājs, pieprasījuma laiks, mērķa resurss (pod, nosaukumtelpa utt.), darbības veids (darbības vārds) utt.;
  • Request — žurnāla metadati un pieprasījuma struktūra;
  • RequestResponse — žurnāla metadati, pieprasījuma pamatteksts un atbildes struktūra.

Pēdējie divi līmeņi (Request и RequestResponse) nereģistrējiet pieprasījumus, kas nepiekļuva resursiem (piekļuve tā sauktajiem ne-resursu URL).

Arī visi pieprasījumi tiek izpildīti vairākus posmus:

  • RequestReceived — posms, kurā apstrādātājs ir saņēmis pieprasījumu un vēl nav nosūtīts tālāk pa apstrādātāju ķēdi;
  • ResponseStarted — atbildes galvenes tiek nosūtītas, bet pirms atbildes pamatteksta nosūtīšanas. Ģenerēts ilgstošiem vaicājumiem (piemēram, watch);
  • ResponseComplete — atbildes struktūra ir nosūtīta, vairāk informācija netiks nosūtīta;
  • Panic — notikumi tiek ģenerēti, kad tiek konstatēta neparasta situācija.

Lai izlaistu visas darbības, ko varat izmantot omitStages.

Politikas failā mēs varam aprakstīt vairākas sadaļas ar dažādiem reģistrēšanas līmeņiem. Tiks piemērota pirmā politikas aprakstā atrastā atbilstošā kārtula.

Kubelet dēmons pārrauga izmaiņas manifestā ar api-servera konfigurāciju un, ja tādas tiek konstatētas, restartē konteineru ar api-serveri. Bet ir svarīga detaļa: izmaiņas politikas failā tiks ignorētas. Pēc izmaiņu veikšanas politikas failā jums būs manuāli jārestartē api-serveris. Tā kā api-serveris ir palaists kā statisks pods, komanda kubectl delete neizraisīs tā restartēšanos. Jums tas būs jādara manuāli docker stop vietnē kube-masters, kur ir mainīta audita politika:

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

Iespējojot auditu, ir svarīgi to atcerēties kube-apiserver slodze palielinās. Jo īpaši palielinās atmiņas patēriņš pieprasījuma konteksta glabāšanai. Reģistrēšana sākas tikai pēc atbildes galvenes nosūtīšanas. Slodze ir atkarīga arī no audita politikas konfigurācijas.

Politiku piemēri

Apskatīsim politikas failu struktūru, izmantojot piemērus.

Šeit ir vienkāršs fails policylai visu pieteiktu līmenī Metadata:

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

Politikā varat norādīt lietotāju sarakstu (Users и ServiceAccounts) un lietotāju grupas. Piemēram, šādi mēs ignorēsim sistēmas lietotājus, bet visu pārējo reģistrēsim līmenī 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

Ir iespējams arī aprakstīt mērķus:

  • vārdu telpas (namespaces);
  • Darbības vārdi (darbības vārdi: get, update, delete un citi);
  • resursi (resursi, Kā ir: pod, configmaps utt.) un resursu grupas (apiGroups).

Pievērsiet uzmanību! Resursus un resursu grupas (API grupas, t.i. apiGroups), kā arī to klasterī instalētās versijas var iegūt, izmantojot komandas:

kubectl api-resources
kubectl api-versions

Tālāk sniegtā revīzijas politika ir sniegta kā labākās prakses demonstrējums Alibaba Cloud dokumentācija:

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

Vēl viens labs revīzijas politikas piemērs ir GCE izmantotais profils.

Ātri reaģēt uz audita notikumiem, tas ir iespējams aprakstiet tīmekļa aizķeri. Šis jautājums ir apskatīts oficiālā dokumentācija, es to atstāšu ārpus šī raksta darbības jomas.

Rezultāti

Rakstā ir sniegts pārskats par pamata drošības mehānismiem Kubernetes klasteros, kas ļauj izveidot personalizētus lietotāju kontus, nodalīt viņu tiesības un reģistrēt viņu darbības. Es ceru, ka tas būs noderīgi tiem, kas teorētiski vai praktiski sastopas ar šādiem jautājumiem. Iesaku arī izlasīt citu materiālu sarakstu par drošības tēmu Kubernetes, kas ir sniegts “PS” - iespējams, starp tiem atradīsit nepieciešamo informāciju par jums aktuālajām problēmām.

PS

Lasi arī mūsu emuārā:

Avots: www.habr.com

Pievieno komentāru