
Dříve nebo později se u každého systému objevuje otázka bezpečnosti: zajištění autentizace, rozdělení práv, auditu a dalších úkolů. Pro Kubernetes již bylo vytvořeno , která umožňují dosáhnout souladu se standardy i v velmi náročných prostředích… Tento materiál se zaměřuje na základní aspekty bezpečnosti, které jsou implementovány v rámci vstavaných mechanismů K8s. Především bude užitečný pro ty, kteří začínají s Kubernetes — jako výchozí bod pro studium otázek týkajících se bezpečnosti.
Autentizace
V Kubernetes existují dva typy uživatelů:
- Service Accounts — účty spravované Kubernetes API;
- Uživatelé — "normální" uživatelé, spravovaní externími, nezávislými službami.
Hlavní rozdíl mezi těmito typy spočívá v tom, že pro Service Accounts existují speciální objekty v Kubernetes API (nazývají se ServiceAccounts), které jsou vázány na jmenný prostor a sadu autorizačních údajů uložených v clusteru v objektech typu Secrets. Tito uživatelé (Service Accounts) jsou určeni především k řízení přístupových práv k Kubernetes API procesů, které běží v clusteru Kubernetes.
Obyčejní uživatelé (Users) nemají záznamy v Kubernetes API: jejich správa by měla být prováděna externími mechanismy. Jsou určeni pro lidi nebo procesy, které žijí mimo cluster.
Každý požadavek na API je vázán buď na Service Account, nebo na uživatele, nebo je považován za anonymní.
Autentizační údaje uživatele zahrnují:
- Uživatelské jméno — uživatelské jméno (závislé na velikosti písmen!);
- UID — strojově čitelný identifikační řetězec uživatele, který je "konzistentnější a jedinečnější než uživatelské jméno";
- Skupiny — seznam skupin, do kterých uživatel patří;
- Extra — další pole, která mohou být použita autorizačním mechanismem.
Kubernetes může používat mnoho autentizačních mechanismů: certifikáty X509, Bearer tokeny, autentizační proxy, HTTP Basic Auth. Pomocí těchto mechanismů lze implementovat řadu autorizačních schémat: od statického souboru s hesly po OpenID OAuth2.
Navíc je povoleno používat více autorizačních schémat současně. Ve výchozím stavu jsou v clusteru používána:
- service account tokens — pro Service Accounts;
- X509 — pro uživatele.
Otázka správy ServiceAccounts přesahuje rámec tohoto článku a doporučuji těm, kteří mají zájem, aby se podívali na . My se nyní podíváme podrobně na problematiku certifikátů X509.
Certifikáty pro uživatele (X.509)
Klasický způsob práce s certifikáty zahrnuje:
- generaci klíče:
mkdir -p ~/mynewuser/.certs/ openssl genrsa -out ~/mynewuser.key 2048 - generaci žádosti o certifikát:
openssl req -new -key ~/mynewuser.key -out ~/mynewuser.csr -subj "/CN=mynewuser/O=company" - zpracování žádosti o certifikát pomocí klíčů CA clusteru Kubernetes, získání certifikátu uživatele (pro získání certifikátu je nutné použít účet, který má přístup ke klíči certifikační autority clusteru Kubernetes, která je ve výchozím nastavení umístěna v
/etc/kubernetes/pki/ca.key):openssl x509 -req -in ~/mynewuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/mynewuser.crt -days 500 - vytvoření konfiguračního souboru:
- popis clusteru (uvedete adresu a umístění souboru certifikátu CA konkrétní instalace clusteru):
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.100.200:6443 - nebo — jak nedoporučená varianta — můžete nepoužít kořenový certifikát (pak kubectl nebude ověřovat správnost api-serveru clusteru):
kubectl config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://192.168.100.200:6443 - přidání uživatele do konfiguračního souboru:
kubectl config set-credentials mynewuser --client-certificate=.certs/mynewuser.crt --client-key=.certs/mynewuser.key - přidání kontextu:
kubectl config set-context mynewuser-context --cluster=kubernetes --namespace=target-namespace --user=mynewuser - nastavení výchozího kontextu:
kubectl config use-context mynewuser-context
- popis clusteru (uvedete adresu a umístění souboru certifikátu CA konkrétní instalace clusteru):
Po výše uvedených manipulacích bude v souboru .kube/config vytvořen konfigurační soubor následující podoby:
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.keyPro usnadnění přenosu konfiguračního souboru mezi účty a servery je užitečné upravit hodnoty následujících klíčů:
-
certificate-authority -
client-certificate -
client-key
K tomu je možné soubory uvedené v nich zakódovat pomocí base64 a zařadit je do konfiguračního souboru, přidáním k názvům klíčů příponu -data, tedy získáním certificate-authority-data atd.
Certifikáty s kubeadm
S vydáním Práce se certifikáty se díky alfa verzi její podpory v . Například takto nyní může vypadat generování konfiguračního souboru se soukromými klíči uživatele:
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200 NB: Požadovaná advertise address může být zkontrolována v konfiguraci api-serveru, který je ve výchozím nastavení umístěn v /etc/kubernetes/manifests/kube-apiserver.yaml.
Výsledná konfigurace bude vytištěna do stdout. Je třeba ji uložit do ~/.kube/config uživatelského účtu nebo do souboru uvedeného v proměnné prostředí KUBECONFIG.
Ponořit se hlouběji
Pro ty, kteří chtějí hlouběji prozkoumat uvedené otázky:
- o práci se certifikáty v oficiální dokumentaci Kubernetes;
- , ve kterém je otázka certifikátů pokryta praktickou stránkou.
- o autentizaci v Kubernetes.
Autentizace
Autorizovaný účet ve výchozím nastavení nemá oprávnění k akcím v klastru. Pro udělení oprávnění byl v Kubernetes implementován mechanismus autorizace.
Až do verze 1.6 se v Kubernetes používal typ autorizace nazývaný ABAC (Attribute-based access control). Podrobnosti o něm naleznete v . V současnosti je tento přístup považován za zastaralý (legacy), avšak stále jej můžete používat současně s jinými typy autorizace.
Aktuální (a flexibilnější) způsob rozdělení přístupových práv do klastru se nazývá RBAC (). Byl vyhlášen stabilním od verze . RBAC implementuje model práv, kde je vše, co není explicitně povoleno, zakázáno.
Pro aktivaci RBAC, je nutné spustit Kubernetes api-server s parametrem --authorization-mode=RBAC. Parametry se nastavují v manifestu konfigurace api-serveru, který je ve výchozím nastavení umístěn na cestě /etc/kubernetes/manifests/kube-apiserver.yaml, v sekci command. Nicméně, ve výchozím nastavení je RBAC již aktivován, takže se tím pravděpodobně nemusíte zabývat: můžete se o tom přesvědčit podle hodnoty authorization-mode (v již zmíněném kube-apiserver.yaml). Mimochodem, mezi jeho hodnotami se mohou objevovat i jiné typy autorizace (node, webhook, always allow), ale jejich zkoumání necháme mimo rámec tohoto materiálu.
Mimochodem, již jsme publikovali dostatečně podrobný popis principů a zvláštností práce s RBAC, takže dále se omezím na stručné shrnutí základů a příkladů.
Pro řízení přístupu v Kubernetes prostřednictvím RBAC se používají následující entity API:
-
RoleaClusterRole— role, které slouží k popisu oprávnění: -
Roleumožňuje popsat práva v rámci namespace; -
ClusterRole— v rámci clusteru, včetně cluster-specifických objektů, jako jsou uzly, non-resources urls (tj. nesouvisejících s Kubernetes zdroji — například,/version,/logs,/api*); -
RoleBindingaClusterRoleBinding— slouží k propojeníRoleaClusterRoles uživatelským účtem, skupinou uživatelů nebo ServiceAccount.
Entity Role a RoleBinding jsou omezeny na namespace, tj. musí se nacházet v rámci jednoho prostoru jmen. RoleBinding však může odkazovat na ClusterRole, což umožňuje vytvořit sadu typových oprávnění a spravovat přístup prostřednictvím nich.
Role popisují oprávnění pomocí sad pravidel, které obsahují:
- API skupiny — viz k apiGroups a příkazu
kubectl api-resources; - zdroje (resources:
pod,namespace,deploymentatd.); - slovesa (verbs:
set,updateatd.). - jména zdrojů (
resourceNames) — pro případ, kdy je potřeba poskytnout přístup k určitému zdroji, nikoli ke všem zdrojům tohoto typu.
Podrobnější rozbor autorizace v Kubernetes lze nalézt na stránce . Místo toho (přesněji — jako doplněk k tomu) uvedu příklady, které ilustrují její fungování.
Příklady entit RBAC
Jednoduchá Role, umožňující získat seznam a stav podů a sledovat je v prostoru jmen 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"] Příklad ClusterRole, což umožňuje získat seznam a stav podů a sledovat je v celém clusteru:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# sekce "namespace" není, protože ClusterRole pokrývá celý cluster
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] Příklad RoleBinding, což umožňuje uživateli mynewuser "číst" podí v prostoru jmen my-namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: target-namespace
subjects:
- kind: User
name: mynewuser # jméno uživatele je citlivé na velikost písmen!
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # zde by mělo být “Role” nebo “ClusterRole”
name: pod-reader # jméno Role, které se nachází ve stejném namespace,
# nebo jméno ClusterRole, jejíž užití
# chceme uživateli povolit
apiGroup: rbac.authorization.k8s.ioAudit událostí
Schématicky lze architekturu Kubernetes představit následovně:

Klíčová komponenta Kubernetes, odpovědná za zpracování požadavků, je api-server. Všechny operace s klastrem probíhají přes něj. Více o těchto vnitřních mechanismech se můžete dočíst v článku „».
Auditing systému je zajímavá funkce v Kubernetes, která je ve výchozím nastavení vypnuta. Umožňuje logovat všechny požadavky na API Kubernetes. Jak asi tušíte, přes toto API se provádějí všechny akce související s kontrolou a změnou stavu klastru. Dobré popisy jejích možností lze (jak obvykle) najít v K8s. Dále se pokusím téma vysvětlit jednodušším jazykem.
Takže, abychom zapli audit, musíme předat kontejneru v api-serveru tři povinné parametry, o kterých se více dozvíte níže:
-
--audit-policy-file=/etc/kubernetes/policies/audit-policy.yaml -
--audit-log-path=/var/log/kube-audit/audit.log -
--audit-log-format=json
Kromě těchto tří nezbytných parametrů existuje mnoho dalších nastavení týkajících se auditu: od rotace logů po popisy webhooků. Příklad parametrů rotace logů:
-
--audit-log-maxbackup=10 -
--audit-log-maxsize=100 -
--audit-log-maxage=7
Ale nebudeme se na ně podrobně zastavovat — všechny detaily lze nalézt v .
Jak již bylo zmíněno, všechny parametry se nastavují v manifestu konfigurace api-serveru (ve výchozím nastavení /etc/kubernetes/manifests/kube-apiserver.yaml), v sekci command. Vraťme se k třem povinným parametrům a rozeberme je:
-
audit-policy-file— cesta k YAML souboru s popisem auditní politiky. K jeho obsahu se ještě vrátíme, ale prozatím podotknu, že soubor musí být přístupný procesu api-serveru. Proto je třeba jej namontovat do kontejneru, k čemuž lze přidat následující kód do příslušných sekcí konfigurace:volumeMounts: - mountPath: /etc/kubernetes/policies name: policies readOnly: true volumes: - hostPath: path: /etc/kubernetes/policies type: DirectoryOrCreate name: policies -
audit-log-path— cesta k souboru s logy. Cesta musí být také přístupná procesu api-serveru, proto ji stejně popisujeme jako namontování:volumeMounts: - mountPath: /var/log/kube-audit name: logs readOnly: false volumes: - hostPath: path: /var/log/kube-audit type: DirectoryOrCreate name: logs -
audit-log-format— formát logu auditu. Ve výchozím nastavení je tojson, ale k dispozici je také zastaralý textový formát (legacy).
Auditní politika
Teď k zmiňovanému souboru s popisem logovací politiky. První pojem audit policy — to je úroveň, logování. Ty mohou být následující:
-
None— neprovádět logování; -
Metadata— logovat metadata požadavku: uživatel, čas požadavku, cílový zdroj (pod, namespace atd.), typ akce (verb) atd.; -
Request— logovat metadata a tělo požadavku; -
RequestResponse— logovat metadata, tělo požadavku a tělo odpovědi.
Poslední dvě úrovně (Request a RequestResponse) nelogují požadavky, které se netýkají zdrojů (žádosti na tzv. non-resources urls).
Také všechny požadavky procházejí několika fázemi:
-
RequestReceived— fáze, kdy byl požadavek přijat zpracovatelem a ještě nebyl předán dále do řetězce zpracovatelů; -
ResponseStarted— hlavičky odpovědi byly odeslány, ale před odesláním těla odpovědi. Generováno pro dlouhé požadavky (například,watch); -
ResponseComplete— tělo odpovědi bylo odesláno, více informací již nebude odesláno; -
Panic— události jsou generovány, když dojde k nečekané situaci.
Pro vynechání jakýchkoli fází lze použít omitStages.
V souboru politiky můžeme popsat několik sekcí s různými úrovněmi logování. Použije se první vhodné pravidlo nalezené v popisu policy.
Démon kubelet sleduje změny manifestu s konfigurací api-serveru a při jejich zjištění restartuje kontejner s api-serverem. Ale je tu důležitý detail: změny v souboru policy budou ignorovány. Po provedení změn v souboru policy bude nutné api-server ručně restartovat. Protože api-server běží jako , příkaz kubectl delete nezpůsobí jeho restart. Bude nutné ručně provést docker stop na kube-masterech, kde byla změněna auditní politika:
docker stop $(docker ps | grep k8s_kube-apiserver | awk '{print $1}')Při zapnutí auditu je důležité mít na paměti, že zvyšuje zátěž na kube-apiserveru. Zejména se zvyšuje spotřeba paměti pro uložení kontextu požadavků. Záznam do logu začíná až po odeslání hlavičky odpovědi. Také zátěž závisí na konfiguraci auditní politiky.
Příklady politik
Prozkoumejme strukturu souborů policy na příkladech.
Tady je jednoduchý soubor policy, který loguje všechno na úrovni Metadata:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata V policy lze uvést seznam uživatelů (Uživatelé a ServiceAccounts) a skupin uživatelů. Například, takto budeme ignorovat systémové uživatele, ale logovat vše ostatní na úrovni. 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: RequestExistuje také možnost popsat cílové:
- jmenné prostory (
jmenné prostory); - slovesa (verbs:
získat,update,odstranita další); - zdroje (resources, konkrétně:
pod,configmapsa podobně) a skupiny zdrojů (apiGroups).
Všimněte si! Zdroje a skupiny zdrojů (API skupiny, tj. apiGroups), a také jejich verze nainstalované v klastru, lze získat pomocí příkazů:
kubectl api-resources
kubectl api-versionsNásledující politiky auditů jsou uvedeny jako příklad nejlepších praktik v :
apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Nezaznamenávat fázi RequestReceived
omitStages:
- "RequestReceived"
rules:
# Nezaznamenávat události považované za bezvýznamné a nebezpečné:
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # toto je api skupina s prázdným jménem, které se týká
# základních zdrojů Kubernetes, nazývaných "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"]
# Nezaznamenávat přístupy k read-only URL:
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Nezaznamenávat zprávy týkající se typu zdrojů "události":
- level: None
resources:
- group: "" # core
resources: ["events"]
# Zdroje typu Secret, ConfigMap a TokenReview mohou obsahovat tajné údaje,
# proto zaznamenáváme pouze metadata související s těmito požadavky
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
# Akce typu get, list a watch mohou být náročné na zdroje; nezaznamenáváme je
- 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"
# Výchozí úroveň protokolování pro standardní API zdroje
- 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"
# Výchozí úroveň protokolování pro všechny ostatní požadavky
- level: MetadataDalší dobrý příklad audit policy — .
Pro rychlou reakci na události auditu je možnost popis webhooku. Toto téma je podrobněji vysvětleno v , nechám to mimo rámec tohoto článku.
Závěry
Článek poskytuje přehled mechanismů základního zabezpečení v clusterech Kubernetes, které umožňují vytvářet personalizované uživatelské účty, rozdělovat jejich práva a také registrovat jejich činnosti. Doufám, že to bude užitečné pro ty, kteří se s těmito otázkami setkali teoreticky nebo již v praxi. Doporučuji se také podívat na seznam dalších materiálů na téma zabezpečení v Kubernetes, který je uveden v "P.S.", – možná mezi nimi najdete potřebné podrobnosti o problémech, které vás zajímají.
P.S.
Přečtěte si také náš blog:
- «»;
- «»;
- «»;
- «»;
- «».
Zdroj: habr.com
