
Dhe një ditë, në përdorimin e çdo sistemi, ngrihet çështja e sigurisë: garantimi i autentifikimit, ndarja e të drejtave, auditimi dhe detyra të tjera. Për Kubernetes ka tashmë , të cilat lejojnë arritjen e përputhshmërisë me standardet edhe në mjedise mjaft kërkuese… Ky material është i përkushtuar ndaj aspekteve themelore të sigurimit, të realizuara brenda mekanizmave të integruar të K8s. Në radhë të parë, kjo do të jetë e dobishme për ata që fillojnë të njoftohen me Kubernetes, si një pikënisje për studimin e çështjeve që lidhen me sigurinë.
Autentifikimi
Në Kubernetes ka dy lloje përdoruesish:
- Llogaritë e Shërbimit — llogari e menaxhuar nga Kubernetes API;
- Përdoruesit — përdorues normalë, të menaxhuar nga shërbime të jashtme dhe të pavarura.
Dallimi kryesor midis këtyre lirave është se për Llogaritë e Shërbimit ekzistojnë objekte speciale në Kubernetes API (ato quhen gjithashtu — Llogaritë e Shërbimit), të cilat janë të lidhura me hapësirën emërore dhe një grup të dhënash autorizimi, të ruajtura në klaster në objekte të tipit Secrets. Këta përdorues (Llogaritë e Shërbimit) janë të destinuar kryesisht për menaxhimin e të drejtave të aksesit në Kubernetes API të proceseve që funksionojnë në klasterin Kubernetes.
Përdoruesit e zakonshëm nuk kanë regjistrime në Kubernetes API: menaxhimi i tyre duhet të kryhet nga mekanizma të jashtëm. Ato janë të destinuara për njerëz ose procese që jetojnë jashtë klasterit.
Çdo kërkesë për API është e lidhur me një hesap shërbimi, një përdorues, ose konsiderohet si anonime.
Të dhënat autentikuese të përdoruesit përfshijnë:
- Emri i përdoruesit — emri i përdoruesit (varet nga rastisja!);
- UID — një varg identifikimi që 'është më konsistent dhe unik se emri i përdoruesit';
- Grupet — lista e grupeve të cilave i përket përdoruesi;
- Extra — fusha shtesë që mund të përdoren nga mekanizmi i autorizimit.
Kubernetes mund të përdorë një numër të madh mekanizmash autentikimi: certifikata X509, Bearer tokena, proxy autentikimi, HTTP Basic Auth. Me këta mekanizma mund të realizohet një gamë e gjerë skemash autorizimi: nga një skedë statike me fjalëkalime deri në OpenID OAuth2.
Më tepër, lejohet përdorimi i disa skemave autorizimi njëkohësisht. Në mënyrë të parazgjedhur në klaster përdoren:
- tokens e shërbimit — për Hesape Shërbimi;
- X509 — për Përdoruesit.
Çështja e menaxhimit të ServiceAccounts del jashtë kornizës së këtij artikulli, dhe atyre që dëshirojnë të njohin më shumë rreth këtij problemi, rekomandoj të fillojnë me . Ne do të shqyrtojmë më thellë çështjen e punës me sertifikatat X509.
Sertifikatat për përdoruesit (X.509)
Mënyra klasike e punës me sertifikatat supozon:
- gjenerimin e çelësit:
mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/.certs/mynewuser.key 2048 - gjenerimin e një kërkese për sertifikatë:
openssl req -new -key ~/mynewuser/.certs/mynewuser.key -out ~/mynewuser/.certs/mynewuser.csr -subj "/CN=mynewuser/O=company" - përpunimin e kërkesës për sertifikatë me ndihmën e çelësave CA të klasterit Kubernetes, marrjen e sertifikatës së përdoruesit (për të marrë sertifikatën, duhet të përdoret një llogari që ka akses në çelësin e qendrës së sertifikimit të klasterit Kubernetes, i cili normalisht ndodhet në
/etc/kubernetes/pki/ca.key):openssl x509 -req -in ~/mynewuser/.certs/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/mynewuser/.certs/mynewuser.crt -days 500 - krijimin e skedarit të konfigurimit:
- përshkrimi i klasterit (specifikoni adresën dhe vendndodhjen e skedarit të sertifikatës CA të instalimit të veçantë të klasterit):
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 - ose — si nukopsioni i rekomanduar — nuk është e nevojshme të specifikohet certifikata e rrënjës (në këtë rast kubectl nuk do të verifikojë saktësinë e api-server të klasterit):
kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 - shtimi i përdoruesit në skedarin e konfigurimit:
kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key - shtimi i kontekstit:
kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser - caktimi i kontekstit si default:
kubectl config use-context mynewuser-context
- përshkrimi i klasterit (specifikoni adresën dhe vendndodhjen e skedarit të sertifikatës CA të instalimit të veçantë të klasterit):
Pas manipulimeve të mësipërme, në skedarin .kube/config do të krijohet një konfigurim i tillë:
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.keyPër lehtësimin e transferimit të konfiguracionit mes përdoruesve dhe serverëve është e dobishme të redaktohen vlerat e çelçave të mëposhtme:
-
certificate-authority -
client-certificate -
client-key
Për këtë mund të kodoni skedaret e specifikuara me base64 dhe t'i shkruani ato në konfigurim, duke shtuar në emrin e çelçave sufixin -data, dmth, duke marrë certificate-authority-data etj.
Certifikatat me kubeadm
Me lëshimin punimi me certifikatat është bërë shumë më i lehtë falë mbështetjes në version alpha të tij në . Për shembull, ja se si mund të duket tani gjenerimi i skedarit të konfigurimit me çelësat e përdoruesit:
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 NB: E kërkuar adresa e reklamimit mund të shihet në konfigurimin e api-serverit, i cili ndodhet për default në /etc/kubernetes/manifests/kube-apiserver.yaml.
Konfiguimi rezultat do të dërgohet në stdout. Ai duhet të ruhet në ~/.kube/config llogarinë e përdoruesit ose në një skedar të caktuar në variablin e mjedisit KUBECONFIG.
Hidhuni më thellë
Për ata që dëshirojnë të kuptojnë më thellë çështjet e përshkruara:
- për punën me certifikatat në dokumentacionin zyrtar të Kubernetes;
- , ku çështja e certifikatave trajtohet nga një këndvështrim praktik.
- për autentifikimin në Kubernetes.
Autorizimi
Llogaria e autorizuar për default nuk ka të drejta për veprime në klaster. Për të ofruar leje në Kubernetes, është implementuar një mekanizëm autorizimi.
Derisa në versionin 1.6 në Kubernetes përdorej një tip autorizimi, i njohur si ABAC (Kontrolli i qasjes mbi atributet). Detajet rreth tij mund të gjenden në . Aktualisht ky qasje konsiderohet i vjetruar (legacy), megjithatë ju mund ta përdorni atë njëkohësisht me lloje të tjera autorizimi.
Metoda më aktuale (dhe më fleksibël) për ndarjen e të drejtave të qasjes në një klaster quhet RBAC (). Ai u shpall stabil nga versioni . RBAC implementon një model të të drejtave, ku gjithçka është e ndaluar përveç asaj që është shprehimisht e lejuar.
Për të aktivizuar RBAC, është e nevojshme të niset api-server Kubernetes me parametrin --authorization-mode=RBAC. Parametrat vendosen në manifenstimin me konfigurimin e api-server, i cili për default gjendet në rrugën /etc/kubernetes/manifests/kube-apiserver.yaml, në seksionin command. Megjithatë, për default, RBAC është tashmë e aktivizuar, prandaj ndoshta nuk ka nevojë për t'u shqetësuar për këtë: mund ta verifikoni këtë me vlerën authorization-mode (në atë që u përmend më parë kube-apiserver.yaml). Për më tepër, mes vlerave të tij mund të jenë edhe lloje të tjera autorizimi (node, webhook, always allow), por shqyrtimi i tyre do ta lërë jashtë kufijve të materialit.
Për më tepër, ne tashmë kemi publikuar me një tregim mjaft të detajuar rreth parimeve dhe veçorive të punës me RBAC, prandaj do të kufizohem me një përmbledhje të shkurtër të të parave dhe shembujve.
Për menaxhimin e qasjes në Kubernetes përmes RBAC përdoren entitete të tjera API:
-
RoldheClusterRole— rollet që shërbejnë për të përshkruar të drejtat e qasjes: -
Rollejon përshkrimin e të drejtave brenda një hapësire emri; -
ClusterRole— brenda klasterit, përfshirë objektet specifikë për klasterin siç janë nyjet, non-resources urls (pra, ato që nuk lidhen me burimet Kubernetes — për shembull,/version,/logs,/api*); -
RoleBindingdheClusterRoleBinding— shërben për lidhjenRoldheClusterRoleme një përdorues, një grup përdoruesish ose ServiceAccount.
Entitetet Role dhe RoleBinding janë të kufizuara në hapësirën emrit, domethënë, ato duhet të jenë brenda një hapësire emri. Megjithatë, RoleBinding mund të referojë një ClusterRole, gjë që lejon krijimin e një grupi standard të lejesh dhe menaxhimin e qasjes me ndihmën e tyre.
Rollet përshkruajnë të drejtat përmes grupeve të rregullave që përmbajnë:
- grupet API — shih për apiGroups dhe
daljet; - burimet (resources:
pod,namespace,deploymentetj.); - veprime (verbs:
set,updateetj.). - emrat e burimeve (
resourceNames) — për rastin kur duhet të jepni qasje në një burim të caktuar, jo në të gjitha burimet e këtij tipi.
Një analizë më të detajuar të autorizimit në Kubernetes mund të gjendet në faqen . Në vend të kësaj (ose më saktësisht — në shtesë të saj) do të jap disa shembuj që ilustrojnë funksionimin e saj.
Shembuj të entiteteve RBAC
E thjeshtë Rol, që lejon marrjen e listës dhe statusit të pod-ve dhe ndjekjen e tyre në hapësirën emërtuese hapësira-target:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: hapësira-target
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"] Shembuj ClusterRole, që lejon marrjen e listës dhe statusit të pod-ve dhe ndjekjen e tyre në të gjithë klasterin:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# seksioni "namespace" nuk është aty, pasi ClusterRole përfshin të gjithë klasterin
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] Shembuj RoleBinding, që i lejon përdoruesit mynewuser të "lexojë" pod-të në hapësirën emërtuese hapësira-ime:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: hapësira-target
subjects:
- kind: User
name: mynewuser # emri i përdoruesit është i ndjeshëm ndaj rastit!
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # këtu duhet të jetë “Role” ose “ClusterRole”
name: pod-reader # emri i Role që gjendet në të njëjtën hapësirë,
# ose emri i ClusterRole që duam
# të autorizojmë për përdoruesin
apiGroup: rbac.authorization.k8s.ioAuditimi i ngjarjeve
Arqitektura e Kubernetes-it mund të paraqitet në mënyrë schematike si më poshtë:

Komponenti kryesor i Kubernetes, i përgjegjshëm për përpunimin e kërkesave, është api-server. Të gjitha operacionet mbi klasterin kalojnë përmes tij. Më shumë rreth këtyre mekanizmave të brendshëm mund të lexoni në artikullin "».
Auditi i sistemit është një karakteristikë interesante në Kubernetes, e cila me default është e çaktivizuar. Ajo lejon regjistrimin e të gjitha kërkesave në API-në e Kubernetes. Siç mund të mendoni, përmes këtij API kryhen të gjitha veprimet e lidhura me kontrollin dhe ndryshimin e gjendjes së klasterit. Një përshkrim i mirë i mundësive të saj mund të gjendet (si zakonisht) në K8s. Më poshtë do përpiqem ta shpjegoj temën në një gjuhë më të thjeshtë.
Pra, për të aktivizuar auditin, na nevojitet t'i kalojmë kontenierit në api-server tre parametra të detyrueshëm, për të cilat është folur më poshtë:
-
--audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml -
--audit-log-path=/var/log/kube-audit/audit.log -
--audit-log-format=json
Përveç këtyre tre parametrave të nevojshëm, ekzistojnë shumë cilësime shtesë që lidhen me auditin: nga rotacioni i logeve deri te përshkrimet e webhook. Një shembull i parametrave të rotacionit të logeve:
-
--audit-log-maxbackup=10 -
--audit-log-maxsize=100 -
--audit-log-maxage=7
Por nuk do të ndalemi më gjatë mbi to - të gjitha detajet mund të gjenden në .
Siç u përmend më parë, të gjitha parametrat vendosen në manifestin e konfiguracionit të api-server (me të drejtë /etc/kubernetes/manifests/kube-apiserver.yaml), në seksionin command. Le të kthehemi te 3 parametrat e detyrueshme dhe t'i shqyrtojmë ata:
-
audit-policy-file— rruga deri te skedari YAML me përshkrimin e politikës (policy) së auditimit. Ne do të kthehemi në përmbajtjen e tij, derisa të theksojmë se skedari duhet të jetë i aksesueshëm për procesin api-server. Prandaj, është e nevojshme ta vendosim atë brenda kontejnerit, për të cilin mund të shtoni kodin e mëposhtëm në seksionet përkatëse të konfigurimit:volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies -
audit-log-path— rruga deri te skedari i logut. Rruga gjithashtu duhet të jetë e aksesueshme për procesin e api-server, prandaj në mënyrë të ngjashme përshkruajmë montimin e saj:volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs -
audit-log-format— formati i logut të auditimit. Për default, kjo ështëjson, por është e disponueshme edhe forma e tekstit të vjetruar (legacy).
Politika e auditimit
Tani për skedarin e përmendur me përshkrimin e politikës së logimit. Koncepti i parë të politikës së auditimit është level, niveli i logimit. Ato janë si më poshtë:
-
Asnjë— mos logimi; -
Metadata— logimi i metadatenave të kërkesës: përdoruesi, koha e kërkesës, burimi qëllimor (pod, namespace etj.), lloji i veprimit (verb) etj.; -
Kërkesa— logimi i metadatenave dhe trupit të kërkesës; -
KërkesaPërgjigja— logimi i metadatenave, trupit të kërkesës dhe trupit të përgjigjes.
Dy nivelet e fundit (Kërkesa dhe KërkesaPërgjigja) nuk logojnë kërkesat që nuk janë drejtuar burimeve (këto përbëjnë kërkesa ndaj URL-esh që nuk janë burime).
Gjithashtu, të gjitha kërkesat kalojnë përmes disa fazash:
-
KërkesaEPranuar— faza kur kërkesa është marrë nga trajtuesi dhe ende nuk është dërguar më tej në zinxhirin e trajtuesve; -
PërgjigjaEFilluar— titujt e përgjigjes janë dërguar, por para dërgimit të trupit të përgjigjes. Generohet për kërkesa të gjata (p.sh.,watch); -
PërgjigjaPërfunduar— trupi i përgjigjes është dërguar, nuk do të dërgohet më shumë informacion; -
Panic— ngjarje që gjenerohen kur zbulohet një situatë e jashtëzakonshme.
Për të anashkaluar ndonjë fazë, mund të përdoret omitStages.
Në skedarin e politikës mund të përshkruajmë disa seksione me nivele të ndryshme logimi. Rregulli i parë i përshtatshëm do të aplikohet, që do të gjendet në përshkrimin e politikës.
Demon kubelet monitoron ndryshimin e manifestit me konfigurimin e api-server dhe, kur e vëren këtë, rinis kontejnerin me api-server. Por ka një detaj të rëndësishëm: ndryshimet në skedarin policy do të injorohen prej tij. Pas ndryshimeve në skedarin policy, do të jetë e nevojshme të rinisni manualisht api-serverin. Duke qenë se api-serveri ekzekutohet si , komandën kubectl delete nuk do të shkaktojë rinisjen e tij. Duhet manualisht të bëni docker stop në kube-master-at, ku është ndryshuar politika e auditi:
docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')Kur është aktivizuar auditi, është e rëndësishme të mbani mend se ngarkohet më shumë kube-apiserveri. Në veçanti, rritet konsumimi i memories për ruajtjen e konteksteve të kërkesave. Shkalla e regjistrimit fillon vetëm pas dërgimit të titullit të përgjigjes. Gjithashtu, ngarkesa varet nga konfigurimi i politikës së auditi.
Shembuj politikash
Le të shqyrtojmë strukturën e skedarëve të policy me shembuj.
Ja një skedar i thjeshtë policy, për të regjistruar gjithçka në nivelin Metadata:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata Në policy mund të specifikoni një listë përdoruesish (Përdoruesit dhe Llogaritë e Shërbimit) dhe grupe përdoruesish. Për shembull, kështu do të injorojmë përdoruesit sistemikë, por do të regjistrojmë gjithçka tjetër në nivelin Kërkesa:
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: RequestKa gjithashtu ka mundësinë për të përshkruar destinacionet:
- hapësirat e emrave (
namespaces); - veprime (verbs:
merr,update,fshidhe të tjera); - burimet (resources, të quajtura:
pod,configmapsetj.) dhe grupe burimesh (apiGroups).
Vini re! Burimet dhe grupet e burimeve (grupet API, dmth. apiGroups), si dhe versionet e tyre, të instaluara në klaster, mund të merren përmes komandave:
kubectl api-resources
kubectl api-versionsPolitika e auditimit të mëposhtme është paraqitur si një demonstrim i praktikave më të mira në :
apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Mos logimi i fazës RequestReceived
omitStages:
- "RequestReceived"
rules:
# Mos logimi i ngjarjeve që konsiderohen të parëndësishme dhe jo të rrezikshme:
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # kjo është grupi i api me emër të zbrazët, i cili i përket
# burimeve bazë të Kubernetes, të njohura si “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"]
# Mos logimi i kërkesave për URLs vetëm për lexim:
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Mos logimi i mesazheve që i përkasin llojit të burimeve “ngjarje”:
- level: None
resources:
- group: "" # core
resources: ["events"]
# Burimet si Secret, ConfigMap dhe TokenReview mund të përmbajnë të dhëna sekrete,
# prandaj logojmë vetëm metadatën e kërkesave lidhur me to
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
# Veprat si get, list dhe watch mund të jenë burim-konsumues; mos i logojmë ato
- 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"
# Niveli i logimit nga default për burimet standarde të 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"
# Niveli i logimit nga default për të gjitha kërkesat e tjera
- level: MetadataNjë shembull tjetër i mirë i audit policy është .
Për të reaguar shpejt ndaj ngjarjeve të auditit, ka mundësi të përshkruani webhook. Ky çështje është trajtuar në , do ta lë jashtë këtij artikulli.
Përfundimet
Artikulli ofron një përmbledhje të mekanizmave bazë për sigurinë në klasteret Kubernetes, që lejojnë krijimin e llogarive të personalizuara për përdoruesit, ndarjen e të drejtave të tyre, si dhe regjistrimin e veprimeve të tyre. Shpresoj se do t’ju ndihmojë atyre që janë ballafaquar me këto çështje në teori ose tashmë në praktikë. Po ashtu rekomandoj që të shqyrtoni listën e materialeve të tjera mbi sigurinë në Kubernetes, e cila është e paraqitur në 'P.S.', ndoshta midis tyre do të gjeni detajet e nevojshme për problemet që ju interesojnë.
P.S.
Lexoni gjithashtu në blogun tonë:
- «»;
- «»;
- «»;
- «»;
- «».
Burimi: habr.com
