
Prej ko ali kasneje se v delovanju vsakega sistema postavi vprašanje varnosti: zagotavljanje avtentikacije, razdeljevanje pravic, revizije in drugih nalog. Za Kubernetes je že ustvarjenih , ki omogočajo dosego skladnosti s standardi tudi v zelo zahtevnih okoljih... Ta material je posvečen osnovnim vidikom varnosti, uveljavljenim v okviru vgrajenih mehanizmov K8s. Predvsem bo koristen tistim, ki se začenjajo spoznavati s Kubernetesom, - kot izhodiščna točka za preučevanje vprašanj, povezanih z varnostjo.
Autentifikacija
V Kubernetesu obstajata dva tipa uporabnikov:
- Service Accounts — računi, ki jih upravlja Kubernetes API;
- Uporabniki — 'običajni' uporabniki, ki jih upravljajo zunanje, neodvisne storitve.
Glavna razlika med tema tipoma je, da za Service Accounts obstajajo posebni objekti v Kubernetes API (ti se imenujejo - ServiceAccounts), ki so vezani na prostor imen in niz avtorizacijskih podatkov, shranjenih v gručah v objektih tipa Secrets. Takšni uporabniki (Service Accounts) so namenjeni predvsem upravljanju pravic dostopa do Kubernetes API procesov, ki delujejo v Kubernetes gručah.
Običajni uporabniki pa nimajo zapisov v Kubernetes API: upravljanje z njimi mora potekati preko zunanjih mehanizmov. Namenjeni so osebam ali procesom, ki živijo zunaj gruče.
Vsak zahtevek k API je povezan bodisi s Service Account bodisi z uporabnikom bodisi velja za anonimnega.
Avtentikacijski podatki uporabnika vključujejo:
- Uporabniško ime — uporabniško ime (odvisno od malih in velikih črk!);
- UID — strojno berljiva identifikacijska vrstica uporabnika, ki je 'bolj dosledna in edinstvena kot uporabniško ime';
- Skupine — seznam skupin, za katere se šteje uporabnik;
- Dodatno — dodatna polja, ki jih lahko uporabi mehanizem avtorizacije.
Kubernetes lahko uporablja veliko število mehanizmov avtentikacije: certifikati X509, Bearer žetoni, avtentikacijski proxy, HTTP Basic Auth. S pomočjo teh mehanizmov je mogoče uresničiti veliko število shem avtorizacije: od statičnega datoteke s gesli do OpenID OAuth2.
Poleg tega je dovoljena uporaba več shem avtorizacije hkrati. Privzeto se v gruči uporabljajo:
- žetoni službenih računov — za Service Accounts;
- X509 — za uporabnike.
Vprašanje o upravljanju ServiceAccounts presega obseg tega članka, zato tistim, ki želijo podrobneje spoznati to temo, priporočam, da začnejo s . Mi pa bomo podrobneje obravnavali vprašanje delovanja certifikatov X509.
Certifikati za uporabnike (X.509)
Klasičen način dela s certifikati predvideva:
- generacijo ključa:
mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/..certs/mynewuser.key 2048 - generacijo zahteve za certifikat:
openssl req -new -key ~/..certs/mynewuser.key -out ~/..certs/mynewuser.csr -subj "/CN=mynewuser/O=company" - obdelavo zahteve za certifikat s pomočjo ključev CA grozda Kubernetes, pridobitev certifikata uporabnika (za pridobitev certifikata morate uporabiti račun, ki ima dostop do ključa certifikacijske agencije grozda Kubernetes, ki je privzeto 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 - ustvarjanje konfiguracijske datoteke:
- opis grozda (navedite naslov in lokacijo datoteke certifikata CA konkretne namestitve grozda):
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 - ali — kako nepriporočena možnost — lahko ne navedete koreninskega certifikata (takrat kubectl ne bo preverjal pravilnosti api-serverja grozda):
kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 - dodajanje uporabnika v konfiguracijsko datoteko:
kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key - dodajanje konteksta:
kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser - določitvi privzetega konteksta:
kubectl config use-context mynewuser-context
- opis grozda (navedite naslov in lokacijo datoteke certifikata CA konkretne namestitve grozda):
Po zgoraj navedenih postopkih bo v datoteki .kube/config ustvarjena konfiguracija v obliki:
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 lažje prenašanje konfiguracije med računi in strežniki je koristno urediti vrednosti naslednjih ključev:
-
certificate-authority -
client-certificate -
client-key
Za to lahko kodirate navedene datoteke s pomočjo base64 in jih vnesete v konfiguracijo, tako da dodate pripono -data, torej pridobite certificate-authority-data itd.
Certifikati s kubeadm
Z izdajo Delo s sertifikatami postalo znatno lažje zahvaljujoč alfa različici njene podpore v . Na primer, tako lahko zdaj izgleda generacija konfiguracijske datoteke s korisniškimi ključi:
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 NB: Zahtevana advertise address lahko si ogledate v konfiguraciji api-server, ki je privzeto locirana v /etc/kubernetes/manifests/kube-apiserver.yaml.
Končni konfiguracij bo izpisan v stdout. Shraniti ga je treba v ~/.kube/config uporabniški račun ali pa v datoteko, določeno v okoljski spremenljivki KUBECONFIG.
Poglejmo podrobneje
Za tiste, ki želijo bolj temeljito razumeti obravnavane teme:
- o delu s sertifikatami v uradni dokumentaciji Kubernetes;
- , v katerem so vprašanja o sertifikatih obravnavana z praktičnega vidika.
- o avtorizaciji v Kubernetes.
Avtorizacija
Avtoriziran uporabniški račun po privzetku nima pravic za delo v klastru. Za dodelitev dovoljenj v Kubernetesu je bil uveden mehanizem avtorizacije.
Do različice 1.6 se je v Kubernetesu uporabljal tip avtorizacije, imenovan ABAC (Attribute-based access control). Podrobnosti o njem lahko najdete v . Ta pristop se trenutno šteje za zastarelega (legacy), vendar ga še vedno lahko uporabljate hkrati z drugimi tipi avtorizacije.
Trenutni (in bolj prilagodljiv) način razdeljevanja pravic dostopa do klastru se imenuje RBAC (). Bil je razglašen za stabilnega od različice . RBAC uveljavlja model pravic, v katerem je vse, kar ni izrecno dovoljeno, prepovedano.
Da bi omogočili RBAC, morate zagnati Kubernetes api-server s parametrom --authorization-mode=RBAC. Parametri se nastavijo v manifestu s konfiguracijo api-server, ki je privzeto na poti /etc/kubernetes/manifests/kube-apiserver.yaml, v razdelku ukaz. Pravzaprav je RBAC po privzetku že vključen, zato verjetno ni razloga za skrb: preveriti to je mogoče po vrednosti authorization-mode (v že omenjenem kube-apiserver.yaml). Mimogrede, med njegovimi vrednostmi so lahko tudi drugi tipi avtorizacije (node, webhook, always allow), vendar tovrstno obravnavo prepustimo drugim virom.
Mimogrede, že smo objavili z dovolj podrobnim opisom načel in značilnosti dela z RBAC, zato se bom nadalje omejil na kratko naštevanje osnov in primerov.
Za upravljanje dostopa v Kubernetes preko RBAC se uporabljajo naslednje entitete API:
-
RoleinClusterRole— vloge, ki se uporabljajo za opis pravic dostopa: -
Roleomogoča opisovanje pravic v okviru imenskega prostora; -
ClusterRole— v okviru gruče, vključno s gručnimi specifičnimi objekti, kot so vozli, URL-ji brez virov (tj. niso povezani z viri Kubernetes — na primer,/version,/logs,/api*); -
RoleBindinginClusterRoleBinding— služi za vezavoRoleinClusterRolena uporabnika, skupino uporabnikov ali ServiceAccount.
Entitete Role in RoleBinding so omejene na imenski prostor, tj. morajo biti v okviru enega samega imenskega prostora. Vendar pa lahko RoleBinding sklicuje na ClusterRole, kar omogoča ustvarjanje naborov standardnih dovoljenj in upravljanje dostopa z njimi.
Vloge opisujejo pravice s pomočjo naborov pravil, ki vsebujejo:
- skupine API — glej po apiGroups in izhodu
kubectl api-resources; - viri (resources:
pod,namespace,deploymentitd.); - glagoli (verbs:
set,updateitd.). - imena virov (
resourceNames) — v primeru, ko je potrebno omogočiti dostop do določenega vira, ne pa do vseh virov te vrste.
Podrobnejšo analizo avtorizacije v Kubernetes lahko najdete na strani . Namesto tega (natančneje — v dodatku k temu) bom navedel primere, ki ponazarjajo njeno delovanje.
Primeri entitet RBAC
Jednostavno Role, ki omogoča pridobivanje seznama in statusa podov ter spremljanje le-teh v imenskem 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"] Primer ClusterRole, kar omogoča pridobitev seznama in statusa podov ter spremljanje le-teh v celotnem grozdu:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# sekcije "namespace" ni, saj ClusterRole deluje v celotnem grozdu
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] Primer RoleBinding, kar uporabniku mynewuser omogoča «branje» podov v imenskem prostoru my-namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: target-namespace
subjects:
- kind: User
name: mynewuser # ime uporabnika je občutljivo na velikost črk!
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # tukaj mora biti “Role” ali “ClusterRole”
name: pod-reader # ime Role, ki se nahaja v istem imenskem prostoru,
# ali ime ClusterRole, katere uporabo
# želimo dovoliti uporabniku
apiGroup: rbac.authorization.k8s.ioRevizija dogodkov
Arhitekturo Kubernetes lahko shematično predstavimo takole:

Ključna komponenta Kubernetes, odgovorna za obdelavo zahtevkov, — api-server. Vse operacije nad grozdom potekajo preko njega. Več o teh notranjih mehanizmih lahko preberete v članku «».
Avtomatska revizija sistema je zanimiva funkcija v Kubernetesu, ki je privzeto izključena. Omogoča beleženje vseh dostopov do Kubernetes API. Kot lahko ugibate, preko tega API se izvajajo vse akcije, povezane s kontrolo in spremembo stanja klasterja. Dober opis njenih zmožnosti lahko (kot ponavadi) najdete v K8s. Nadalje bom poskušal tematiko predstaviti bolj preprosto.
Dakle, Da bi omogočili revizijo, moramo api-serverju posredovati tri obvezne parametre, o katerih bomo podrobneje govorili spodaj:
-
--audit-policy-file=\/etc\/kubernetes\/policies\/audit-policy.yaml -
--audit-log-path=\/var\/log\/kube-audit\/audit.log -
--audit-log-format=json
Poleg teh treh obveznih parametrov obstaja še vrsta dodatnih nastavitev, ki se nanašajo na revizijo: od rotacije logov do opisov webhookov. Primer parametrov rotacije logov:
-
--audit-log-maxbackup=10 -
--audit-log-maxsize=100 -
--audit-log-maxage=7
Vendar se ne bomo podrobneje ukvarjali z njimi — vse podrobnosti lahko najdete v .
Kot je bilo že omenjeno, se vsi parametri nastavijo v manifestu z konfiguracijo api-serverja (privzeto /etc/kubernetes/manifests/kube-apiserver.yaml), v razdelku ukaz. Vrnimo se k trem obveznim parametrom in jih razčlenimo:
-
audit-policy-file— pot do YAML datoteke z opisom politike (policy) revizije. K njeni vsebini se bomo še vrnili, zaenkrat pa naj poudarim, da mora biti datoteka dostopna za branje procesu api-serverja. Zato ji je treba pritrditi v znotraj posode, za kar lahko dodate naslednjo kodo v ustrezne razdelke konfiguracije:volumeMounts: - mountPath: \/etc\/kubernetes\/policies name: policies readOnly: true volumes: - hostPath: path: \/etc\/kubernetes\/policies type: DirectoryOrCreate name: policies -
audit-log-path— pot do datoteke loga. Pot mora biti tudi dostopna procesu api-serverja, zato je priporočen postopek montaže: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 revizijskega loga. Privzeto je tojson, vendar je na voljo tudi zastarela besedilna oblika (legacy).
Politika revizije
Zdaj se osredotočimo na omenjeno datoteko z opisom politike beleženja. Prvi pojem audit policy je level, nivo beleženja. Lahko so naslednji:
-
Noben— ne beleži; -
Metadata— beleži metapodatke poizvedbe: uporabnika, čas poizvedbe, ciljni vir (pod, namespace itd.), tip dejanja (verb) itd.; -
Request— beleži metapodatke in telo poizvedbe; -
RequestResponse— beleži metapodatke, telo poizvedbe in telo odgovora.
Zadnja dva nivoa (Request in RequestResponse) ne beleže zahteve koji se ne upućuju resursima (upiti na tzv. non-resources urls).
Takođe, svi zahtevi prolaze kroz nekoliko faza:
-
RequestReceived— faza kada je zahtev primljen od strane obradnika i još nije prosleđen dalje u lancu obradnika; -
ResponseStarted— zaglavlja odgovora su poslata, ali pre nego što se pošalje telo odgovora. Generiše se za dugotrajne zahteve (na primer,watch); -
ResponseComplete— telo odgovora je poslato, više informacija neće biti poslato; -
Panic— događaji se generišu kada se otkrije vanredna situacija.
Za preskakanje bilo kojih faza može se koristiti omitStages.
U fajlu politike možemo opisati nekoliko sekcija sa različitim nivoima logovanja. Primenjivaće se prvo pogodna pravila, pronađena u opisu politike.
Demon kubelet prati promene manifesta sa konfiguracijom api-server-a i prilikom otkrivanja takvih ponovo pokreće kontejner sa api-server-om. Ali postoji važan detalj: promene u fajlu politike će se ignorisati. Nakon izmene fajla politike, potrebno je ručno ponovo pokrenuti api-server. Pošto je api-server pokrenut kao , komanda kubectl delete neće dovesti do njegovog ponovnog pokretanja. Moraćemo ručno uraditi docker stop na kube-master-ima gde je politika audita promenjena:
docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')Prilikom uključivanja audita, važno je zapamtiti da na kube-apiserver-u raste opterećenje. Konkretno, povećava se potrošnja memorije za skladištenje konteksta zahteva. Zapisivanje u log počinje tek nakon slanja zaglavlja odgovora. Takođe, opterećenje zavisi od konfiguracije politike audita.
Primeri politika
Razradićemo strukturu fajlova politike na primerima.
Evo jednostavnog fajla policy, da logujemo sve na nivou Metadata:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata U politici se može navesti spisak korisnika (Uporabniki in ServiceAccounts) i grupa korisnika. Na primer, ovako ćemo ignorisati sistemske korisnike, ali logovati 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đe postoji mogućnost opisivanja ciljeva:
- imenici (
namespaces); - glagoli (verbs:
pridobi,update,izbrišii slično); - viri (resources, a to su:
pod,configmapsi sl.) i grupe resursa (apiGroups).
Obratite pažnju! Viri in skupine virov (skupine API, torej apiGroups) ter njihove različice, nameščene v gručah, je mogoče pridobiti z naslednjimi ukazi:
kubectl api-resources
kubectl api-versionsNaslednja politika revizije je navedena kot prikaz najboljših praks v :
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Другой хороший пример политики аудита — .
Для оперативного реагирования на события аудита есть возможность описать webhook. Этот вопрос раскрыт в , pustim ga izvan okvira ovog članka.
Zaključki
Članak pruža pregled mehanizama osnovne bezbednosti u Kubernetes klasterima, koji omogućavaju kreiranje personalizovanih korisničkih naloga, deljenje prava, kao i evidentiranje njihovih aktivnosti. Nadam se da će koristiti onima koji su se susreli s ovim pitanjima, bilo teoretski ili u praksi. Takođe preporučujem da pogledate spisak drugih materijala o bezbednosti u Kubernetesu naveden u "P.S.", možda među njima pronađete potrebne detalje koji su vam bitni.
P.S.
Preberite tudi na našem blogu:
- «»;
- «»;
- «»;
- «»;
- «».
Izvor: habr.com
