diff --git a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md index b9311e821..5fae46453 100644 --- a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md +++ b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md @@ -2,11 +2,11 @@ {{#include ../../banners/hacktricks-training.md}} -Es gibt **verschiedene Möglichkeiten, services** in Kubernetes offenzulegen, sodass sowohl **interne** Endpunkte als auch **externe** Endpunkte darauf zugreifen können. Diese Kubernetes-Konfiguration ist ziemlich kritisch, da der Administrator **Angreifern Zugriff auf services geben könnte, auf die sie keinen Zugriff haben sollten**. +Es gibt **verschiedene Möglichkeiten, Services** in Kubernetes zu exponieren, sodass sowohl **interne** Endpoints als auch **externe** Endpoints darauf zugreifen können. Diese Kubernetes-Konfiguration ist ziemlich kritisch, da der Administrator **Angreifern Zugriff auf Services geben könnte, auf die sie keinen Zugriff haben sollten**. ### Automatic Enumeration -Bevor du damit beginnst, die Möglichkeiten zu enumerieren, die K8s bietet, um services öffentlich offenzulegen, beachte: Wenn du namespaces, services und ingresses auflisten kannst, kannst du alles finden, was öffentlich exposed ist mit: +Bevor du damit beginnst, die Möglichkeiten zu enumerieren, die K8s bietet, um Services der Öffentlichkeit zugänglich zu machen, beachte, dass du, wenn du Namespaces, Services und ingresses auflisten kannst, alles finden kannst, was öffentlich exponiert ist mit: ```bash kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do echo "Namespace: $ns" @@ -20,17 +20,17 @@ done | grep -v "ClusterIP" ``` ### ClusterIP -Ein **ClusterIP**-**service** ist der **Standard**-Kubernetes-**service**. Er stellt dir einen **service innerhalb** deines Clusters zur Verfügung, auf den andere Apps innerhalb deines Clusters zugreifen können. Es gibt **keinen externen Zugriff**. +Ein **ClusterIP**-Service ist der **Standard**-Kubernetes-**service**. Er bietet dir einen **service inside** deinem Cluster, auf den andere Apps innerhalb deines Clusters zugreifen können. Es gibt **keinen externen Zugriff**. Allerdings kann darauf über den Kubernetes Proxy zugegriffen werden: ```bash kubectl proxy --port=8080 ``` -Jetzt kannst du durch die Kubernetes API navigieren, um Services mit diesem Schema zu erreichen: +Jetzt kannst du durch die Kubernetes API navigieren, um auf Services mit diesem Schema zuzugreifen: `http://localhost:8080/api/v1/proxy/namespaces//services/:/` -Zum Beispiel kannst du die folgende URL verwenden: +Zum Beispiel könntest du die folgende URL verwenden: `http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/` @@ -50,15 +50,15 @@ port: 80 targetPort: 80 protocol: TCP ``` -_Diese Methode erfordert, dass du `kubectl` als ein **authentifizierter Benutzer** ausführst._ +_Diese Methode erfordert, dass du `kubectl` als **authentifizierter Benutzer** ausführst._ -Liste alle ClusterIPs: +Liste alle ClusterIPs auf: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP ``` ### NodePort -Wenn **NodePort** verwendet wird, wird ein bestimmter Port auf allen Nodes (den Virtual Machines) verfügbar gemacht. **Traffic**, der an diesen spezifischen Port gesendet wird, wird dann systematisch **an den service weitergeleitet**. Typischerweise wird diese Methode wegen ihrer Nachteile nicht empfohlen. +Wenn **NodePort** verwendet wird, wird ein festgelegter Port auf allen Nodes (den Virtual Machines) verfügbar gemacht. **Traffic**, der an diesen spezifischen Port gesendet wird, wird dann systematisch **an den service weitergeleitet**. Typischerweise wird diese Methode aufgrund ihrer Nachteile nicht empfohlen. Alle NodePorts auflisten: ```bash @@ -81,13 +81,24 @@ targetPort: 80 nodePort: 30036 protocol: TCP ``` -Wenn du **nodePort** in der yaml **nicht angibst** (das ist der Port, der geöffnet wird), wird ein Port im **Bereich 30000–32767 verwendet**. +Wenn du **nodePort** in der yaml **nicht angibst** (es ist der Port, der geöffnet wird), wird ein Port im **Bereich 30000–32767 verwendet**. + +Beim Prüfen von NodePort- oder LoadBalancer-Services solltest du auch die traffic-policy-Felder untersuchen, weil sie ändern, welche Nodes und Backends von einer bestimmten Quelle aus nutzbar sind: +```bash +kubectl get services --all-namespaces \ +-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,ETP:.spec.externalTrafficPolicy,ITP:.spec.internalTrafficPolicy,AFFINITY:.spec.sessionAffinity,DIST:.spec.trafficDistribution,NODEPORTS:.spec.ports[*].nodePort' +``` +- `externalTrafficPolicy: Local` bewahrt die ursprüngliche Client-Source-IP für NodePort/LoadBalancer-Traffic und verhindert das Weiterleiten zu Endpoints auf anderen Nodes. Ein Node ohne lokalen ready Endpoint kann den Traffic verwerfen, selbst wenn das Service anderswo Endpoints hat. +- `externalTrafficPolicy: Cluster` ist der Standard und kann über jeden Node weiterleiten, aber Backend-Logs sehen möglicherweise Node-IPs statt der echten externen Client-IP. +- `internalTrafficPolicy: Local` beschränkt Service-Traffic im Cluster auf Endpoints, die lokal zum Quell-Node sind. Das ist locality routing, keine authorization boundary. +- `sessionAffinity: ClientIP` kann dafür sorgen, dass wiederholte Tests von einem Client immer das gleiche Backend treffen und so andere ready Endpoints bei manuellen Checks verborgen bleiben. +- `trafficDistribution` und EndpointSlice topology hints können auf neueren Clustern Endpoints in derselben Zone oder auf demselben Node bevorzugen; behandle sie als routing preferences und nicht als harte security policy. ### LoadBalancer -Macht den Service extern **über den Load Balancer des Cloud-Anbieters** zugänglich. Auf GKE wird dadurch ein [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) gestartet, der dir eine einzelne IP-Adresse gibt, die den gesamten Traffic an deinen Service weiterleitet. In AWS wird ein Load Balancer gestartet. +Stellt das Service extern bereit **unter Verwendung eines cloud provider's load balancer**. Auf GKE startet dies einen [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/), der dir eine einzelne IP-Adresse gibt, die den gesamten Traffic an dein service weiterleitet. In AWS wird ein Load Balancer gestartet. -Du musst für jeden exponierten Service einen LoadBalancer bezahlen, was teuer sein kann. +Du musst für einen LoadBalancer pro exposed service bezahlen, was teuer sein kann. Alle LoadBalancers auflisten: ```bash @@ -96,15 +107,15 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam ### External IPs > [!TIP] -> External IPs werden von Services des Typs Load Balancers exponiert und werden im Allgemeinen verwendet, wenn ein externer Cloud Provider Load Balancer genutzt wird. +> External IPs werden von Services vom Typ Load Balancers exposed und werden generell verwendet, wenn ein externer Cloud Provider Load Balancer genutzt wird. > -> Um sie zu finden, prüfe Load Balancers mit Werten im Feld `EXTERNAL-IP`. +> Um sie zu finden, prüfe Load Balancer mit Werten im Feld `EXTERNAL-IP`. -Traffic, der mit der **external IP** (als **destination IP**) auf dem Service port in den cluster gelangt, wird **an einen der Service endpoints weitergeleitet**. `externalIPs` werden nicht von Kubernetes verwaltet und liegen in der Verantwortung des cluster administrator. +Traffic, der mit der **external IP** (als **destination IP**) in den cluster ingresses, wird am Service-Port **zu einem der Service-endpoints gerouted**. `externalIPs` werden nicht von Kubernetes verwaltet und liegen in der Verantwortung des cluster administrators. -`externalIPs` ist ein sensibles route-control Feld, weil ein user, der es setzen kann, Traffic für eine IP-Adresse beanspruchen könnte, die der Service owner nicht kontrollieren sollte, wenn das umgebende network diese IP zum cluster routet. Kubernetes kündigte die Deprecation und geplante Entfernung von Service `externalIPs` in v1.36 an, also bevorzuge nach Möglichkeit controller-owned exposure mechanisms wie LoadBalancer integrations oder Gateway API und beschränke/erlaube dieses Feld sorgfältig, solange es noch existiert. +`externalIPs` ist ein sensibles route-control-Feld, weil ein user, der es setzen kann, Traffic für eine IP-Adresse beanspruchen könnte, die der Service owner nicht kontrollieren sollte, wenn das umgebende network diese IP zum cluster routed. Kubernetes hat die Deprecation und geplante Entfernung von Service `externalIPs` in v1.36 angekündigt, daher sollten nach Möglichkeit controller-owned exposure mechanisms wie LoadBalancer integrations oder Gateway API bevorzugt werden, und dieses Feld sollte sorgfältig eingeschränkt/admitted werden, solange es noch existiert. -In der Service spec kann `externalIPs` zusammen mit jedem der `ServiceTypes` angegeben werden. Im folgenden example kann auf "`my-service`" von clients unter "`80.11.12.10:80`" zugegriffen werden (`externalIP:port`) +In der Service spec kann `externalIPs` zusammen mit jedem der `ServiceTypes` angegeben werden. Im folgenden Beispiel kann "`my-service`" von clients unter "`80.11.12.10:80`" (`externalIP:port`) erreicht werden. ```yaml apiVersion: v1 kind: Service @@ -123,9 +134,9 @@ externalIPs: ``` ### ExternalName -[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services vom Typ ExternalName **mappen einen Service auf einen DNS-Namen**, nicht auf einen typischen selector wie `my-service` oder `cassandra`. Diese Services legst du mit dem Parameter `spec.externalName` fest. +[**Aus den docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services vom Typ ExternalName **ordnen einen Service einem DNS-Namen zu**, nicht einem typischen selector wie `my-service` oder `cassandra`. Diese Services gibst du mit dem `spec.externalName`-Parameter an. -Diese Service-Definition mappt zum Beispiel den `my-service` Service im `prod` Namespace auf `my.database.example.com`: +Diese Service-Definition ordnet zum Beispiel den `my-service` Service im `prod`-Namespace `my.database.example.com` zu: ```yaml apiVersion: v1 kind: Service @@ -136,7 +147,7 @@ spec: type: ExternalName externalName: my.database.example.com ``` -Wenn der Host `my-service.prod.svc.cluster.local` abgefragt wird, gibt der cluster DNS Service einen `CNAME`-Record mit dem Wert `my.database.example.com` zurück. Der Zugriff auf `my-service` funktioniert auf die gleiche Weise wie bei anderen Services, mit dem entscheidenden Unterschied, dass **die Weiterleitung auf DNS-Ebene** statt über Proxying oder Forwarding erfolgt. +Beim Nachschlagen des Hosts `my-service.prod.svc.cluster.local` gibt der Cluster-DNS-Service einen `CNAME`-Record mit dem Wert `my.database.example.com` zurück. Der Zugriff auf `my-service` funktioniert auf die gleiche Weise wie bei anderen Services, aber mit dem entscheidenden Unterschied, dass **die Weiterleitung auf DNS-Ebene** statt über Proxying oder Forwarding erfolgt. List all ExternalNames: ```bash @@ -144,24 +155,24 @@ kubectl get services --all-namespaces | grep ExternalName ``` ### EndpointSlices -EndpointSlices zeigen die konkreten Backend-Adressen und Ports, zu denen ein Service aktuell routet. Sie sind besonders nützlich, wenn ein Service keinen selector hat, wenn Labels den Traffic-Pfad nicht erklären oder wenn nur einige Backends bereit sind. +EndpointSlices zeigen die konkreten Backend-Adressen und Ports, an die ein Service aktuell weiterleitet. Sie sind besonders nützlich, wenn ein Service keinen selector hat, wenn Labels den Traffic-Pfad nicht erklären oder wenn nur einige Backends bereit sind. -Liste die mit Services verbundenen EndpointSlices auf: +Liste die mit Services verbundenen EndpointSlices: ```bash kubectl get endpointslices --all-namespaces kubectl get endpointslice -n -l kubernetes.io/service-name= -o yaml kubectl get endpointslice -n -l kubernetes.io/service-name= \ -o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port' ``` -Bei der Überprüfung der Exposition vergleiche den Service-Selector mit dem EndpointSlice `targetRef`, den Endpoint-Adressen, Readiness-Conditions und Ports. Ein selectorloser Service kann mit manuell verwalteten EndpointSlices gekoppelt werden und Traffic an Nicht-Pod- oder unerwartete Ziele leiten. +Beim Prüfen der Exposition vergleiche den Service selector mit dem EndpointSlice `targetRef`, den Endpoint-Adressen, Readiness-Bedingungen und Ports. Ein selectorless Service kann mit manuell verwalteten EndpointSlices kombiniert werden und Traffic an Nicht-Pod- oder unerwartete Ziele routen. ### Ingress -Im Gegensatz zu allen obigen Beispielen ist **Ingress KEIN Typ von Service**. Stattdessen sitzt es **vor mehreren Services und fungiert als „smart router“** oder Einstiegspunkt in deinen Cluster. +Im Gegensatz zu allen obigen Beispielen ist **Ingress KEIN Typ von service**. Stattdessen sitzt es **vor mehreren services und fungiert als „smart router“** oder Entry-Point in deinen cluster. -Mit einem Ingress kannst du viele verschiedene Dinge tun, und es gibt **viele Arten von Ingress-Controllern mit unterschiedlichen Fähigkeiten**. +Du kannst mit einem Ingress viele verschiedene Dinge tun, und es gibt **viele Typen von Ingress controllers, die unterschiedliche Fähigkeiten haben**. -Der standardmäßige GKE Ingress-Controller erstellt für dich einen [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/). Damit kannst du sowohl pfadbasiertes als auch subdomain-basiertes Routing zu Backend-Services machen. Zum Beispiel kannst du alles auf foo.yourdomain.com an den foo Service senden, und alles unter dem Pfad yourdomain.com/bar/ an den bar Service. +Der Standard-GKE-Ingress controller startet für dich einen [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/). Damit kannst du sowohl pfadbasiertes als auch subdomain-basiertes Routing zu backend services durchführen. Zum Beispiel kannst du alles auf foo.yourdomain.com an den foo service senden und alles unter dem Pfad yourdomain.com/bar/ an den bar service. Das YAML für ein Ingress-Objekt auf GKE mit einem [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) könnte so aussehen: ```yaml @@ -197,19 +208,19 @@ name: bar port: number: 8080 ``` -Listet alle ingresses auf: +Liste alle Ingresses: ```bash kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' ``` -Obwohl es in diesem Fall besser ist, die Infos einzeln nacheinander zu holen, um sie besser lesen zu können: +Obwohl es in diesem Fall besser ist, die Infos einzeln nacheinander zu erhalten, um sie besser lesen zu können: ```bash kubectl get ingresses --all-namespaces -o=yaml ``` ### Gateway API -Gateway API ist die neuere Kubernetes API zum Exponieren von Services. Sie trennt von der Infrastruktur verwaltete Gateway-Objekte von von Anwendungen verwalteten Route-Objekten wie HTTPRoute. Das ist nützlich für Delegation, bedeutet aber auch, dass Exposure über Namespaces hinweg aufgeteilt sein kann. +Gateway API ist die neuere Kubernetes API zum Exponieren von Services. Sie trennt infrastrukturell verwaltete Gateway-Objekte von anwendungsseitig verwalteten Route-Objekten wie HTTPRoute. Das ist nützlich für Delegation, bedeutet aber auch, dass Exposure über mehrere Namespaces verteilt sein kann. -Liste Gateway API Exposure-Objekte: +Liste der Gateway API-Expositionsobjekte: ```bash kubectl get gatewayclasses kubectl get gateways --all-namespaces @@ -217,13 +228,16 @@ kubectl get httproutes --all-namespaces kubectl get gateway -n -o yaml kubectl get httproute -n -o yaml ``` -Prüfe Gateway listeners, erlaubte Route-Namespaces, Route `parentRefs`, hostnames, filters, backend references und Statusbedingungen wie etwa, ob die Route accepted wurde. Eine Route, die von einem shared Gateway accepted wurde, kann ein backend exposen, auch wenn kein legacy Ingress-Objekt existiert. +Prüfe Gateway-Listener, erlaubte Route-Namespaces, Route-`parentRefs`, Hostnames, filters, backend references und Statusbedingungen wie etwa, ob die Route akzeptiert wurde. Eine Route, die von einem gemeinsamen Gateway akzeptiert wird, kann ein backend exponieren, selbst wenn kein legacy Ingress-Objekt existiert. ### References - [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0) - [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/) - [https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/](https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/) +- [https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) +- [https://kubernetes.io/docs/tutorials/services/source-ip/](https://kubernetes.io/docs/tutorials/services/source-ip/) +- [https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/) - [https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) - [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/) diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md b/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md index 85708d480..945130160 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md @@ -2,53 +2,55 @@ {{#include ../../banners/hacktricks-training.md}} -**Der ursprüngliche Autor dieser Seite ist** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(lies seinen ursprünglichen Beitrag** [**hier**](https://sickrov.github.io)**)** +**Der ursprüngliche Autor dieser Seite ist** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(lies seinen Originalbeitrag** [**hier**](https://sickrov.github.io)**)** ## Architecture & Basics ### Was macht Kubernetes? -- Ermöglicht das Ausführen von Container/s in einer container engine. -- Schedule ermöglicht es Containern, mission efficient zu sein. +- Erlaubt das Ausführen von Container/s in einer container engine. +- Das Schedule erlaubt es, Container ressourceneffizient auszuführen. - Hält Container am Leben. -- Ermöglicht Container-Kommunikation. -- Ermöglicht deployment techniques. -- Verwaltet Volumes von Informationen. +- Erlaubt Container communications. +- Erlaubt deployment techniques. +- Handhabt volumes of information. ### Architecture ![Kubernetes architecture diagram showing control plane components, API server, kubelet, kube-proxy, pods, and worker nodes](https://sickrov.github.io/media/Screenshot-68.jpg) -- **Node**: Betriebssystem mit pod oder pods. -- **Pod**: Wrapper um einen container oder mehrere containers mit. Ein pod sollte nur eine Anwendung enthalten (daher läuft ein pod normalerweise nur 1 container). Der pod ist die Art und Weise, wie kubernetes die laufende container technology abstrahiert. -- **Service**: Jedes pod hat 1 interne **IP address** aus dem internen Bereich des nodes. Es kann jedoch auch über einen service exponiert werden. Der **service hat ebenfalls eine IP address** und sein Ziel ist es, die Kommunikation zwischen pods aufrechtzuerhalten, sodass, wenn einer ausfällt, der **neue Ersatz** (mit einer anderen internen IP) **unter derselben IP des services zugänglich** exponiert wird. Er kann als intern oder extern konfiguriert werden. Der service fungiert außerdem als **load balancer, wenn 2 pods** mit demselben service verbunden sind.\ -Wenn ein **service** **erstellt** wurde, kannst du die Endpoints jedes services mit `kubectl get endpoints` finden -- **Kubelet**: Primärer node agent. Die Komponente, die die Kommunikation zwischen node und kubectl herstellt, und die nur pods ausführen kann (über den API server). Das kubelet verwaltet keine containers, die nicht von Kubernetes erstellt wurden. -- **Kube-proxy**: ist der Dienst, der für die Kommunikation (services) zwischen dem apiserver und dem node zuständig ist. Die Basis ist ein IPtables für nodes. Erfahrene Nutzer könnten andere kube-proxies von anderen Anbietern installieren. -- **Sidecar container**: Sidecar containers sind die containers, die zusammen mit dem main container im pod laufen sollen. Dieses sidecar pattern erweitert und verbessert die Funktionalität bestehender containers, ohne sie zu verändern. Heute wissen wir, dass wir container technology nutzen, um alle Abhängigkeiten für die Anwendung zu verpacken, damit sie überall laufen kann. Ein container macht nur eine Sache und macht diese Sache sehr gut. +- **Node**: operating system mit pod oder pods. +- **Pod**: Wrapper um einen container oder mehrere containers. Ein pod sollte nur eine application enthalten (also läuft ein pod normalerweise nur 1 container). Der pod ist die Art und Weise, wie kubernetes die laufende container technology abstrahiert. +- **Service**: Jeder pod hat 1 interne **IP address** aus dem internen Bereich des nodes. Er kann jedoch auch über einen service exponiert werden. Der **service hat ebenfalls eine IP address** und sein Ziel ist es, die communication zwischen pods aufrechtzuerhalten, sodass, wenn einer ausfällt, der **neue Ersatz** (mit einer anderen internen IP) **über die gleiche IP des services erreichbar** ist. Er kann als intern oder extern konfiguriert werden. Der service wirkt außerdem als **load balancer, wenn 2 pods mit demselben service verbunden sind**.\ +Wenn ein **service** **erstellt** wurde, kannst du die endpoints jedes service mit `kubectl get endpoints` finden +- **Kubelet**: Primärer node agent. Die Komponente, die die communication zwischen node und kubectl herstellt, und nur pods ausführen kann (über API server). Das kubelet verwaltet keine container, die nicht von Kubernetes erstellt wurden. +- **Kube-proxy**: ist der service, der für die communications (services) zwischen dem apiserver und dem node zuständig ist. Die Basis ist ein IPtables für nodes. Erfahrene Benutzer könnten andere kube-proxies von anderen Anbietern installieren. +- **Sidecar container**: Sidecar containers sind die containers, die zusammen mit dem Hauptcontainer im pod laufen sollen. Dieses Sidecar-Muster erweitert und verbessert die Funktionalität vorhandener containers, ohne sie zu verändern. Heutzutage wissen wir, dass wir container technology verwenden, um alle Abhängigkeiten so zu verpacken, dass die application überall laufen kann. Ein container tut nur eine Sache und tut diese Sache sehr gut. - **Master process:** -- **Api Server:** Ist der Weg, über den die Benutzer und die pods mit dem master process kommunizieren. Nur authentifizierte requests sollten erlaubt sein. -- **Scheduler**: Scheduling bedeutet sicherzustellen, dass Pods den Nodes zugewiesen werden, damit Kubelet sie ausführen kann. Er ist intelligent genug zu entscheiden, welcher node mehr verfügbare Ressourcen hat, und weist ihm den neuen pod zu. Beachte, dass der scheduler keine neuen pods startet, er kommuniziert nur mit dem Kubelet process, der innerhalb des nodes läuft und den neuen pod startet. -- **Kube Controller manager**: Er prüft Ressourcen wie replica sets oder deployments, um z. B. zu kontrollieren, ob die richtige Anzahl an pods oder nodes läuft. Falls ein pod fehlt, kommuniziert er mit dem scheduler, um einen neuen zu starten. Er kontrolliert replication, tokens und account services für die API. -- **etcd**: Data storage, persistent, consistent und distributed. Ist Kubernetes’ Datenbank und der key-value storage, in dem der vollständige Zustand der clusters gespeichert wird (jede Änderung wird hier protokolliert). Komponenten wie der Scheduler oder der Controller manager hängen von diesen date ab, um zu wissen, welche Änderungen aufgetreten sind (verfügbare resourced der nodes, Anzahl laufender pods...) -- **Cloud controller manager**: Ist der spezielle controller für flow controls und applications, d. h.: wenn du clusters in AWS oder OpenStack hast. +- **Api Server:** Ist der Weg, über den die Benutzer und die pods mit dem Master-Prozess kommunizieren. Nur authentifizierte requests sollten erlaubt sein. +- **Scheduler**: Scheduling bedeutet sicherzustellen, dass Pods Nodes zugewiesen werden, damit Kubelet sie ausführen kann. Er hat genug Intelligenz zu entscheiden, welcher node mehr verfügbare Ressourcen hat, um den neuen pod ihm zuzuweisen. Beachte, dass der scheduler keine neuen pods startet, sondern nur mit dem im node laufenden Kubelet-Prozess kommuniziert, der den neuen pod startet. +- **Kube Controller manager**: Er prüft Ressourcen wie replica sets oder deployments, um zu kontrollieren, ob beispielsweise die richtige Anzahl an pods oder nodes läuft. Falls ein pod fehlt, kommuniziert er mit dem scheduler, um einen neuen zu starten. Er steuert replication, tokens und account services zur API. +- **etcd**: Data storage, persistent, consistent und distributed. Ist die Datenbank von Kubernetes und der key-value storage, in dem der vollständige Zustand der clusters gespeichert wird (jede Änderung wird hier protokolliert). Komponenten wie der Scheduler oder der Controller manager hängen von diesen date ab, um zu wissen, welche Änderungen aufgetreten sind (verfügbare resourced der nodes, Anzahl der laufenden pods...) +- **Cloud controller manager**: Ist der spezifische controller für flow controls und applications, z. B.: wenn du clusters in AWS oder OpenStack hast. -Beachte, dass es mehrere nodes geben kann (die mehrere pods ausführen), und es können auch mehrere master processes existieren, deren Zugriff auf den Api server load balanced ist und deren etcd synchronisiert sind. +Beachte, dass da es mehrere nodes (mit mehreren pods) geben kann, es auch mehrere master processes geben kann, deren Zugriff auf den Api server load balanced und deren etcd synchronisiert ist. **Volumes:** -Wenn ein pod Daten erstellt, die nicht verloren gehen sollen, wenn der pod verschwindet, sollten sie in einem physischen Volume gespeichert werden. **Kubernetes erlaubt es, ein volume an einen pod anzuhängen, um die Daten persistent zu speichern**. Das volume kann sich auf dem lokalen Rechner oder in einem **remote storage** befinden. Wenn du pods auf verschiedenen physischen nodes betreibst, solltest du einen remote storage verwenden, damit alle pods darauf zugreifen können. +Wenn ein pod Daten erstellt, die nicht verloren gehen sollen, wenn der pod verschwindet, sollten sie in einem physischen volume gespeichert werden. **Kubernetes allow to attach a volume to a pod to persist the data**. Das volume kann auf der lokalen Maschine oder in einem **remote storage** liegen. Wenn du pods auf verschiedenen physischen nodes ausführst, solltest du remote storage verwenden, damit alle pods darauf zugreifen können. + +Kubernetes unterstützt in neueren Versionen auch **image volumes**. Ein `image` volume mountet ein OCI image oder artifact als **read-only** filesystem source innerhalb des Pod, mithilfe von Feldern wie `volumes[].image.reference` und `volumes[].image.pullPolicy`. Das kubelet zieht das artifact mit denselben credential sources wie bei container images, einschließlich node credentials, Pod `imagePullSecrets` und ServiceAccount `imagePullSecrets`. Bei einer security review solltest du image volumes als runtime inputs und supply-chain dependencies behandeln: Prüfe, ob die reference per digest fest gepinnt ist, welche Registry-Credentials es abrufen können, wo es gemountet wird und ob `subPath` das sichtbare Verzeichnis einschränkt. **Other configurations:** -- **ConfigMap**: Du kannst **URLs** konfigurieren, um services zu erreichen. Der pod erhält von hier Daten, um zu wissen, wie er mit den restlichen services (pods) kommunizieren soll. Beachte, dass dies nicht der empfohlene Ort ist, um credentials zu speichern! -- **Secret**: Dies ist der Ort, um **secret data** wie Passwörter, API keys... in B64 zu speichern. Der pod kann auf diese Daten zugreifen, um die erforderlichen credentials zu verwenden. -- **Deployments**: Hier werden die von kubernetes auszuführenden Komponenten angegeben. Ein Benutzer arbeitet normalerweise nicht direkt mit pods; pods werden in **ReplicaSets** abstrahiert (Anzahl identischer replizierter pods), die über deployments ausgeführt werden. Beachte, dass deployments für **stateless** Anwendungen gedacht sind. Die minimale Konfiguration für ein deployment ist der Name und das image, das ausgeführt werden soll. -- **StatefulSet**: Diese Komponente ist speziell für Anwendungen wie **databases** gedacht, die auf denselben storage zugreifen müssen. -- **Ingress**: Dies ist die Konfiguration, die verwendet wird, um **die Anwendung öffentlich mit einer URL zu exponieren**. Beachte, dass dies auch mit external services gemacht werden kann, aber dies ist der richtige Weg, um die Anwendung zu exponieren. -- Wenn du einen Ingress implementierst, musst du **Ingress Controllers** erstellen. Der Ingress Controller ist ein **pod**, der der endpoint ist, der die requests empfängt und prüft und sie an die services load balanced. der ingress controller wird die **request basierend auf den konfigurierten ingress rules senden**. Beachte, dass die ingress rules auf verschiedene paths oder sogar subdomains zu unterschiedlichen internen kubernetes services zeigen können. -- Eine bessere security practice wäre es, einen cloud load balancer oder einen proxy server als entrypoint zu verwenden, damit kein Teil des Kubernetes cluster exponiert ist. -- Wenn eine request empfangen wird, die zu keiner ingress rule passt, leitet der ingress controller sie an das "**Default backend**" weiter. Du kannst den ingress controller mit `describe` untersuchen, um die address dieses Parameters zu erhalten. +- **ConfigMap**: Du kannst **URLs** konfigurieren, um auf services zuzugreifen. Der pod erhält von hier Daten, um zu wissen, wie er mit dem Rest der services (pods) kommunizieren soll. Beachte, dass dies nicht der empfohlene Ort ist, um credentials zu speichern! +- **Secret**: Dies ist der Ort, um **secret data** wie Passwörter, API keys... in B64 codiert zu speichern. Der pod kann auf diese Daten zugreifen, um die erforderlichen credentials zu verwenden. +- **Deployments**: Hier werden die Komponenten angegeben, die von kubernetes ausgeführt werden sollen. Ein Benutzer arbeitet normalerweise nicht direkt mit pods; pods werden in **ReplicaSets** abstrahiert (Anzahl gleicher replizierter pods), die über deployments ausgeführt werden. Beachte, dass deployments für **stateless** applications gedacht sind. Die minimale Konfiguration für ein deployment ist der Name und das auszuführende image. +- **StatefulSet**: Diese Komponente ist speziell für applications wie **databases** gedacht, die auf **denselben storage zugreifen** müssen. +- **Ingress**: Dies ist die Konfiguration, die verwendet wird, um die application öffentlich mit einer **URL** zu exponieren. Beachte, dass dies auch mit external services möglich ist, aber dies ist der richtige Weg, um die application zu exponieren. +- Wenn du einen Ingress implementierst, musst du **Ingress Controllers** erstellen. Der Ingress Controller ist ein **pod**, der der endpoint ist, der die requests empfängt, prüft und sie per load balancing an die services weiterleitet. der ingress controller wird die **request basierend auf den konfigurierten ingress rules senden**. Beachte, dass die ingress rules auf verschiedene paths oder sogar subdomains zu unterschiedlichen internen kubernetes services zeigen können. +- Eine bessere security practice wäre, einen cloud load balancer oder einen proxy server als entrypoint zu verwenden, damit kein Teil des Kubernetes-Clusters exponiert ist. +- Wenn eine request empfangen wird, die keiner ingress rule entspricht, leitet der ingress controller sie an das "**Default backend**" weiter. Du kannst den ingress controller mit `describe` untersuchen, um die address dieses parameters zu erhalten. - `minikube addons enable ingress` ### PKI infrastructure - Certificate Authority CA: @@ -56,9 +58,9 @@ Wenn ein pod Daten erstellt, die nicht verloren gehen sollen, wenn der pod versc ![Kubernetes CA and PKI diagram showing API server certificates between clients, scheduler, controller manager, kubelet, and etcd](https://sickrov.github.io/media/Screenshot-66.jpg) - CA is the trusted root for all certificates inside the cluster. -- Allows components to validate to each other. -- All cluster certificates are signed by the CA. -- ETCd has its own certificate. +- Erlaubt es den Komponenten, sich gegenseitig zu validieren. +- Alle cluster certificates werden von der CA signiert. +- ETCd hat sein eigenes certificate. - types: - apiserver cert. - kubelet cert. @@ -68,7 +70,7 @@ Wenn ein pod Daten erstellt, die nicht verloren gehen sollen, wenn der pod versc ### Minikube -**Minikube** can be used to perform some **quick tests** on kubernetes without needing to deploy a whole kubernetes environment. It will run the **master and node processes in one machine**. Minikube will use virtualbox to run the node. See [**here how to install it**](https://minikube.sigs.k8s.io/docs/start/). +**Minikube** kann verwendet werden, um einige **quick tests** auf kubernetes durchzuführen, ohne eine komplette kubernetes-Umgebung deployen zu müssen. Es führt die **master and node processes auf einer Maschine** aus. Minikube verwendet virtualbox, um den node auszuführen. Siehe [**hier, wie man es installiert**](https://minikube.sigs.k8s.io/docs/start/). ``` $ minikube start 😄 minikube v1.19.0 on Ubuntu 20.04 @@ -105,7 +107,7 @@ $ minikube delete ``` ### Kubectl Basics -**`Kubectl`** ist das Command-Line-Tool für kubernetes-Cluster. Es kommuniziert mit dem Api server des Master-Prozesses, um Aktionen in kubernetes auszuführen oder Daten abzufragen. +**`Kubectl`** ist das Command-Line-Tool für kubernetes-Cluster. Es kommuniziert mit dem Api Server des Master-Prozesses, um Aktionen in kubernetes auszuführen oder Daten abzufragen. ```bash kubectl version #Get client and server version kubectl get pod @@ -138,7 +140,7 @@ kubectl apply -f deployment.yml ``` ### Minikube Dashboard -Das Dashboard ermöglicht es dir, einfacher zu sehen, was minikube ausführt, du findest die URL für den Zugriff darauf in: +Das Dashboard ermöglicht es dir, leichter zu sehen, was in minikube läuft. Du findest die URL, um darauf zuzugreifen, in: ``` minikube dashboard --url @@ -154,11 +156,11 @@ http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kube ### YAML configuration files examples Jede Konfigurationsdatei hat 3 Teile: **metadata**, **specification** (was gestartet werden muss), **status** (gewünschter Zustand).\ -Innerhalb der specification der deployment configuration file findest du die template, definiert mit einer neuen configuration structure, die das image festlegt, das ausgeführt werden soll: +Innerhalb der specification der deployment-Konfigurationsdatei findest du die template, definiert mit einer neuen configuration structure, die das image angibt, das ausgeführt werden soll: -**Beispiel für Deployment + Service, die in derselben configuration file deklariert sind (von** [**hier**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)** +**Example of Deployment + Service declared in the same configuration file (from** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)** -Da ein service normalerweise mit einem deployment verknüpft ist, ist es möglich, beide in derselben configuration file zu deklarieren (der in dieser config deklarierte service ist nur intern erreichbar): +Da ein service normalerweise mit einem deployment verbunden ist, ist es möglich, beides in derselben Konfigurationsdatei zu deklarieren (der in dieser config deklarierte service ist nur intern zugänglich): ```yaml apiVersion: apps/v1 kind: Deployment @@ -205,9 +207,9 @@ ports: port: 27017 targetPort: 27017 ``` -**Beispiel einer externen Service-Konfiguration** +**Beispiel für externe Service-Konfiguration** -Dieser Service wird extern erreichbar sein (prüfe die Attribute `nodePort` und `type: LoadBlancer`): +Dieser Service wird extern erreichbar sein (prüfe die `nodePort`- und `type: LoadBlancer`-Attribute): ```yaml --- apiVersion: v1 @@ -225,9 +227,9 @@ targetPort: 8081 nodePort: 30000 ``` > [!NOTE] -> Dies ist nützlich zum Testen, aber für die Produktion solltest du nur interne Services und einen Ingress haben, um die Anwendung zu exponieren. +> Dies ist nützlich für Tests, aber für die Produktion solltest du nur interne Services und einen Ingress haben, um die Anwendung zu exponieren. -**Example of Ingress config file** +**Beispiel für eine Ingress-Konfigurationsdatei** Dies wird die Anwendung unter `http://dashboard.com` exponieren. ```yaml @@ -247,7 +249,7 @@ servicePort: 80 ``` **Beispiel einer secrets config file** -Beachte, wie die passwords in B64 encoded sind (was nicht secure ist!) +Beachte, dass die password in B64 codiert sind (was nicht secure ist!) ```yaml apiVersion: v1 kind: Secret @@ -260,7 +262,7 @@ mongo-root-password: cGFzc3dvcmQ= ``` **Beispiel eines ConfigMap** -Ein **ConfigMap** ist die Konfiguration, die den pods gegeben wird, damit sie wissen, wie sie andere services finden und darauf zugreifen können. In diesem Fall weiß jeder pod, dass der Name `mongodb-service` die Adresse eines pods ist, mit dem er kommunizieren kann (dieser pod wird ein mongodb ausführen): +Ein **ConfigMap** ist die Konfiguration, die den pods gegeben wird, damit sie wissen, wie sie andere Services finden und auf sie zugreifen können. In diesem Fall weiß jeder pod, dass der Name `mongodb-service` die Adresse eines pods ist, mit dem er kommunizieren kann (dieser pod führt ein mongodb aus): ```yaml apiVersion: v1 kind: ConfigMap @@ -269,7 +271,7 @@ name: mongodb-configmap data: database_url: mongodb-service ``` -Dann kann diese Adresse innerhalb einer **deployment config** auf folgende Weise angegeben werden, sodass sie innerhalb der env des Pods geladen wird: +Dann kann diese Adresse innerhalb einer **deployment config** auf die folgende Weise angegeben werden, damit sie in die env des pod geladen wird: ```yaml [...] spec: @@ -290,16 +292,16 @@ name: mongodb-configmap key: database_url [...] ``` -**Beispiel für volume config** +**Beispiel für die Volume-Konfiguration** -Du findest verschiedene Beispiel-Dateien für storage-Konfigurationen in [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\ -**Beachte, dass volumes nicht innerhalb von namespaces sind** +Du kannst verschiedene Beispiel-Storage-Configuration-YAML-Dateien in [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes) finden.\ +**Beachte, dass volumes nicht innerhalb von namespaces liegen** ### Namespaces -Kubernetes unterstützt **mehrere virtuelle Cluster**, die von demselben physischen Cluster getragen werden. Diese virtuellen Cluster werden **namespaces** genannt. Sie sind für den Einsatz in Umgebungen mit vielen Benutzern gedacht, die über mehrere Teams oder Projekte verteilt sind. Für Cluster mit wenigen bis zu einigen Dutzend Benutzern musst du namespaces normalerweise gar nicht erstellen oder darüber nachdenken. Du solltest namespaces nur dann verwenden, wenn du eine bessere Kontrolle und Organisation jedes Teils der in kubernetes bereitgestellten Anwendung haben willst. +Kubernetes unterstützt **mehrere virtuelle Cluster**, die auf demselben physischen Cluster basieren. Diese virtuellen Cluster werden **namespaces** genannt. Sie sind für den Einsatz in Umgebungen mit vielen Benutzern gedacht, die auf mehrere Teams oder Projekte verteilt sind. Für Cluster mit wenigen bis zu einigen Dutzend Benutzern solltest du überhaupt keine namespaces erstellen oder darüber nachdenken. Du solltest namespaces nur dann verwenden, um eine bessere Kontrolle und Organisation jedes Teils der in kubernetes bereitgestellten Anwendung zu haben. -Namespaces bieten einen Gültigkeitsbereich für Namen. Namen von Ressourcen müssen innerhalb eines namespaces eindeutig sein, aber nicht über namespaces hinweg. Namespaces können nicht ineinander verschachtelt sein und **jede** Kubernetes-**Ressource** kann nur **in** **einem** **namespace** sein. +Namespaces bieten einen Namensraum für Namen. Die Namen von Ressourcen müssen innerhalb eines namespace eindeutig sein, aber nicht über namespaces hinweg. Namespaces können nicht ineinander verschachtelt werden und **jede** Kubernetes-**Ressource** kann nur **in** **einem** **namespace** sein. Es gibt standardmäßig 4 namespaces, wenn du minikube verwendest: ``` @@ -310,8 +312,8 @@ kube-node-lease Active 1d kube-public Active 1d kube-system Active 1d ``` -- **kube-system**: Es ist nicht dafür gedacht, dass Benutzer es verwenden, und du solltest es nicht anfassen. Es ist für master- und kubectl-Prozesse. -- **kube-public**: Öffentlich zugängliche Daten. Enthält ein configmap, das Cluster-Informationen enthält +- **kube-system**: Es ist nicht dafür gedacht oder von den Benutzern verwendet, und du solltest es nicht anfassen. Es ist für master- und kubectl-Prozesse. +- **kube-public**: Öffentlich zugängliche date. Enthält ein configmap, das Cluster-Informationen enthält - **kube-node-lease**: Bestimmt die Verfügbarkeit eines node - **default**: Der namespace, den der Benutzer verwenden wird, um Ressourcen zu erstellen ```bash @@ -319,7 +321,7 @@ kube-system Active 1d kubectl create namespace my-namespace ``` > [!NOTE] -> Beachte, dass die meisten Kubernetes-Ressourcen (z. B. pods, services, replication controllers und andere) sich in einigen namespaces befinden. Andere Ressourcen wie namespace resources und Low-Level-Ressourcen wie nodes und persistenVolumes befinden sich jedoch nicht in einem namespace. Um zu sehen, welche Kubernetes-Ressourcen sich in einem namespace befinden und welche nicht: +> Beachte, dass die meisten Kubernetes-Ressourcen (z. B. pods, services, replication controllers und andere) in einigen namespaces liegen. Andere Ressourcen wie namespace-Ressourcen und Low-Level-Ressourcen, wie nodes und persistenVolumes, liegen jedoch nicht in einem namespace. Um zu sehen, welche Kubernetes-Ressourcen in einem namespace liegen und welche nicht: > > ```bash > kubectl api-resources --namespaced=true #In a namespace @@ -332,25 +334,25 @@ kubectl config set-context --current --namespace= ``` ### Helm -Helm ist der **package manager** für Kubernetes. Es ermöglicht, YAML-Dateien zu paketieren und sie in öffentlichen und privaten repositories zu verteilen. Diese Pakete werden **Helm Charts** genannt. +Helm ist der **package manager** für Kubernetes. Es ermöglicht, YAML-Dateien zu paketieren und sie in öffentlichen und privaten Repositories zu verteilen. Diese Pakete werden **Helm Charts** genannt. ``` helm search ``` -Helm ist auch eine template engine, die es ermöglicht, config files mit Variablen zu generieren: +Helm ist auch eine Template-Engine, die es erlaubt, Config files mit Variablen zu generieren: ## Kubernetes secrets -Ein **Secret** ist ein Objekt, das **sensitive data** wie ein password, ein token oder einen key enthält. Solche Informationen könnten ansonsten in einer Pod specification oder in einem image abgelegt werden. Users können Secrets erstellen, und das system erstellt ebenfalls Secrets. Der Name eines Secret-Objekts muss ein gültiger **DNS subdomain name** sein. Lies hier [die offizielle documentation](https://kubernetes.io/docs/concepts/configuration/secret/). +Ein **Secret** ist ein Objekt, das **sensitive data** enthält, wie ein Passwort, ein Token oder ein key. Solche Informationen könnten sonst in einer Pod-Spezifikation oder in einem image abgelegt werden. Users können Secrets erstellen, und das system erstellt ebenfalls Secrets. Der Name eines Secret-Objekts muss ein gültiger **DNS subdomain name** sein. Hier lesen [the official documentation](https://kubernetes.io/docs/concepts/configuration/secret/). Secrets können Dinge sein wie: - API, SSH Keys. - OAuth tokens. - Credentials, Passwords (plain text oder b64 + encryption). -- Information oder comments. +- Informationen oder Kommentare. - Database connection code, strings… . -Es gibt verschiedene types of secrets in Kubernetes +Es gibt verschiedene types von secrets in Kubernetes | Builtin Type | Usage | | ----------------------------------- | ----------------------------------------- | @@ -364,13 +366,13 @@ Es gibt verschiedene types of secrets in Kubernetes | bootstrap.kubernetes.io/token | bootstrap token data | > [!NOTE] -> **Der Opaque-Typ ist der Standardtyp, das typische von Users definierte key-value pair.** +> **The Opaque type is the default one, the typical key-value pair defined by users.** **How secrets works:** ![Kubernetes secrets diagram showing secret data reaching the API server and being consumed by a pod](https://sickrov.github.io/media/Screenshot-164.jpg) -Die folgende configuration file definiert ein **secret** namens `mysecret` mit 2 key-value pairs `username: YWRtaW4=` und `password: MWYyZDFlMmU2N2Rm`. Sie definiert außerdem ein **pod** namens `secretpod`, das die in `mysecret` definierten `username` und `password` in den **environment variables** `SECRET_USERNAME` __ und __ `SECRET_PASSWOR` verfügbar macht. Es wird außerdem das `username` secret innerhalb von `mysecret` unter dem Pfad `/etc/foo/my-group/my-username` mit Berechtigungen `0640` **mounten**. +Die folgende configuration file definiert ein **secret** namens `mysecret` mit 2 key-value pairs `username: YWRtaW4=` und `password: MWYyZDFlMmU2N2Rm`. Sie definiert außerdem ein **pod** namens `secretpod`, der die in `mysecret` definierten `username` und `password` in den **environment variables** `SECRET_USERNAME` \_\_ und \_\_ `SECRET_PASSWOR` exponiert haben wird. Es wird außerdem das `username` secret aus `mysecret` unter dem Pfad `/etc/foo/my-group/my-username` mit Berechtigungen von `0640` **mount**en. ```yaml:secretpod.yaml apiVersion: v1 kind: Secret @@ -422,17 +424,17 @@ env | grep SECRET && cat /etc/foo/my-group/my-username && echo ``` ### Secrets in etcd -**etcd** ist ein konsistenter und hochverfügbarer **key-value store**, der als Kubernetes-Backing-Store für alle Cluster-Daten verwendet wird. Greifen wir auf die in etcd gespeicherten secrets zu: +**etcd** ist ein konsistenter und hochverfügbarer **key-value store**, der als Kubernetes-Backing-Store für alle Cluster-Daten verwendet wird. Lassen Sie uns auf die in etcd gespeicherten Secrets zugreifen: ```bash cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd ``` -Du wirst Zertifikate, Keys und URLs sehen, die sich im FS befinden. Sobald du sie hast, kannst du eine Verbindung zu etcd herstellen. +Du wirst sehen, dass Zertifikate, Keys und URLs im FS liegen. Sobald du sie hast, kannst du dich mit etcd verbinden. ```bash #ETCDCTL_API=3 etcdctl --cert --key --cacert endpoint=[] health ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health ``` -Sobald du eine Kommunikation aufbauen kannst, wirst du in der Lage sein, die secrets zu erhalten: +Sobald du die Kommunikation hergestellt hast, kannst du die secrets erhalten: ```bash #ETCDCTL_API=3 etcdctl --cert --key --cacert endpoint=[] get @@ -440,7 +442,7 @@ ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key ``` **Verschlüsselung zu ETCD hinzufügen** -Standardmäßig werden alle Secrets als **Klartext** in etcd gespeichert, sofern du keine Verschlüsselungsschicht anwendest. Das folgende Beispiel basiert auf [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) +Standardmäßig werden alle secrets **im Klartext** in etcd gespeichert, sofern du keine encryption layer anwendest. Das folgende Beispiel basiert auf [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) ```yaml:encryption.yaml apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration @@ -454,7 +456,7 @@ keys: secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key - identity: {} ``` -Danach musst du das `--encryption-provider-config`-Flag auf dem `kube-apiserver` setzen, um auf den Speicherort der erstellten Konfigurationsdatei zu verweisen. Du kannst `/etc/kubernetes/manifest/kube-apiserver.yaml` ändern und die folgenden Zeilen hinzufügen: +Danach musst du das `--encryption-provider-config`-Flag auf dem `kube-apiserver` setzen, sodass es auf den Speicherort der erstellten Config-Datei zeigt. Du kannst `/etc/kubernetes/manifest/kube-apiserver.yaml` ändern und die folgenden Zeilen hinzufügen: ```yaml containers: - command: @@ -476,36 +478,36 @@ name: etcd ``` **Verifying that data is encrypted** -Daten werden verschlüsselt, wenn sie nach etcd geschrieben werden. Nach dem Neustart deines `kube-apiserver` sollte jedes neu erstellte oder aktualisierte secret verschlüsselt gespeichert werden. Um das zu überprüfen, kannst du das `etcdctl` Commandline-Programm verwenden, um den Inhalt deines secrets abzurufen. +Data is encrypted when written to etcd. After restarting your `kube-apiserver`, any newly created or updated secret should be encrypted when stored. To check, you can use the `etcdctl` command line program to retrieve the contents of your secret. -1. Erstelle ein neues secret namens `secret1` im `default` namespace: +1. Create a new secret called `secret1` in the `default` namespace: ``` kubectl create secret generic secret1 -n default --from-literal=mykey=mydata ``` -2. Lies dieses secret mit der etcdctl Commandline aus etcd aus: +2. Using the etcdctl commandline, read that secret out of etcd: `ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C` -wobei `[...]` die zusätzlichen Argumente für die Verbindung zum etcd server sein müssen. +where `[...]` must be the additional arguments for connecting to the etcd server. -3. Verifiziere, dass dem gespeicherten secret das Präfix `k8s:enc:aescbc:v1:` vorangestellt ist, was anzeigt, dass der `aescbc` provider die resultierenden Daten verschlüsselt hat. -4. Verifiziere, dass das secret korrekt entschlüsselt wird, wenn es über die API abgerufen wird: +3. Verify the stored secret is prefixed with `k8s:enc:aescbc:v1:` which indicates the `aescbc` provider has encrypted the resulting data. +4. Verify the secret is correctly decrypted when retrieved via the API: ``` kubectl describe secret secret1 -n default ``` -sollte mit `mykey: bXlkYXRh` übereinstimmen, mydata ist encoded, prüfe [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) um das secret vollständig zu decodieren. +should match `mykey: bXlkYXRh`, mydata is encoded, check [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) to completely decode the secret. -**Since secrets are encrypted on write, performing an update on a secret will encrypt that content:** +**Da secrets bei write verschlüsselt werden, wird ein update auf ein secret diesen Inhalt verschlüsseln:** ``` kubectl get secrets --all-namespaces -o json | kubectl replace -f - ``` **Abschließende Tipps:** -- Versuche, Secrets nicht im FS zu behalten, hole sie aus anderen Orten. +- Versuche, Secrets nicht im FS zu speichern, sondern sie aus anderen Orten zu beziehen. - Schau dir [https://www.vaultproject.io/](https://www.vaultproject.io) an, um deinen Secrets mehr Schutz zu geben. - [https://kubernetes.io/docs/concepts/configuration/secret/#risks](https://kubernetes.io/docs/concepts/configuration/secret/#risks) - [https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm](https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm) @@ -520,4 +522,12 @@ https://sickrov.github.io/ https://www.youtube.com/watch?v=X48VuDVv0do {{#endref}} +{{#ref}} +https://kubernetes.io/docs/concepts/storage/volumes/#image +{{#endref}} + +{{#ref}} +https://kubernetes.io/docs/tasks/configure-pod-container/image-volumes/ +{{#endref}} + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md b/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md index 2835f57be..ff25cff59 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md @@ -4,81 +4,87 @@ ## PodSecurityContext -[**Aus den Docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) +[**Aus den docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) -Beim Festlegen des Security Context eines Pod kannst du mehrere Attribute verwenden. Aus defensiver Security-Sicht solltest du Folgendes berücksichtigen: +Wenn du den Security Context eines Pods angibst, kannst du mehrere Attribute verwenden. Aus defensiver Sicherheitssicht solltest du Folgendes beachten: - **runASNonRoot** auf **True** setzen - **runAsUser** konfigurieren -- Falls möglich, **Permissions** einschränken und dabei **seLinuxOptions** und **seccompProfile** angeben -- **KEINEN** **privilege**-**group**-Zugriff über **runAsGroup** und **supplementaryGroups** geben +- Wenn möglich, **Berechtigungen** einschränken, indem du **seLinuxOptions** und **seccompProfile** angibst +- **KEINE** **privilege**-**group**-Zugriffe über **runAsGroup** und **supplementaryGroups** geben | Parameter | Beschreibung | -|

fsGroup
integer

|

Eine spezielle zusätzliche Gruppe, die für alle container in einem pod gilt. Einige volume-Typen erlauben es dem Kubelet, den Eigentümer dieses volume zu ändern, sodass es dem pod gehört:
1. Die GID des Eigentümers ist die FSGroup
2. Das setgid-Bit ist gesetzt (neu erstellte Dateien im volume gehören der FSGroup)
3. Die Permission-Bits werden mit rw-rw---- verknüpft. Wenn nicht gesetzt, ändert das Kubelet weder Eigentum noch Permissions eines volume

| +|

fsGroup
integer

|

Eine spezielle zusätzliche Gruppe, die für alle containers in einem pod gilt. Einige volume-Typen erlauben dem Kubelet, den Besitzer dieses volumes zu ändern, sodass es dem pod gehört:
1. Die besitzende GID ist die FSGroup
2. Das setgid-Bit ist gesetzt (neu erstellte Dateien im volume gehören der FSGroup)
3. Die permission bits werden mit rw-rw---- verodert. Wenn nicht gesetzt, ändert das Kubelet die ownership und permissions von keinem volume

| -|

fsGroupChangePolicy
string

| Dies definiert das Verhalten beim **Ändern von Eigentum und Permissions des volume**, bevor es innerhalb des Pod verfügbar gemacht wird. | -|

runAsGroup
integer

| Die **GID, unter der der Entrypoint des container process ausgeführt wird**. Verwendet den runtime-Standard, wenn nicht gesetzt. Kann auch in SecurityContext gesetzt werden. | -|

runAsNonRoot
boolean

| Gibt an, dass der container als Nicht-root-Benutzer ausgeführt werden muss. Wenn true, validiert das Kubelet das image zur Laufzeit, um sicherzustellen, dass es nicht als UID 0 (root) läuft, und startet den container andernfalls nicht. | -|

runAsUser
integer

| Die **UID, unter der der Entrypoint des container process ausgeführt wird**. Standardmäßig der im image metadata angegebene Benutzer, falls nicht angegeben. | -|

seLinuxOptions
SELinuxOptions
More info about seLinux

| Der **SELinux context, der auf alle containers angewendet wird**. Falls nicht angegeben, weist die container runtime jedem container einen zufälligen SELinux context zu. | -|

seccompProfile
SeccompProfile
More info about Seccomp

| Die **seccomp options, die von den containers in diesem pod verwendet werden**. | -|

supplementalGroups
integer array

| Eine Liste von **Gruppen, die auf den ersten in jedem container ausgeführten Prozess angewendet werden**, zusätzlich zur primären GID des container. | -|

sysctls
Sysctl array
More info about sysctls

| Sysctls enthalten eine Liste von **namespaced sysctls, die für den pod verwendet werden**. Pods mit nicht unterstützten sysctls (durch die container runtime) können beim Start fehlschlagen. | +|

fsGroupChangePolicy
string

| Dies definiert das Verhalten beim **Ändern von ownership und permission des volumes**, bevor es innerhalb des Pod verfügbar gemacht wird. | +|

runAsGroup
integer

| Die **GID, unter der der entrypoint des container process ausgeführt wird**. Verwendet den runtime-default, wenn nicht gesetzt. Kann auch in SecurityContext gesetzt werden. | +|

runAsNonRoot
boolean

| Gibt an, dass der container als nicht-root user ausgeführt werden muss. Wenn true, validiert das Kubelet das image zur Laufzeit, um sicherzustellen, dass es nicht als UID 0 (root) läuft, und schlägt das Starten des container fehl, wenn dies der Fall ist. | +|

runAsUser
integer

| Die **UID, unter der der entrypoint des container process ausgeführt wird**. Standardmäßig der im image metadata angegebene user, falls nicht spezifiziert. | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| Der **SELinux context, der auf alle containers angewendet wird**. Falls nicht angegeben, weist die container runtime für jeden container einen zufälligen SELinux context zu. | +|

seccompProfile
SeccompProfile
More info about Seccomp

| Die **seccomp options, die von den containers in diesem pod verwendet werden sollen**. | +|

supplementalGroups
integer array

| Eine Liste von **groups, die auf den ersten in jedem container ausgeführten process angewendet werden**, zusätzlich zur primären GID des container. | +|

sysctls
Sysctl array
More info about sysctls

| Sysctls enthalten eine Liste von **namespaced sysctls, die für den pod verwendet werden**. Pods mit nicht unterstützten sysctls (durch die container runtime) können möglicherweise nicht gestartet werden. | |

windowsOptions
WindowsSecurityContextOptions

| Die Windows-spezifischen Einstellungen, die auf alle containers angewendet werden. Falls nicht angegeben, werden die Optionen innerhalb des SecurityContext eines container verwendet. | ## SecurityContext -[**Aus den Docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) +[**Aus den docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) -Dieser context wird innerhalb der **containers definitions** gesetzt. Aus defensiver Security-Sicht solltest du Folgendes berücksichtigen: +Dieser Context wird in den **container definitions** gesetzt. Aus defensiver Sicherheitssicht solltest du Folgendes beachten: - **allowPrivilegeEscalation** auf **False** - Keine sensiblen **capabilities** hinzufügen (und die nicht benötigten entfernen) - **privileged** auf **False** -- Falls möglich, **readOnlyFilesystem** auf **True** setzen -- **runAsNonRoot** auf **True** setzen und einen **runAsUser** festlegen -- Falls möglich, **Permissions** einschränken und dabei **seLinuxOptions** und **seccompProfile** angeben -- **KEINEN** **privilege**-**group**-Zugriff über **runAsGroup** geben +- Wenn möglich, **readOnlyFilesystem** auf **True** +- **runAsNonRoot** auf **True** setzen und einen **runAsUser** setzen +- Wenn möglich, **Berechtigungen** einschränken, indem du **seLinuxOptions** und **seccompProfile** angibst +- **KEINE** **privilege**-**group**-Zugriffe über **runAsGroup** geben. Beachte, dass bei Attributen, die sowohl in **SecurityContext** als auch in **PodSecurityContext** gesetzt sind, der in **SecurityContext** angegebene Wert **Vorrang** hat. -|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** steuert, ob ein Prozess **mehr Privilegien erlangen** kann als sein Parent-Prozess. Dieses bool bestimmt direkt, ob das no_new_privs-Flag für den container process gesetzt wird. AllowPrivilegeEscalation ist immer true, wenn der container als **Privileged** läuft oder **CAP_SYS_ADMIN** hat | +|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** steuert, ob ein process **mehr privileges erhalten kann** als sein parent process. Dieser boolesche Wert steuert direkt, ob das no_new_privs-Flag für den container process gesetzt wird. AllowPrivilegeEscalation ist immer true, wenn der container als **Privileged** läuft oder **CAP_SYS_ADMIN** hat | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|

capabilities
Capabilities
More info about Capabilities

| Die **capabilities, die beim Ausführen von containers hinzugefügt/entfernt werden**. Standardmäßig der Standard-Satz an capabilities. | -|

privileged
boolean

| container im privileged mode ausführen. Prozesse in privileged containers sind im Wesentlichen **gleichwertig zu root auf dem Host**. Standardmäßig false. | -|

procMount
string

| procMount bezeichnet den **Typ des proc mount, der für die containers verwendet werden soll**. Der Standard ist DefaultProcMount, der die container runtime-Standards für read-only paths und masked paths verwendet. | -|

readOnlyRootFilesystem
boolean

| Ob dieses **container ein read-only root filesystem hat**. Standard ist false. | -|

runAsGroup
integer

| Die **GID, unter der der Entrypoint** des container process ausgeführt wird. Verwendet den runtime-Standard, wenn nicht gesetzt. | -|

runAsNonRoot
boolean

| Gibt an, dass der container **als Nicht-root-Benutzer ausgeführt werden muss**. Wenn true, validiert das Kubelet das image zur Laufzeit, um sicherzustellen, dass es nicht als UID 0 (root) läuft, und startet den container andernfalls nicht. | -|

runAsUser
integer

| Die **UID, unter der der Entrypoint** des container process ausgeführt wird. Standardmäßig der im image metadata angegebene Benutzer, falls nicht angegeben. | -|

seLinuxOptions
SELinuxOptions
More info about seLinux

| Der **SELinux context, der auf den container angewendet wird**. Falls nicht angegeben, weist die container runtime jedem container einen zufälligen SELinux context zu. | -|

seccompProfile
SeccompProfile

| Die **seccomp options**, die von diesem container verwendet werden. | +|

capabilities
Capabilities
More info about Capabilities

| Die **capabilities, die beim Ausführen von containers hinzugefügt/entfernt werden**. Standardmäßig der default set of capabilities. | +|

privileged
boolean

| Container im privileged mode ausführen. Prozesse in privileged containers sind im Wesentlichen **äquivalent zu root auf dem host**. Standardmäßig false. | +|

procMount
string

| procMount bezeichnet den **Typ von proc mount, der für die containers verwendet werden soll**. Standard ist DefaultProcMount, das die container runtime defaults für readonly paths und masked paths verwendet. | +|

readOnlyRootFilesystem
boolean

| Ob dieser **container ein schreibgeschütztes root filesystem hat**. Standard ist false. | +|

runAsGroup
integer

| Die **GID, unter der der entrypoint** des container process ausgeführt wird. Verwendet den runtime-default, wenn nicht gesetzt. | +|

runAsNonRoot
boolean

| Gibt an, dass der container als **nicht-root user ausgeführt werden muss**. Wenn true, validiert das Kubelet das image zur Laufzeit, um sicherzustellen, dass es nicht als UID 0 (root) läuft, und schlägt das Starten des container fehl, wenn dies der Fall ist. | +|

runAsUser
integer

| Die **UID, unter der der entrypoint** des container process ausgeführt wird. Standardmäßig der im image metadata angegebene user, falls nicht spezifiziert. | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| Der **SELinux context, der auf den container angewendet wird**. Falls nicht angegeben, weist die container runtime für jeden container einen zufälligen SELinux context zu. | +|

seccompProfile
SeccompProfile

| Die **seccomp options**, die von diesem container verwendet werden sollen. | |

windowsOptions
WindowsSecurityContextOptions

| Die **Windows-spezifischen Einstellungen**, die auf alle containers angewendet werden. | -## Praktische Workload-Review-Checkliste +## Praktische Checkliste für Workload-Review -Beim Review eines Pod- oder Workload-Templates solltest du sowohl `spec.securityContext` als auch jedes container-level `securityContext` unter `containers`, `initContainers` und `ephemeralContainers` prüfen. Felder auf container-Ebene können die pod-level Defaults überschreiben, daher garantiert ein sicher aussehender pod-Default nicht, dass jeder container sicher ist. +Wenn du ein Pod- oder Workload-Template prüfst, inspiziere sowohl `spec.securityContext` als auch jedes container-level `securityContext` unter `containers`, `initContainers` und `ephemeralContainers`. Felder auf container-Ebene können die Defaults auf pod-Ebene überschreiben, daher garantiert ein sicher wirkender pod-Default nicht, dass jeder container sicher ist. -Hochriskante Kombinationen, die du priorisieren solltest: +Zu priorisierende High-Risk-Kombinationen: - `privileged: true`, besonders zusammen mit `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports oder runtime socket mounts. - Hinzugefügte capabilities wie `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` oder `DAC_OVERRIDE`. -- `allowPrivilegeEscalation: true` oder unset in containers, die attacker-controlled code ausführen können. -- `seccompProfile: Unconfined`, `procMount: Unmasked` oder fehlende runtime profiles bei sensiblen workloads. -- Schreibbare root filesystems oder breite schreibbare volume mounts in workloads, die untrusted input verarbeiten. -- Fehlende CPU-, memory- oder ephemeral-storage-Requests und Limits in Multi-tenant-Namespaces. +- `allowPrivilegeEscalation: true` oder nicht gesetzt bei containers, die attacker-controlled code ausführen können. +- `seccompProfile: Unconfined`, `procMount: Unmasked` oder fehlende runtime profiles bei sensiblen Workloads. +- Schreibbare root filesystems oder breite schreibbare volume mounts bei Workloads, die untrusted input verarbeiten. +- Fehlende CPU-, memory- oder ephemeral-storage-requests und -limits in multi-tenant namespaces. +- Fehlende oder unrealistische pod-level `spec.resources` budgets und principals mit `patch` oder `update` auf dem Pod-`resize`-subresource, da unterstützte clusters den laufenden CPU- und memory-Desired-State ändern können, ohne den Pod neu zu erstellen. -Für die meisten application workloads ist ein guter Ausgangspunkt, als Nicht-root-UID zu laufen, `runAsNonRoot: true` zu setzen, `allowPrivilegeEscalation: false` zu setzen, alle capabilities zu entfernen und nur die minimal benötigten wieder hinzuzufügen, `seccompProfile: RuntimeDefault` zu verwenden, ein read-only root filesystem zu bevorzugen und host namespaces, hostPath mounts sowie privileged mode zu vermeiden. +Resource-Kontrollen sind nicht Teil von `securityContext`, aber prüfe sie im selben Workload-Durchlauf, weil sie die availability boundary definieren. Modernes Kubernetes kann CPU-, memory- und hugepage-Budgets auf Pod-Ebene unter `spec.resources` zusätzlich zu container-level `resources` definieren. Ein Pod mit sidecars kann durch einen aggregierten Pod-envelope begrenzt sein, selbst wenn ein container keine individuellen limits hat, während lokaler ephemeral storage weiterhin separate `ephemeral-storage`-limits, `emptyDir.sizeLimit`, LimitRanges und ResourceQuotas benötigt. Vergleiche außerdem die gewünschten resources im Pod spec mit `status.containerStatuses[].resources` nach einer in-place resize request; ein fehlgeschlagener oder ausstehender resize kann den angeforderten Wert in `spec` lassen, während das kubelet die vorherige runtime allocation beibehält und eine `PodResizePending`-condition meldet. -Auf Cluster-Ebene solltest du, wo möglich, Namespace-Labels von [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) verwenden, um die Kubernetes [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) durchzusetzen. Verwende `restricted` für Namespaces, die es unterstützen, mindestens `baseline` für normale application namespaces, und halte privileged Ausnahmen eng, dokumentiert und isoliert auf vertrauenswürdige platform namespaces oder node pools. +Für die meisten application workloads ist eine gute baseline, als non-root UID auszuführen, `runAsNonRoot: true` zu setzen, `allowPrivilegeEscalation: false` zu setzen, alle capabilities zu droppen und nur die minimal benötigten wieder hinzuzufügen, `seccompProfile: RuntimeDefault` zu verwenden, ein read-only root filesystem zu bevorzugen und host namespaces, hostPath mounts und privileged mode zu vermeiden. + +Auf cluster-Ebene verwende [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) namespace labels, um nach Möglichkeit die Kubernetes [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) durchzusetzen. Verwende `restricted` für namespaces, die es unterstützen können, mindestens `baseline` für normale application namespaces, und halte privileged exceptions eng, dokumentiert und isoliert auf trusted platform namespaces oder node pools. ## References - [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) - [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) - [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +- [https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) - [https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/](https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/) - [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/) - [https://kubernetes.io/docs/concepts/security/pod-security-admission/](https://kubernetes.io/docs/concepts/security/pod-security-admission/) +- [https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/) +- [https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/](https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/) {{#include ../../../banners/hacktricks-training.md}}