
рано ili kasnije u radu bilo kojeg sustava postavlja se pitanje sigurnosti: osiguravanje autentifikacije, razdvajanje prava, revizija i drugih zadataka. Za Kubernetes već je stvoreno , koja omogućuju postizanje usklađenosti sa standardima čak i u vrlo zahtjevnim okruženjima… Ovaj materijal posvećen je osnovnim aspektima sigurnosti, implementiranim u okviru ugrađenih mehanizama K8s. Prije svega, bit će koristan onima koji se počinju upoznavati s Kubernetesom, kao polazna točka za proučavanje pitanja vezanih za sigurnost.
Autentifikacija
U Kubernetesu postoje dvije vrste korisnika:
- Računi servisa — računi kojima upravlja Kubernetes API;
- Korisnici — „normalni“ korisnici kojima upravljaju vanjske, neovisne usluge.
Osnovna razlika između ovih tipova je u tome što za račune servisa postoje posebni objekti u Kubernetes API (oni se tako i nazivaju — ServiceAccounts), koji su vezani za prostor imena i skup autorizacijskih podataka pohranjenih u klasteru u objektima tipa Secrets. Takvi korisnici (računi servisa) su prvenstveno namijenjeni upravljanju pravima pristupa Kubernetes API procesima koji rade unutar Kubernetes klastera.
Obični korisnici nemaju zapise u Kubernetes API: njihovo upravljanje mora se provoditi vanjskim mehanizmima. Oni su namijenjeni ljudima ili procesima koji žive izvan klastera.
Svaki zahtjev prema API-ju vezan je ili za račun servisa, ili za korisnika, ili se smatra anonimnim.
Autentifikacijski podaci korisnika uključuju:
- Korisničko ime — ime korisnika (ovisno o registru!);
- UID — strojno čitljiva oznaka identifikacije korisnika koja je „dosljednija i jedinstvenija od imena korisnika“;
- Grupe — popis grupa kojima korisnik pripada;
- Dodatno — dodatna polja koja se mogu koristiti u mehanizmu autorizacije.
Kubernetes može koristiti veliki broj mehanizama autentifikacije: X509 certifikate, Bearer tokene, autentifikacijske proksije, HTTP Basic Auth. Pomoću ovih mehanizama može se implementirati mnoštvo shema autorizacije: od statične datoteke s lozinkama do OpenID OAuth2.
Štoviše, dopušteno je korištenje više shema autorizacije istovremeno. Po defaultu u klasteru se koriste:
- tokeni računa servisa — za račune servisa;
- X509 — za korisnike.
Pitanje upravljanja ServiceAccountima izlazi iz okvira ovog članka, a svima koji žele detaljnije upoznati s ovom temom preporučam da započnu s . Mi ćemo detaljnije razmotriti pitanje rada sa X509 certifikatima.
Certifikati za korisnike (X.509)
Klasični način rada s certifikatima podrazumijeva:
- generisanje ključa:
mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/.certs/mynewuser.key 2048 - generisanje zahtjeva za certifikat:
openssl req -new -key ~/.certs/mynewuser.key -out ~/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company" - obrada zahtjeva za certifikat uz pomoć ključeva CA klastera Kubernetes, dobijanje certifikata korisnika (za dobijanje certifikata potrebno je koristiti račun koji ima pristup ključu centra za certifikaciju klastera Kubernetes, koji je po defaultu smješten
/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 - kreiranje konfiguracijske datoteke:
- opis klastera (navedite adresu i lokaciju datoteke certifikata CA konkretne instalacije klastera):
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 - ili — kao nepreporučeni način — nije potrebno navoditi korijenski certifikat (tada kubectl neće provjeravati ispravnost api-servera 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 - postavljanje konteksta po zadanim postavkama:
kubectl config use-context mynewuser-context
- opis klastera (navedite adresu i lokaciju datoteke certifikata CA konkretne instalacije klastera):
Nakon gore navedenih radnji, u datoteci .kube/config bit će kreiran konfiguracijski oblik:
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.keyZa olakšavanje premještanja konfiguracije između računa i servera, korisno je urediti vrijednosti sljedećih ključeva:
-
certificate-authority -
client-certificate -
client-key
Za to se navedene datoteke mogu kodirati pomoću base64 i upisati ih u konfiguraciju, dodajući sufiks -data, tj. dobijajući certificate-authority-data itd.
Certifikati s kubeadm
S izdanjem rad sa certifikatima postao je znatno lakši zahvaljujući alpha verziji njegove podrške u . Na primjer, ovako može izgledati generacija konfiguracijske datoteke s korisničkim ključevima:
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 NB: Potrebna advertise address može se vidjeti u konfiguraciji api-servera, koja je po defaultu smještena u /etc/kubernetes/manifests/kube-apiserver.yaml.
Rezultantna konfiguracija bit će ispisana u stdout. Potrebno ju je pohraniti u ~/kube/config korisnički račun ili u datoteku navedenu u varijabli okruženja KUBECONFIG.
Zaviriti dublje
Za one koji žele detaljnije proučiti opisane teme:
- o radu sa certifikatima u službenoj dokumentaciji Kubernetes;
- , u kojem je pitanje certifikata obrađeno s praktične strane.
- o autentifikaciji u Kubernetes.
Autorizacija
Defaultni autorizirani korisnički račun nema prava na radnje u klasteru. Za dodjelu dozvola u Kubernetes-u implementiran je mehanizam autorizacije.
Do verzije 1.6 u Kubernetes-u koristio se tip autorizacije nazvan ABAC (Kontrola pristupa temeljenog na atributima). Detalje o njemu možete pronaći u . Trenutno se ovaj pristup smatra zastarjelim (legacy), međutim i dalje ga možete koristiti zajedno s drugim tipovima autorizacije.
Aktualni (i fleksibilniji) način podjele prava pristupa klasteru naziva se RBAC (). Proglašen je stabilnim od verzije . RBAC implementira model prava u kojem je sve zabranjeno što nije izričito dozvoljeno.
Da biste omogućili RBAC, potrebno je pokrenuti Kubernetes api-server s parametrima --authorization-mode=RBAC. Parametri se postavljaju u manifest s konfiguracijom api-servera, koji se po defaultu nalazi na putu /etc/kubernetes/manifests/kube-apiserver.yaml, u sekciji naredba. Ipak, RBAC je po defaultu već uključen, stoga se vjerojatno ne morate brinuti o tome: možete se uvjeriti u to prema vrijednosti authorization-mode (u već spomenutom kube-apiserver.yaml). Usput, među njegovim vrijednostima mogu se naći i drugi tipovi autorizacije (čvor, webhook, always allow), ali ćemo njihovo razmatranje ostaviti izvan okvira ovog materijala.
U međuvremenu, već smo objavili dovoljno detaljno izlaganje principa i osobitosti rada s RBAC-om, tako da ću se dalje ograničiti na kratak popis osnova i primjera.
Za upravljanje pristupom u Kubernetes-u putem RBAC-a koriste se sljedeće API entitete:
-
UlogaiClusterRole— uloge koje služe za opisivanje prava pristupa: -
Ulogaomogućuje opisivanje prava unutar imenskog prostora; -
ClusterRole— unutar klastera, uključujući klaster-specifične objekte poput čvorova, non-resources url-ova (tj. onih koji nisu povezani s resursima Kubernetes — kao što su/version,/logs,/api*); -
RoleBindingiClusterRoleBinding— služi za povezivanjeUlogaiClusterRoles korisnikom, grupom korisnika ili ServiceAccount-om.
Entiteti Role i RoleBinding su ograničeni imenskim prostorom, tj. moraju se nalaziti unutar jednog imenskog prostora. Međutim, RoleBinding može referencirati ClusterRole, što omogućava stvaranje seta standardnih dozvola i upravljanje pristupom putem njih.
Uloge opisuju prava pomoću skupova pravila koja sadrže:
- grupe API — vidi o apiGroups i izlazu
kubectl api-resources; - resurse (resources:
pod,namespace,deploymentitd.); - glagole (verbs:
set,updateitd.). - imena resursa (
resourceNames) — u slučaju kada je potrebno omogućiti pristup određenom resursu, a ne svim resursima tog tipa.
Detaljnije razmatranje autorizacije u Kubernetesu može se pronaći na stranici . Umjesto toga (a točnije — kao dodatak tome) dajem primjere koji ilustriraju njen rad.
Primjeri entiteta RBAC
Jednostavan Uloga, koji omogućava dobivanje popisa i statusa podova i njihovo praćenje u imenskom prostoru 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, što omogućava dobivanje popisa i statusa podova i njihovo praćenje u cijelom klasteru:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# nema sekcije "namespace", jer ClusterRole obuhvaća cijeli klaster
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] Primjer RoleBinding, što omogućava korisniku mynewuser "čitati" podove u imenskom prostoru my-namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: target-namespace
subjects:
- kind: User
name: mynewuser # ime korisnika ovisno o velikim i malim slovima!
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # ovdje mora biti “Role” ili “ClusterRole”
name: pod-reader # ime Role, koja se nalazi u istom namespace,
# ili ime ClusterRole koju
# želimo omogućiti korisniku
apiGroup: rbac.authorization.k8s.ioRevizija događaja
Shematski se arhitektura Kubernetesa može predstaviti na sljedeći način:

Ključna komponenta Kubernetesa, odgovorna za obradu zahtjeva, — api-server. Sve operacije na klasteru prolaze kroz njega. Više o ovim unutarnjim mehanizmima možete pročitati u članku „».
Revizija sustava — zanimljiva značajka u Kubernetesu koja je prema zadanim postavkama isključena. Omogućuje bilježenje svih zahtjeva na Kubernetes API. Kao što se može lako pretpostaviti, putem ovog API-aja izvršavaju se sve radnje povezane s kontrolom i promjenom stanja klastera. Dobar opis njenih mogućnosti možete (kao obično) pronaći u K8s. U nastavku ću pokušati izložiti temu jednostavnijim jezikom.
Dakle, da uključimo reviziju, trebamo proslijediti kontejneru u api-server tri obvezna parametra, o kojima je više detalja navedeno u nastavku:
-
--audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml -
--audit-log-path=/var/log/kube-audit/audit.log -
--audit-log-format=json
Osim ovih triju obveznih parametara, postoji mnogo dodatnih postavki vezanih uz reviziju: od rotacije logova do opisa webhooka. Primjer parametara rotacije logova:
-
--audit-log-maxbackup=10 -
--audit-log-maxsize=100 -
--audit-log-maxage=7
Ali nećemo se previše zadržavati na njima — sve detalje možete pronaći u .
Kao što je već spomenuto, svi parametri postavljaju se u manifest s konfiguracijom api-servera (po zadanim postavkama /etc/kubernetes/manifests/kube-apiserver.yaml), u sekciji naredba. Vratimo se na tri obvezna parametra i razmotrimo ih:
-
audit-policy-file— put do YAML datoteke s opisom politike (policy) revizije. O njenom sadržaju još ćemo se vratiti, a za sada napominjem da datoteka mora biti dostupna procesu api-servera. Stoga je potrebno montirati je unutar kontejnera, a za to možete dodati sljedeći kod u odgovarajuće sekcije konfiguracije:volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies -
audit-log-path— put do datoteke loga. Put također mora biti dostupan procesu api-servera, stoga ga također opisujemo na sličan način:volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs -
audit-log-format— format loga revizije. Prema zadanim postavkama to jejson, ali dostupan je i zastarjeli tekstualni format (legacy).
Politika revizije
Sada o spomenutoj datoteci s opisom politike bilježenja. Prvo pojmove audit policy — to je level, razina bilježenja. One mogu biti sljedeće:
-
Nema— ne bilježiti; -
Metadata— bilježenje metapodataka zahtjeva: korisnika, vrijeme zahtjeva, ciljani resurs (pod, namespace itd.), tip akcije (verb) itd.; -
Request— bilježenje metapodataka i tijela zahtjeva; -
RequestResponse— bilježenje metapodataka, tijela zahtjeva i tijela odgovora.
Posljednja dva nivoa (Request i RequestResponse) ne bilježe zahtjeve koji nisu pozivali resurse (pozive na takozvane non-resources urls).
Također, svi zahtjevi prolaze kroz nekoliko faza:
-
RequestReceived— faza kada je zahtjev primljen od strane obraditelja i još nije proslijeđen dalje kroz lanac obraditelja; -
ResponseStarted— glava odgovora je poslana, ali prije slanja tijela odgovora. Generira se za dugotrajne zahtjeve (na primjer,watch); -
ResponseComplete— tijelo odgovora je poslano, više informacija neće biti poslane; -
Panic— događaji se generiraju kada se otkrije izvanredna situacija.
Za preskakanje bilo kojih faza može se koristiti omitStages.
U datoteci politike možemo opisati nekoliko sekcija sa različitim nivoima bilježenja. Primijenit će se prvo odgovarajuće pravilo pronađeno u opisu politike.
Demon kubelet prati promjene manifesta s konfiguracijom api-servera i kada ih otkrije, ponovno pokreće kontejner s api-serverom. No postoji važna sitnica: promjene u datoteci politike će se ignorirati. Nakon unosa promjena u datoteku politike potrebno je ručno ponovno pokrenuti api-server. Budući da je api-server pokrenut kao , tim kubectl delete neće dovesti do njegovog ponovnog pokretanja. Trebat će ručno izvršiti docker stop na kube-masterima, gdje je politika audita promijenjena:
docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')Pri uključivanju audita važno je zapamtiti da na kube-apiserveru opterećenje raste. Konkretno, povećava se potrošnja memorije za pohranu konteksta zahtjeva. Bilježenje u log počinje samo nakon slanja glave odgovora. Također, opterećenje ovisi o konfiguraciji politike audita.
Primjeri politika
Razmotrit ćemo strukturu datoteka politike na primjerima.
Evo jednostavne datoteke policy, kako bismo bilježili sve na nivou Metadata:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata U politici se može navesti popis korisnika (Korisnici i ServiceAccounts) i grupi korisnika. Na primjer, ovako ćemo ignorirati sistemske korisnike, ali bilježiti sve ostalo na nivou 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: RequestTakođer postoji mogućnost opisivanja ciljeva:
- imenskih prostora (
imena prostora); - glagole (verbs:
preuzmi,update,izbrišii ostalih); - resurse (resources, odnosno:
pod,configmapsi slično) i grupe resursa (apiGrupe).
Obratite pažnju! Resursi i grupe resursa (grupe API, tj. apiGrupe), kao i njihove verzije instalirane u klasteru, mogu se dobiti pomoću naredbi:
kubectl api-resources
kubectl api-versionsSljedeća audit politika navedena je kao demonstracija najboljih praksi u :
apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Ne bilježi fazu RequestReceived
omitStages:
- "RequestReceived"
rules:
# Ne bilježi događaje koji se smatraju beznačajnima i ne opasnim:
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # ovo je api grupa s praznim imenom, kojoj pripadaju
# osnovni resursi Kubernetes-a, nazvani “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"]
# Ne bilježi pristupe read-only URL-ovima:
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Ne bilježi poruke vezane uz tip resursa “događaji”:
- level: None
resources:
- group: "" # core
resources: ["events"]
# Resursi tipa Secret, ConfigMap i TokenReview mogu sadržavati tajne podatke,
# zato bilježimo samo metapodatke povezanih s njima zahtjeva
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
# Radnje tipa get, list i watch mogu biti resursno intenzivne; ne bilježimo ih
- 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"
# Zahtev za bilježenje po defaultu za standardne API resurse
- 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"
# Default nivo logovanja za sve ostale zahteve
- level: MetadataDrugi dobar primjer audit policy-a — .
Za brze reakcije na audit događaje postoji mogućnost opisati webhook. Ovo pitanje je obrađeno u , ostavit ću ga izvan okvira ovog članka.
Zaključci
U članku je dan pregled mehanizama osnovnog osiguranja u Kubernetes klasterima, koji omogućuju stvaranje personaliziranih korisničkih računa, razdjeljivanje njihovih prava i registraciju njihovih aktivnosti. Nadam se da će biti koristan onima koji su se suočili s takvim pitanjima u teoriji ili su ih već iskusili u praksi. Preporučujem vam da se također upoznate s popisom drugih materijala o sigurnosti u Kubernetesu navedenim u "P.S." — možda ćete među njima pronaći potrebne detalje o problemima koji su vam važni.
P.S.
Pročitajte i na našem blogu:
- «»;
- «»;
- «»;
- «»;
- «».
Izvor: habr.com
