Abeceda sigurnosti u Kubernetesu: autentifikacija, autorizacija, revizija

Abeceda sigurnosti u Kubernetesu: autentifikacija, autorizacija, revizija

Prije ili kasnije, u radu bilo kojeg sustava, pojavi se pitanje sigurnosti: osiguranje autentifikacije, odvajanje prava, revizija i drugi poslovi. Već stvoreno za Kubernetes mnoga rješenja, koji vam omogućuju postizanje usklađenosti sa standardima čak iu vrlo zahtjevnim okruženjima... Isti materijal posvećen je osnovnim aspektima sigurnosti implementiranim unutar ugrađenih mehanizama K8s. Prije svega, bit će korisno onima koji se počinju upoznavati s Kubernetesom - kao polazištem za proučavanje pitanja vezanih uz sigurnost.

ovjera

U Kubernetesu postoje dvije vrste korisnika:

  • Računi usluga — računi kojima upravlja Kubernetes API;
  • korisnici — “normalni” korisnici kojima upravljaju vanjski, neovisni servisi.

Glavna razlika između ovih vrsta je u tome što za račune usluga postoje posebni objekti u Kubernetes API-ju (tako se zovu - ServiceAccounts), koji su povezani s prostorom imena i skupom autorizacijskih podataka pohranjenih u klasteru u objektima tipa Secrets. Takvi su korisnici (Service Accounts) prvenstveno namijenjeni upravljanju pravima pristupa Kubernetes API-ju procesa koji se izvode u Kubernetes klasteru.

Obični korisnici nemaju unose u Kubernetes API: njima moraju upravljati vanjski mehanizmi. Namijenjeni su ljudima ili procesima koji žive izvan klastera.

Svaki API zahtjev povezan je ili s računom usluge, korisnikom ili se smatra anonimnim.

Podaci za autentifikaciju korisnika uključuju:

  • Korisničko ime — korisničko ime (različito na velika i mala slova!);
  • UID - strojno čitljiv identifikacijski niz korisnika koji je "dosljedniji i jedinstveniji od korisničkog imena";
  • Klanovi — popis grupa kojima korisnik pripada;
  • dodatni — dodatna polja koja može koristiti mehanizam autorizacije.

Kubernetes može koristiti velik broj mehanizama za autentifikaciju: X509 certifikate, Bearer tokene, proxy za autentifikaciju, HTTP Basic Auth. Pomoću ovih mehanizama možete implementirati velik broj shema autorizacije: od statične datoteke s lozinkama do OpenID OAuth2.

Štoviše, moguće je koristiti nekoliko shema autorizacije istovremeno. Prema zadanim postavkama, klaster koristi:

  • tokeni računa usluge - za račune usluge;
  • X509 - za korisnike.

Pitanje o upravljanju ServiceAccounts izvan je opsega ovog članka, ali za one koji se žele detaljnije upoznati s ovim problemom, preporučujem da počnete s službene stranice dokumentacije. Pobliže ćemo pogledati pitanje rada X509 certifikata.

Certifikati za korisnike (X.509)

Klasičan način rada s certifikatima uključuje:

  • generiranje ključeva:
    mkdir -p ~/mynewuser/.certs/
    openssl genrsa -out ~/.certs/mynewuser.key 2048
  • generiranje zahtjeva za certifikatom:
    openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company"
  • obrada zahtjeva za certifikat pomoću CA ključeva Kubernetes klastera, dobivanje korisničkog certifikata (za dobivanje certifikata morate koristiti račun koji ima pristup CA ključu Kubernetes klastera koji se prema zadanim postavkama nalazi u /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
  • stvaranje konfiguracijske datoteke:
    • opis klastera (navedite adresu i lokaciju datoteke CA certifikata za određenu instalaciju klastera):
      kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443
    • ili kako nepreporučena opcija - ne morate navesti korijenski certifikat (tada kubectl neće provjeravati ispravnost api-poslužitelja klastera):
      kubectl config set-cluster kubernetes  --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443
    • dodavanje korisnika u konfiguracijsku datoteku:
      kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt  --client-key=.certs/mynewuser.key
    • dodavanje konteksta:
      kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser
    • zadana dodjela konteksta:
      kubectl config use-context mynewuser-context

Nakon gore navedenih manipulacija, u datoteku .kube/config kreirat će se ovakva konfiguracija:

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

Kako biste olakšali prijenos konfiguracije između računa i poslužitelja, korisno je urediti vrijednosti sljedećih ključeva:

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

Da biste to učinili, možete kodirati datoteke navedene u njima pomoću base64 i registrirati ih u konfiguraciji, dodajući sufiks nazivu ključeva -data, tj. primivši certificate-authority-data itd.

Certifikati s kubeadm

Uz oslobađanje Kubernetes 1.15 rad s certifikatima postao je puno lakši zahvaljujući alfa verziji njegove podrške za kubeadm uslužni program. Na primjer, ovako bi sada moglo izgledati generiranje konfiguracijske datoteke s korisničkim ključevima:

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

NB: Obavezno oglašavati adresu može se pronaći u konfiguraciji api-poslužitelja, koja se prema zadanim postavkama nalazi u /etc/kubernetes/manifests/kube-apiserver.yaml.

Rezultirajuća konfiguracija bit će poslana u stdout. Treba ga spremiti u ~/.kube/config korisnički račun ili u datoteku navedenu u varijabli okruženja KUBECONFIG.

Kopaj Dublje

Za one koji žele detaljnije razumjeti opisana pitanja:

Autorizacija

Zadani ovlašteni račun nema prava za rad na klasteru. Za dodjelu dopuštenja, Kubernetes implementira mehanizam autorizacije.

Prije verzije 1.6, Kubernetes je koristio vrstu autorizacije tzv ABAC (Kontrola pristupa temeljena na atributima). Detalje o tome možete pronaći u službena dokumentacija. Ovaj se pristup trenutno smatra naslijeđenim, ali ga još uvijek možete koristiti uz druge vrste provjere autentičnosti.

Sadašnji (i fleksibilniji) način podjele prava pristupa klasteru zove se RBAC (Uloga kontrole pristupa na temelju uloga). Od verzije je proglašen stabilnim Kubernetes 1.8. RBAC implementira model prava u kojem je zabranjeno sve što nije izričito dopušteno.
Da biste omogućili RBAC, trebate pokrenuti Kubernetes api-poslužitelj s parametrom --authorization-mode=RBAC. Parametri su postavljeni u manifestu s konfiguracijom api-poslužitelja, koji se prema zadanim postavkama nalazi duž staze /etc/kubernetes/manifests/kube-apiserver.yaml, u odjeljku command. Međutim, RBAC je već omogućen prema zadanim postavkama, tako da najvjerojatnije ne biste trebali brinuti o tome: to možete provjeriti pomoću vrijednosti authorization-mode (u već spomenutom kube-apiserver.yaml). Usput, među njegovim značenjima mogu postojati i druge vrste ovlaštenja (node, webhook, always allow), ali ćemo njihovo razmatranje ostaviti izvan okvira materijala.

Inače, već smo objavili članak s prilično detaljnim opisom načela i značajki rada s RBAC-om, pa ću se dalje ograničiti na kratki popis osnova i primjera.

Sljedeći API entiteti koriste se za kontrolu pristupa u Kubernetesu putem RBAC-a:

  • Role и ClusterRole — uloge koje služe za opisivanje prava pristupa:
  • Role omogućuje vam da opišete prava unutar imenskog prostora;
  • ClusterRole - unutar klastera, uključujući objekte specifične za klaster kao što su čvorovi, url-ovi koji nisu resursi (tj. koji nisu povezani s Kubernetes resursima - na primjer, /version, /logs, /api*);
  • RoleBinding и ClusterRoleBinding - služi za uvezivanje Role и ClusterRole korisniku, grupi korisnika ili ServiceAccountu.

Entiteti Role i RoleBinding ograničeni su prostorom imena, tj. mora biti unutar istog imenskog prostora. Međutim, RoleBinding može referencirati ClusterRole, što vam omogućuje stvaranje skupa generičkih dopuštenja i kontrolu pristupa pomoću njih.

Uloge opisuju prava korištenjem skupova pravila koji sadrže:

  • API grupe - vidi službena dokumentacija by apiGroups i izlaz kubectl api-resources;
  • resursi (sredstva: pod, namespace, deployment i tako dalje.);
  • Glagoli (glagoli: set, update itd.).
  • imena resursa (resourceNames) - za slučaj kada trebate omogućiti pristup određenom resursu, a ne svim resursima ove vrste.

Detaljniju analizu autorizacije u Kubernetesu možete pronaći na stranici službena dokumentacija. Umjesto toga (ili bolje rečeno uz to), navest ću primjere koji ilustriraju njezin rad.

Primjeri RBAC entiteta

jednostavan Role, koji vam omogućuje da dobijete popis i status podova i nadgledate ih u prostoru imena 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"]

Primjer ClusterRole, koji vam omogućuje da dobijete popis i status mahuna i da ih nadzirete u cijelom klasteru:

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

Primjer RoleBinding, što omogućuje korisniku mynewuser "čitaj" mahune u prostoru imena 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

Revizija događaja

Shematski se Kubernetes arhitektura može prikazati na sljedeći način:

Abeceda sigurnosti u Kubernetesu: autentifikacija, autorizacija, revizija

Ključna Kubernetes komponenta odgovorna za obradu zahtjeva je api-poslužitelj. Sve operacije na klasteru prolaze kroz njega. Više o ovim unutarnjim mehanizmima možete pročitati u članku “Što se događa u Kubernetesu kada pokrenete kubectl run?".

Revizija sustava je zanimljiva značajka u Kubernetesu, koja je prema zadanim postavkama onemogućena. Omogućuje vam bilježenje svih poziva na Kubernetes API. Kao što možda pretpostavljate, sve radnje vezane uz praćenje i promjenu stanja klastera izvode se putem ovog API-ja. Dobar opis njegovih mogućnosti može se (kao i obično) pronaći u službena dokumentacija K8s. Zatim ću temu pokušati predstaviti jednostavnijim jezikom.

Dakle, omogućiti reviziju, trebamo proslijediti tri potrebna parametra spremniku u api-poslužitelju, koji su detaljnije opisani u nastavku:

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

Uz ova tri potrebna parametra, postoje mnoge dodatne postavke vezane uz reviziju: od rotacije dnevnika do opisa webhooka. Primjer parametara rotacije trupaca:

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

Ali nećemo se detaljnije zadržavati na njima - sve detalje možete pronaći u kube-apiserver dokumentacija.

Kao što je već spomenuto, svi su parametri postavljeni u manifestu s konfiguracijom api-poslužitelja (prema zadanim postavkama /etc/kubernetes/manifests/kube-apiserver.yaml), u odjeljku command. Vratimo se na 3 potrebna parametra i analizirajmo ih:

  1. audit-policy-file — put do YAML datoteke koja opisuje politiku revizije. Kasnije ćemo se vratiti na njegov sadržaj, ali za sada ću napomenuti da datoteka mora biti čitljiva od strane procesa api-poslužitelja. Stoga ga je potrebno montirati unutar kontejnera, za što možete dodati sljedeći kod u odgovarajuće dijelove konfiguracije:
      volumeMounts:
        - mountPath: /etc/kubernetes/policies
          name: policies
          readOnly: true
      volumes:
      - hostPath:
          path: /etc/kubernetes/policies
          type: DirectoryOrCreate
        name: policies
  2. audit-log-path — put do datoteke dnevnika. Put također mora biti dostupan procesu api-poslužitelja, tako da opisujemo njegovo montiranje na isti način:
      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 dnevnika revizije. Zadano je json, no dostupan je i stari format teksta (legacy).

Politika revizije

Sada o spomenutoj datoteci koja opisuje politiku zapisivanja. Prvi koncept politike revizije je level, razina zapisivanja. Oni su sljedeći:

  • None - ne prijavljivati ​​se;
  • Metadata — metapodaci zahtjeva za zapisnik: korisnik, vrijeme zahtjeva, ciljni resurs (pod, imenski prostor itd.), tip akcije (glagol) itd.;
  • Request — metapodaci dnevnika i tijelo zahtjeva;
  • RequestResponse — metapodaci dnevnika, tijelo zahtjeva i tijelo odgovora.

Posljednje dvije razine (Request и RequestResponse) ne bilježi zahtjeve koji nisu pristupili resursima (pristupi tzv. ne-resursnim url-ovima).

Također prolaze svi zahtjevi nekoliko faza:

  • RequestReceived — faza kada je zahtjev primio procesor i još nije proslijeđen dalje duž lanca procesora;
  • ResponseStarted — šalju se zaglavlja odgovora, ali prije slanja tijela odgovora. Generirano za dugotrajne upite (na primjer, watch);
  • ResponseComplete — tijelo odgovora je poslano, više informacija neće biti poslano;
  • Panic — događaji se generiraju kada se otkrije nenormalna situacija.

Da biste preskočili sve korake koje možete koristiti omitStages.

U datoteci pravila možemo opisati nekoliko odjeljaka s različitim razinama zapisivanja. Primijenit će se prvo odgovarajuće pravilo koje se pronađe u opisu pravila.

Kubelet demon nadzire promjene u manifestu s konfiguracijom api-poslužitelja i, ako ih otkrije, ponovno pokreće spremnik s api-poslužiteljem. Ali postoji važan detalj: zanemarit će promjene u datoteci pravila. Nakon što napravite izmjene u datoteci pravila, morat ćete ručno ponovno pokrenuti api-poslužitelj. Budući da se api-poslužitelj pokreće kao statična pod, tim kubectl delete neće izazvati ponovno pokretanje. Morat ćete to učiniti ručno docker stop na kube-masters, gdje je politika revizije promijenjena:

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

Prilikom omogućavanja revizije važno je to zapamtiti povećava se opterećenje kube-apiservera. Posebno se povećava potrošnja memorije za pohranu konteksta zahtjeva. Bilježenje počinje tek nakon slanja zaglavlja odgovora. Opterećenje također ovisi o konfiguraciji politike revizije.

Primjeri politika

Pogledajmo strukturu datoteka pravila koristeći primjere.

Ovdje je jednostavna datoteka policylogirati sve na razini Metadata:

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

U politici možete navesti popis korisnika (Users и ServiceAccounts) i grupe korisnika. Na primjer, ovako ćemo ignorirati korisnike sustava, ali sve ostalo zabilježiti na razini 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

Također je moguće opisati ciljeve:

  • prostori imena (namespaces);
  • Glagoli (glagoli: get, update, delete i drugi);
  • resursi (sredstva, Kako slijedi: pod, configmaps itd.) i grupe resursa (apiGroups).

Obratite pozornost! Resurse i grupe resursa (API grupe, tj. apiGroups), kao i njihove verzije instalirane u klasteru, možete dobiti pomoću naredbi:

kubectl api-resources
kubectl api-versions

Sljedeća politika revizije pruža se kao demonstracija najbolje prakse u Dokumentacija za 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

Još jedan dobar primjer politike revizije je profil koji se koristi u GCE.

Moguće je brzo odgovoriti na revizijske događaje opišite webhook. Ovo je pitanje pokriveno u službena dokumentacija, ostavit ću to izvan opsega ovog članka.

Rezultati

Članak daje pregled osnovnih sigurnosnih mehanizama u Kubernetes klasterima, koji vam omogućuju stvaranje personaliziranih korisničkih računa, odvajanje njihovih prava i snimanje njihovih radnji. Nadam se da će biti od koristi onima koji se susreću s takvim problemima u teoriji ili praksi. Također preporučujem da pročitate popis drugih materijala na temu sigurnosti u Kubernetesu, koji je naveden u “PS” - možda ćete među njima pronaći potrebne pojedinosti o problemima koji su vam relevantni.

PS

Pročitajte i na našem blogu:

Izvor: www.habr.com

Dodajte komentar