Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-hardeni

This commit is contained in:
Translator
2026-07-04 11:48:29 +00:00
parent b256edcb3d
commit a9c4bb3cf5
3 changed files with 124 additions and 94 deletions
@@ -2,11 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
Istnieją **różne sposoby expose services** w Kubernetes, aby zarówno **internal** endpointy, jak i **external** endpointy mogły mieć do nich dostęp. Taka konfiguracja Kubernetes jest dość krytyczna, ponieważ administrator może dać access **attackers do services, do których nie powinni mieć access**.
Istnieją **różne sposoby wystawiania services** w Kubernetes, tak aby zarówno **internal** endpoints, jak i **external** endpoints mogły uzyskiwać do nich dostęp. Taka konfiguracja Kubernetes jest dość krytyczna, ponieważ administrator może dać **attackers dostęp do services, do których nie powinni mieć dostępu**.
### Automatic Enumeration
Zanim zaczniesz enumerating sposoby, jakie K8s oferuje do expose services publicznie, wiedz, że jeśli możesz list namespaces, services i ingresses, możesz znaleźć wszystko exposed do publicznego dostępu za pomocą:
Zanim zaczniesz enumerować sposoby, jakie K8s oferuje do wystawiania services publicznie, wiedz, że jeśli możesz list namespaces, services i ingresses, możesz znaleźć wszystko wystawione publicznie za pomocą:
```bash
kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
echo "Namespace: $ns"
@@ -20,13 +20,13 @@ done | grep -v "ClusterIP"
```
### ClusterIP
**ClusterIP** service to **domyślna** **service** Kubernetes. Zapewnia ci **service wewnątrz** twojego klastra, do którego inne aplikacje w twoim klastrze mogą uzyskać dostęp. **Brak** dostępu zewnętrznego.
**ClusterIP** service to **domyślna** usługa Kubernetes. Zapewnia **usługę wewnątrz** klastra, do której mogą uzyskać dostęp inne aplikacje w klastrze. **Brak zewnętrznego dostępu**.
Jednak można uzyskać do niej dostęp za pomocą Kubernetes Proxy:
```bash
kubectl proxy --port=8080
```
Teraz możesz nawigować przez Kubernetes API, aby uzyskać dostęp do services, używając tego schematu:
Teraz możesz poruszać się po Kubernetes API, aby uzyskać dostęp do services, używając tego schematu:
`http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/`
@@ -52,13 +52,13 @@ protocol: TCP
```
_Ta metoda wymaga uruchomienia `kubectl` jako **uwierzytelniony użytkownik**._
Wyświetl wszystkie ClusterIPs:
Lista wszystkich ClusterIP:
```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
Gdy używany jest **NodePort**, określony port zostaje udostępniony na wszystkich Nodes (reprezentujących Virtual Machines). **Traffic** kierowany na ten konkretny port jest następnie systematycznie **routed to the service**. Zazwyczaj ta metoda nie jest zalecana ze względu na jej wady.
Gdy używany jest **NodePort**, określony port jest udostępniany na wszystkich Nodes (reprezentujących Virtual Machines). **Traffic** kierowany na ten konkretny port jest następnie systematycznie **routed to the service**. Zwykle nie jest to zalecane ze względu na jego wady.
List all NodePorts:
```bash
@@ -81,15 +81,26 @@ targetPort: 80
nodePort: 30036
protocol: TCP
```
Jeśli **nie określisz** **nodePort** w yaml (to jest port, który zostanie otwarty), zostanie użyty port z zakresu **3000032767**.
Jeśli **nie określisz** **nodePort** w yaml (to port, który zostanie otwarty), zostanie użyty port w **zakresie 3000032767**.
Podczas przeglądania Services typu NodePort lub LoadBalancer, sprawdź też pola traffic-policy, ponieważ zmieniają one, które node i backendy są użyteczne z danego źródła:
```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` zachowuje oryginalny źródłowy IP klienta dla ruchu NodePort/LoadBalancer i unika przekazywania do endpointów na innych node. Node bez lokalnego gotowego endpointu może odrzucić ruch, nawet jeśli Service ma endpointy gdzie indziej.
- `externalTrafficPolicy: Cluster` jest domyślne i może przekazywać ruch przez dowolny node, ale logi backendu mogą widzieć IP node zamiast prawdziwego zewnętrznego IP klienta.
- `internalTrafficPolicy: Local` ogranicza ruch Service wewnątrz cluster do endpointów lokalnych względem node źródłowego. To routing oparty na locality, a nie boundary authorization.
- `sessionAffinity: ClientIP` może sprawić, że powtarzane testy z jednego klienta trafią do tego samego backend, ukrywając inne gotowe endpointy podczas ręcznych sprawdzeń.
- `trafficDistribution` i EndpointSlice topology hints mogą preferować endpointy w tej samej strefie lub na tym samym node w nowszych cluster; traktuj je jako preferencje routingu, a nie twardą politykę security.
### LoadBalancer
Udostępnia Service na zewnątrz **używając load balancera dostawcy cloud**. W GKE uruchomi to [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/), który da Ci jeden adres IP przekierowujący cały ruch do Twojego service. W AWS uruchomi to Load Balancer.
Udostępnia Service zewnętrznie **używając cloud provider's load balancer**. Na GKE uruchomi to [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/), który da ci jeden IP address, przekazujący cały traffic do twojego service. W AWS uruchomi Load Balancer.
Musisz płacić za LoadBalancer dla każdego wystawionego service, co może być kosztowne.
Musisz płacić za jeden LoadBalancer na każdy exposed service, co może być kosztowne.
Wyświetl wszystkie LoadBalancery:
List all LoadBalancers:
```bash
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer
```
@@ -100,11 +111,11 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam
>
> Aby je znaleźć, sprawdź load balancers z wartościami w polu `EXTERNAL-IP`.
Traffic, który wchodzi do klastra z **external IP** (jako **destination IP**), na porcie Service, będzie **przekierowany do jednego z endpointów Service**. `externalIPs` nie są zarządzane przez Kubernetes i są odpowiedzialnością administratora klastra.
Ruch wchodzący do klastra z **external IP** (jako **destination IP**), na porcie Service, zostanie **przekierowany do jednego z endpointów Service**. `externalIPs` nie są zarządzane przez Kubernetes i leżą w gestii administratora klastra.
`externalIPs` to wrażliwe pole kontroli routingu, ponieważ użytkownik, który może je ustawić, może przejąć traffic dla adresu IP, nad którym właściciel Service nie powinien mieć kontroli, jeśli okoliczna sieć routuje ten IP do klastra. Kubernetes ogłosił deprecjację i planowane usunięcie `externalIPs` Service w v1.36, więc tam, gdzie to możliwe, preferuj mechanizmy ekspozycji należące do controller, takie jak integracje LoadBalancer lub Gateway API, a to pole ograniczaj/dopuszczaj bardzo ostrożnie, dopóki jeszcze istnieje.
`externalIPs` to wrażliwe pole kontroli routingu, ponieważ użytkownik, który może je ustawić, może przejąć ruch dla adresu IP, nad którym właściciel Service nie powinien mieć kontroli, jeśli otaczająca sieć routuje ten adres IP do klastra. Kubernetes ogłosił deprecjację i planowane usunięcie `externalIPs` dla Service w v1.36, więc tam, gdzie to możliwe, preferuj mechanizmy wystawiania należące do controllerów, takie jak integracje LoadBalancer lub Gateway API, i ostrożnie ograniczaj/dopuszczaj to pole, dopóki jeszcze istnieje.
W specyfikacji Service `externalIPs` może być określone razem z dowolnym z `ServiceTypes`. W poniższym przykładzie "`my-service`" może być dostępny dla klientów pod "`80.11.12.10:80`" (`externalIP:port`)
W specyfikacji Service, `externalIPs` mo być określone razem z dowolnym z `ServiceTypes`. W poniższym przykładzie "`my-service`" może być dostępny dla klientów pod "`80.11.12.10:80`" (`externalIP:port`)
```yaml
apiVersion: v1
kind: Service
@@ -123,7 +134,7 @@ externalIPs:
```
### ExternalName
[**Z dokumentacji:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services typu ExternalName **mapują Service do nazwy DNS**, a nie do typowego selektora, takiego jak `my-service` czy `cassandra`. Określasz te Services za pomocą parametru `spec.externalName`.
[**Z dokumentacji:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services typu ExternalName **mapują Service do nazwy DNS**, a nie do typowego selektora, takiego jak `my-service` czy `cassandra`. Te Services określa się za pomocą parametru `spec.externalName`.
Na przykład ta definicja Service mapuje Service `my-service` w namespace `prod` na `my.database.example.com`:
```yaml
@@ -136,7 +147,7 @@ spec:
type: ExternalName
externalName: my.database.example.com
```
Gdy wyszukujesz host `my-service.prod.svc.cluster.local`, usługa cluster DNS zwraca rekord `CNAME` o wartości `my.database.example.com`. Dostęp do `my-service` działa tak samo jak w przypadku innych Services, ale z kluczową różnicą, że **przekierowanie odbywa się na poziomie DNS** zamiast przez proxying albo forwarding.
Podczas wyszukiwania hosta `my-service.prod.svc.cluster.local`, usługa DNS klastra zwraca rekord `CNAME` z wartością `my.database.example.com`. Dostęp do `my-service` działa w ten sam sposób jak w przypadku innych Services, ale z kluczową różnicą, że **przekierowanie odbywa się na poziomie DNS** zamiast przez proxying albo forwarding.
Wymień wszystkie ExternalNames:
```bash
@@ -144,7 +155,7 @@ kubectl get services --all-namespaces | grep ExternalName
```
### EndpointSlices
EndpointSlices pokazują konkretne adresy backendów i porty, do których Service aktualnie kieruje ruch. Są szczególnie przydatne, gdy Service nie ma selektora, gdy etykiety nie wyjaśniają ścieżki ruchu albo gdy tylko niektóre backendy są gotowe.
EndpointSlices pokazują konkretne adresy backendów i porty, do których Service aktualnie kieruje ruch. Są szczególnie przydatne, gdy Service nie ma selector, gdy labels nie wyjaśniają ścieżki ruchu lub gdy tylko część backendów jest gotowa.
Wyświetl EndpointSlices powiązane z Services:
```bash
@@ -153,15 +164,15 @@ kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-name> \
-o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port'
```
Podczas przeglądania exposure porównaj Service selector z EndpointSlice `targetRef`, adresami endpointów, warunkami readiness i portami. Service bez selektora może być połączony z ręcznie zarządzanymi EndpointSlices i kierować traffic do nie-Pod lub nieoczekiwanych destination.
Przy przeglądaniu exposure porównaj selector Service z `targetRef` EndpointSlice, adresami endpointów, warunkami readiness i portami. Service bez selectora może być połączony z ręcznie zarządzanymi EndpointSlices i kierować traffic do nie-Pod lub nieoczekiwanych destynacji.
### Ingress
W przeciwieństwie do wszystkich powyższych przykładów, **Ingress NIE jest typem service**. Zamiast tego znajduje się **przed wieloma services i działa jako smart router”** lub entrypoint do twojego cluster.
W przeciwieństwie do wszystkich powyższych przykładów, **Ingress NIE jest typem service**. Zamiast tego stoi **przed wieloma services i działa jako smart router”** albo punkt wejścia do twojego cluster.
Możesz robić z Ingress wiele różnych rzeczy, a istnieje **wiele typów Ingress controllers, które mają różne capabilities**.
Domyślny GKE ingress controller uruchomi dla ciebie [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/). Umożliwi ci to zarówno routing oparty na path, jak i na subdomain do backend services. Na przykład możesz wysłać wszystko z foo.yourdomain.com do service foo, a wszystko pod path yourdomain.com/bar/ do service bar.
Domyślny GKE ingress controller uruchomi dla ciebie [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/). Pozwoli ci to używać zarówno routingu opartego na ścieżce, jak i na subdomain, do backend services. Na przykład możesz wysłać wszystko na foo.yourdomain.com do service foo, a wszystko pod path yourdomain.com/bar/ do service bar.
YAML dla obiektu Ingress w GKE z [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) może wyglądać tak:
```yaml
@@ -197,19 +208,19 @@ name: bar
port:
number: 8080
```
Wyświetl wszystkie ingresses:
Wylistuj wszystkie ingresses:
```bash
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'
```
Mimo że w tym przypadku lepiej jest pobrać informacje o każdym z osobna, aby lepiej je przeczytać:
Chociaż w tym przypadku lepiej jest pobierać informacje o każdym z nich po kolei, aby lepiej je odczytać:
```bash
kubectl get ingresses --all-namespaces -o=yaml
```
### Gateway API
Gateway API to nowsze Kubernetes API do exposing Services. Oddziela należące do infrastruktury obiekty Gateway od należących do aplikacji obiektów Route, takich jak HTTPRoute. Jest to przydatne do delegation, ale oznacza też, że exposure może być rozdzielone między namespace.
Gateway API to nowsze Kubernetes API do exposing Services. Oddziela obiekty Gateway należące do infrastruktury od obiektów Route należących do aplikacji, takich jak HTTPRoute. Jest to przydatne do delegation, ale oznacza też, że exposure może być podzielone między namespace.
List Gateway API exposure objects:
Wylistuj obiekty exposure Gateway API:
```bash
kubectl get gatewayclasses
kubectl get gateways --all-namespaces
@@ -217,13 +228,16 @@ kubectl get httproutes --all-namespaces
kubectl get gateway -n <namespace> <gateway-name> -o yaml
kubectl get httproute -n <namespace> <route-name> -o yaml
```
Sprawdź Gateway listeners, dozwolone route namespaces, `parentRefs` Route, hostnames, filtry, backend references oraz warunki statusu, takie jak to, czy Route została zaakceptowana. Route zaakceptowana przez współdzielony Gateway może expose backend nawet wtedy, gdy nie istnieje żaden legacy obiekt Ingress.
Sprawdź Gateway listeners, dozwolone route namespaces, Route `parentRefs`, hostnames, filters, backend references oraz status conditions, takie jak to, czy route została accepted. Route, która została accepted przez współdzielony Gateway, może expose backend nawet wtedy, gdy nie istnieje żaden legacy Ingress object.
### 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/)
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
**Autorem oryginalnej wersji tej strony jest** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(przeczytaj jego oryginalny post [**here**](https://sickrov.github.io)**)**
**The original author of this page is** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(read his original post** [**here**](https://sickrov.github.io)**)**
## Architecture & Basics
@@ -19,17 +19,17 @@
![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**: system operacyjny z pod lub pods.
- **Node**: operating system with pod or pods.
- **Pod**: Wrapper around a container or multiple containers with. A pod should only contain one application (so usually, a pod run just 1 container). The pod is the way kubernetes abstracts the container technology running.
- **Service**: Each pod has 1 internal **IP address** from the internal range of the node. However, it can be also exposed via a service. The **service has also an IP address** and its goal is to maintain the communication between pods so if one dies the **new replacement** (with a different internal IP) **will be accessible** exposed in the **same IP of the service**. It can be configured as internal or external. The service also actuates as a **load balancer when 2 pods are connected** to the same service.\
When a **service** is **created** you can find the endpoints of each service running `kubectl get endpoints`
- **Kubelet**: Główny agent node. Komponent, który ustanawia komunikację między node i kubectl, i może uruchamiać tylko pods (through API server). Kubelet nie zarządza containerami, które nie zostały utworzone przez Kubernetes.
- **Kubelet**: Primary node agent. The component that establishes communication between node and kubectl, and only can run pods (through API server). The kubelet doesnt manage containers that were not created by Kubernetes.
- **Kube-proxy**: is the service in charge of the communications (services) between the apiserver and the node. The base is an IPtables for nodes. Most experienced users could install other kube-proxies from other vendors.
- **Sidecar container**: Sidecar containers are the containers that should run along with the main container in the pod. This sidecar pattern extends and enhances the functionality of current containers without changing them. Nowadays, We know that we use container technology to wrap all the dependencies for the application to run anywhere. A container does only one thing and does that thing very well.
- **Master process:**
- **Api Server:** To sposób, w jaki users i pods używają do komunikacji z master process. Tylko authenticated request should be allowed.
- **Api Server:** Is the way the users and the pods use to communicate with the master process. Only authenticated request should be allowed.
- **Scheduler**: Scheduling refers to making sure that Pods are matched to Nodes so that Kubelet can run them. It has enough intelligence to decide which node has more available resources the assign the new pod to it. Note that the scheduler doesn't start new pods, it just communicate with the Kubelet process running inside the node, which will launch the new pod.
- **Kube Controller manager**: Sprawdza resources takie jak replica sets lub deployments, aby sprawdzić, czy na przykład działa prawidłowa liczba pods lub nodes. W przypadku braku pod, skomunikuje się z scheduler, aby uruchomić nowy. Kontroluje replication, tokens i account services do API.
- **Kube Controller manager**: It checks resources like replica sets or deployments to check if, for example, the correct number of pods or nodes are running. In case a pod is missing, it will communicate with the scheduler to start a new one. It controls replication, tokens, and account services to the API.
- **etcd**: Data storage, persistent, consistent, and distributed. Is Kubernetess database and the key-value storage where it keeps the complete state of the clusters (each change is logged here). Components like the Scheduler or the Controller manager depends on this date to know which changes have occurred (available resourced of the nodes, number of pods running...)
- **Cloud controller manager**: Is the specific controller for flow controls and applications, i.e: if you have clusters in AWS or OpenStack.
@@ -39,12 +39,14 @@ Note that as the might be several nodes (running several pods), there might also
When a pod creates data that shouldn't be lost when the pod disappear it should be stored in a physical volume. **Kubernetes allow to attach a volume to a pod to persist the data**. The volume can be in the local machine or in a **remote storage**. If you are running pods in different physical nodes you should use a remote storage so all the pods can access it.
Kubernetes also supports **image volumes** in recent versions. An `image` volume mounts an OCI image or artifact as a **read-only** filesystem source inside the Pod, using fields such as `volumes[].image.reference` and `volumes[].image.pullPolicy`. The kubelet pulls the artifact with the same credential sources used for container images, including node credentials, Pod `imagePullSecrets`, and ServiceAccount `imagePullSecrets`. During a security review, treat image volumes as runtime inputs and supply-chain dependencies: check whether the reference is pinned by digest, which registry credentials can fetch it, where it is mounted, and whether `subPath` limits the visible directory.
**Other configurations:**
- **ConfigMap**: You can configure **URLs** to access services. The pod will obtain data from here to know how to communicate with the rest of the services (pods). Note that this is not the recommended place to save credentials!
- **Secret**: This is the place to **store secret data** like passwords, API keys... encoded in B64. The pod will be able to access this data to use the required credentials.
- **Deployments**: Tutaj wskazuje się components, które mają być uruchamiane przez kubernetes. User zwykle nie pracuje bezpośrednio z pods, pods abstrakcyjne w **ReplicaSets** (number of same pods replicated), które są uruchamiane przez deployments. Note that deployments are for **stateless** applications. The minimum configuration for a deployment is the name and the image to run.
- **StatefulSet**: Ten component jest przeznaczony specifically dla applications like **databases** które potrzebują **access the same storage**.
- **Deployments**: This is where the components to be run by kubernetes are indicated. A user usually won't work directly with pods, pods are abstracted in **ReplicaSets** (number of same pods replicated), which are run via deployments. Note that deployments are for **stateless** applications. The minimum configuration for a deployment is the name and the image to run.
- **StatefulSet**: This component is meant specifically for applications like **databases** which needs to **access the same storage**.
- **Ingress**: This is the configuration that is use to **expose the application publicly with an URL**. Note that this can also be done using external services, but this is the correct way to expose the application.
- If you implement an Ingress you will need to create **Ingress Controllers**. The Ingress Controller is a **pod** that will be the endpoint that will receive the requests and check and will load balance them to the services. the ingress controller will **send the request based on the ingress rules configured**. Note that the ingress rules can point to different paths or even subdomains to different internal kubernetes services.
- A better security practice would be to use a cloud load balancer or a proxy server as entrypoint to don't have any part of the Kubernetes cluster exposed.
@@ -138,7 +140,7 @@ kubectl apply -f deployment.yml
```
### Minikube Dashboard
Dashboard pozwala łatwiej zobaczyć, co działa w minikube; URL, aby uzyskać do niego dostęp, znajdziesz w:
Dashboard pozwala łatwiej zobaczyć, co działa w minikube, URL do dostępu znajdziesz w:
```
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
Każdy plik konfiguracji ma 3 części: **metadata**, **specification** (co trzeba uruchomić), **status** (desired state).\
Wewnątrz specification pliku konfiguracji deployment możesz znaleźć template zdefiniowany z nową strukturą konfiguracji, określającą image do uruchomienia:
Wewnątrz specification pliku konfiguracji deployment możesz znaleźć template zdefiniowany z nową strukturą konfiguracji określającą image do uruchomienia:
**Example of Deployment + Service zadeklarowane w tym samym pliku konfiguracji (z** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**
**Example of Deployment + Service zadeklarowanych w tym samym pliku konfiguracji (z** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**
Ponieważ service zwykle jest powiązany z jednym deployment, możliwe jest zadeklarowanie obu w tym samym pliku konfiguracji (service zadeklarowany w tej config jest dostępny tylko wewnętrznie):
Ponieważ service zwykle jest powiązany z jednym deployment, możliwe jest zadeklarowanie obu w tym samym pliku konfiguracji (service zadeklarowany w tym config jest dostępny tylko wewnętrznie):
```yaml
apiVersion: apps/v1
kind: Deployment
@@ -205,9 +207,9 @@ ports:
port: 27017
targetPort: 27017
```
**Przykład konfiguracji usługi zewnętrznej**
**Przykład zewnętrznej konfiguracji service**
Ta usługa będzie dostępna z zewnątrz (sprawdź atrybuty `nodePort` i `type: LoadBlancer`):
Ten service będzie dostępny zewnętrznie (sprawdź atrybuty `nodePort` i `type: LoadBlancer`):
```yaml
---
apiVersion: v1
@@ -225,9 +227,9 @@ targetPort: 8081
nodePort: 30000
```
> [!NOTE]
> Jest to przydatne do testowania, ale w środowisku produkcyjnym powinieneś mieć tylko internal services i Ingress do wystawienia aplikacji.
> To jest przydatne do testów, ale w produkcji powinieneś mieć tylko wewnętrzne usługi i Ingress, aby wystawić aplikację.
**Przykładowy plik konfiguracyjny Ingress**
**Przykład pliku konfiguracyjnego Ingress**
To wystawi aplikację pod `http://dashboard.com`.
```yaml
@@ -260,7 +262,7 @@ mongo-root-password: cGFzc3dvcmQ=
```
**Przykład ConfigMap**
**ConfigMap** to konfiguracja przekazywana do podów, aby wiedziały, jak znaleźć i uzyskać dostęp do innych usług. W tym przypadku każdy pod będzie wiedział, że nazwa `mongodb-service` to adres poda, z którym może się komunikować (ten pod będzie uruchamiał mongodb):
**ConfigMap** to konfiguracja przekazywana do podów, aby wiedziały, jak zlokalizować i uzyskać dostęp do innych usług. W tym przypadku każdy pod będzie wiedział, że nazwa `mongodb-service` to adres poda, z którym może się komunikować (ten pod będzie uruchamiał mongodb):
```yaml
apiVersion: v1
kind: ConfigMap
@@ -290,16 +292,16 @@ name: mongodb-configmap
key: database_url
[...]
```
**Przykład volume config**
**Przykład konfiguracji volume**
Możesz znaleźć różne przykłady plików YAML konfiguracji storage w [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
**Pamiętaj, że volumes nie są wewnątrz namespaces**
Możesz znaleźć różne przykłady plików yaml konfiguracji storage w [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
**Zwróć uwagę, że volumes nie są wewnątrz namespaces**
### Namespaces
Kubernetes wspiera **wiele wirtualnych clusterów** opartych na tym samym fizycznym clusterze. Te wirtualne clustery nazywane są **namespaces**. Są one przeznaczone do użycia w środowiskach z wieloma użytkownikami rozproszonymi między wieloma teams lub projects. Dla clusterów z kilkoma do kilkudziesięciu użytkowników nie powinieneś w ogóle potrzebować tworzenia ani nawet myślenia o namespaces. Powinieneś zacząć używać namespaces dopiero wtedy, gdy chcesz mieć lepszą kontrolę i organizację każdej części application wdrożonej w kubernetes.
Kubernetes wspiera **wiele wirtualnych klastrów** opartych na tym samym fizycznym cluster. Te wirtualne klastry nazywane są **namespaces**. Są one przeznaczone do użycia w środowiskach z wieloma użytkownikami pracującymi w wielu zespołach lub projektach. W przypadku cluster z kilkoma do kilkudziesięciu użytkowników nie powinieneś w ogóle potrzebować tworz ani nawet myśleć o namespaces. Zacznij używać namespaces dopiero wtedy, gdy chcesz lepiej kontrolować i organizować każdą część application wdrożonej w kubernetes.
Namespaces zapewniają zakres dla names. Names zasobów muszą być unikalne w obrębie jednego namespace, ale nie między namespaces. Namespaces nie mogą być zagnieżdżane jeden w drugim i **każdy** Kubernetes **resource** może znajdować się tylko w **jednym** **namespace**.
Namespaces zapewniają zakres dla nazw. Nazwy resources muszą być unikalne w obrębie jednego namespace, ale nie muszą być unikalne między namespaces. Namespaces nie mogą być zagnieżdżane jeden w drugim, a **każdy** Kubernetes **resource** może znajdować się tylko w **jednym** **namespace**.
Domyślnie są 4 namespaces, jeśli używasz minikube:
```
@@ -310,16 +312,16 @@ kube-node-lease Active 1d
kube-public Active 1d
kube-system Active 1d
```
- **kube-system**: Nie jest przeznaczony do użycia przez użytkowników i nie powinieneś go dotykać. Jest dla procesów master i kubectl.
- **kube-system**: Nie jest przeznaczona do użycia przez użytkowników i nie powinieneś jej ruszać. Jest dla procesów master i kubectl.
- **kube-public**: Publicznie dostępne dane. Zawiera configmap, który zawiera informacje o klastrze
- **kube-node-lease**: Określa dostępność node
- **default**: Namespace, którego użytkownik będzie używać do tworzenia resources
- **default**: Namespace, którego użytkownik będzie używać do tworzenia zasobów
```bash
#Create namespace
kubectl create namespace my-namespace
```
> [!NOTE]
> Zwróć uwa, że większość zasobów Kubernetes (np. pods, services, replication controllers i inne) znajduje się w niektórych namespaces. Jednak inne zasoby, takie jak namespace resources oraz zasoby niskiego poziomu, takie jak nodes i persistenVolumes, nie znajdują się w namespace. Aby zobaczyć, które zasoby Kubernetes znajdują się w namespace, a które nie:
> Zauważ, że większość zasobów Kubernetes (np. pods, services, replication controllers i innych) znajduje się w jakichś namespaces. Jednak inne zasoby, takie jak namespace resources i zasoby niskiego poziomu, takie jak nodes oraz persistenVolumes, nie znajdują się w namespace. Aby zobaczyć, które zasoby Kubernetes są i nie są w namespace:
>
> ```bash
> kubectl api-resources --namespaced=true #In a namespace
@@ -332,7 +334,7 @@ kubectl config set-context --current --namespace=<insert-namespace-name-here>
```
### Helm
Helm jest **package manager** dla Kubernetes. Pozwala pakować pliki YAML i dystrybuować je w publicznych i prywatnych repozytoriach. Te pakiety nazywane są **Helm Charts**.
Helm to **package manager** dla Kubernetes. Umożliwia pakowanie plików YAML i dystrybuowanie ich w publicznych i prywatnych repository. Te pakiety nazywane są **Helm Charts**.
```
helm search <keyword>
```
@@ -370,7 +372,7 @@ There are different types of secrets in Kubernetes
![Kubernetes secrets diagram showing secret data reaching the API server and being consumed by a pod](https://sickrov.github.io/media/Screenshot-164.jpg)
Następujący plik konfiguracyjny definiuje **secret** o nazwie `mysecret` z 2 parami klucz-wartość `username: YWRtaW4=` oraz `password: MWYyZDFlMmU2N2Rm`. Definiuje też **pod** o nazwie `secretpod`, który będzie miał `username` i `password` zdefiniowane w `mysecret` ujawnione w **zmiennych środowiskowych** `SECRET_USERNAME` \_\_ oraz \_\_ `SECRET_PASSWOR`. Będzie też **montował** secret `username` wewnątrz `mysecret` w ścieżce `/etc/foo/my-group/my-username` z uprawnieniami `0640`.
The following configuration file defines a **secret** called `mysecret` with 2 key-value pairs `username: YWRtaW4=` and `password: MWYyZDFlMmU2N2Rm`. It also defines a **pod** called `secretpod` that will have the `username` and `password` defined in `mysecret` exposed in the **environment variables** `SECRET_USERNAME` \_\_ and \_\_ `SECRET_PASSWOR`. It will also **mount** the `username` secret inside `mysecret` in the path `/etc/foo/my-group/my-username` with `0640` permissions.
```yaml:secretpod.yaml
apiVersion: v1
kind: Secret
@@ -422,11 +424,11 @@ env | grep SECRET && cat /etc/foo/my-group/my-username && echo
```
### Sekrety w etcd <a href="#discover-secrets-in-etcd" id="discover-secrets-in-etcd"></a>
**etcd** jest spójnym i wysoce dostępnym **key-value store** używanym jako backing store Kubernetes dla wszystkich danych klastra. Uzyskajmy dostęp do sekretów przechowywanych w etcd:
**etcd** to spójny i wysoko dostępny **key-value store** używany jako backing store Kubernetes dla wszystkich danych klastra. Spróbujmy uzyskać dostęp do secrets przechowywanych w etcd:
```bash
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd
```
Zobaczysz certs, keys i URL-e, które znajdują się w FS. Gdy je zdobędziesz, będziesz mógł połączyć się z etcd.
Zobaczysz certs, keys i urls znajdujące się w FS. Gdy je zdobędziesz, będziesz mógł połączyć się z etcd.
```bash
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health
@@ -440,7 +442,7 @@ ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key
```
**Dodawanie encryption do ETCD**
Domyślnie wszystkie secrets są **przechowywane w plain** text wewnątrz etcd, chyba że zastosujesz warstwę encryption. Poniższy przykład opiera się na [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
Domyślnie wszystkie secrets są **przechowywane w plain** tekście wewnątrz etcd, chyba że zastosujesz warstwę encryption. Poniższy przykład opiera się na [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: {}
```
Po tym musisz ustawić flagę `--encryption-provider-config` na `kube-apiserver`, aby wskazywała lokalizację utworzonego pliku konfiguracyjnego. Możesz zmodyfikować `/etc/kubernetes/manifest/kube-apiserver.yaml` i dodać następujące linie:
Następnie musisz ustawić flagę `--encryption-provider-config` na `kube-apiserver`, aby wskazywała lokalizację utworzonego pliku konfiguracyjnego. Możesz zmodyfikować `/etc/kubernetes/manifest/kube-apiserver.yaml` i dodać następujące linie:
```yaml
containers:
- command:
@@ -467,14 +469,14 @@ Przewiń w dół w volumeMounts:
name: etcd
readOnly: true
```
Przewiń w dół w volumeMounts do hostPath:
Przewiń w dół w `volumeMounts` do `hostPath`:
```yaml
- hostPath:
path: /etc/kubernetes/etcd
type: DirectoryOrCreate
name: etcd
```
**Weryfikacja, że dane są zaszyfrowane**
**Sprawdzanie, czy dane są zaszyfrowane**
Dane są szyfrowane podczas zapisu do etcd. Po ponownym uruchomieniu `kube-apiserver`, każdy nowo utworzony lub zaktualizowany secret powinien być zaszyfrowany podczas przechowywania. Aby to sprawdzić, możesz użyć programu wiersza poleceń `etcdctl`, aby pobrać zawartość swojego secret.
@@ -484,22 +486,22 @@ Dane są szyfrowane podczas zapisu do etcd. Po ponownym uruchomieniu `kube-apise
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
```
2. Używając commandline `etcdctl`, odczytaj ten secret z etcd:
2. Używając `etcdctl` commandline, odczytaj ten secret z etcd:
`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`
gdzie `[...]` musi być dodatkowymi argumentami do połączenia z serwerem etcd.
gdzie `[...]` musi zawierać dodatkowe argumenty do połączenia z serwerem etcd.
3. Sprawdź, że zapisany secret ma prefiks `k8s:enc:aescbc:v1:`, co wskazuje, że provider `aescbc` zaszyfrował wynikowe dane.
4. Sprawdź, że secret jest poprawnie odszyfrowany przy pobraniu przez API:
3. Sprawdź, czy zapisany secret jest poprzedzony `k8s:enc:aescbc:v1:`, co wskazuje, że provider `aescbc` zaszyfrował wynikowe dane.
4. Sprawdź, czy secret jest poprawnie odszyfrowywany przy pobieraniu przez API:
```
kubectl describe secret secret1 -n default
```
powinno dawać wynik zgodny z `mykey: bXlkYXRh`, mydata jest zakodowane, sprawdź [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret), aby całkowicie zdekodować secret.
powinno odpowiadać `mykey: bXlkYXRh`, mydata jest zakodowane, sprawdź [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) aby całkowicie zdekodować secret.
**Ponieważ secrets są szyfrowane podczas zapisu, wykonanie update na secie zaszyfruje tę zawartość:**
**Ponieważ secrets są szyfrowane przy zapisie, wykonanie update na secie zaszyfruje tę zawartość:**
```
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
```
@@ -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}}
@@ -6,31 +6,31 @@
[**Z dokumentacji:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core)
Podczas określania security context dla Pod możesz użyć kilku atrybutów. Z defensywnego punktu widzenia bezpieczeństwa warto rozważyć:
Podczas określania security context Pod możesz użyć kilku atrybutów. Z defensywnego punktu widzenia powinieneś rozważyć:
- Ustawienie **runASNonRoot** na **True**
- Skonfigurowanie **runAsUser**
- Konfigurację **runAsUser**
- Jeśli to możliwe, rozważ **ograniczenie** **permissions** wskazując **seLinuxOptions** i **seccompProfile**
- **NIE** nadawaj dostępu do **privilege** **group** przez **runAsGroup** i **supplementaryGroups**
- **NIE** dawaj dostępu do **privilege** **group** przez **runAsGroup** i **supplementaryGroups**
| Parameter | Description |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroup</strong></a><br><em>integer</em></p> | <p>Specjalna grupa dodatkowa, która ma zastosowanie do <strong>wszystkich kontenerów w pod</strong>. Niektóre typy wolumenów pozwalają Kubelet na <strong>zmianę właściciela tego wolumenu</strong> tak, aby należał do poda:<br>1. Właściciel GID będzie FSGroup<br>2. Ustawiany jest bit setgid (nowe pliki utworzone w wolumenie będą należeć do FSGroup)<br>3. Bity uprawnień są łączone operacją OR z rw-rw---- Jeśli nie ustawiono, Kubelet nie będzie modyfikować własności ani uprawnień żadnego wolumenu</p> |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroup</strong></a><br><em>integer</em></p> | <p>Specjalna grupa pomocnicza, która ma zastosowanie do <strong>wszystkich kontenerów w podzie</strong>. Niektóre typy woluminów pozwalają Kubeletowi na <strong>zmianę właściciela tego woluminu</strong>, tak aby był własnością poda:<br>1. GID właściciela będzie równy FSGroup<br>2. Bit setgid jest ustawiany (nowe pliki utworzone w woluminie będą należeć do FSGroup)<br>3. Bity uprawnień są OR'd z rw-rw---- Jeśli nie ustawiono, Kubelet nie zmodyfikuje własności ani uprawnień żadnego woluminu</p> |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroupChangePolicy</strong></a><br><em>string</em></p> | Określa zachowanie **zmiany własności i uprawnień wolumenu** przed jego udostępnieniem wewnątrz Pod. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | **GID, z którym uruchamiany jest entrypoint procesu kontenera**. Używa domyślnej wartości runtime, jeśli nie ustawiono. Może być też ustawione w SecurityContext. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Wskazuje, że kontener musi działać jako użytkownik nie-root. Jeśli true, Kubelet zweryfikuje obraz w czasie działania, aby upewnić się, że nie uruchamia się jako UID 0 (root), i nie uruchomi kontenera, jeśli tak się dzieje. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | **UID, z którym uruchamiany jest entrypoint procesu kontenera**. Jeśli nie podano, domyślnie używany jest użytkownik określony w metadanych obrazu. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | **SELinux context, który ma zostać zastosowany do wszystkich kontenerów**. Jeśli nie podano, runtime kontenera przypisze losowy SELinux context dla każdego kontenera. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a><br><em>More info about</em> <em><strong>Seccomp</strong></em></p> | **Opcje seccomp**, których mają używać kontenery w tym podzie. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroupChangePolicy</strong></a><br><em>string</em></p> | To określa zachowanie **zmiany własności i uprawnień woluminu** przed udostępnieniem go wewnątrz Pod. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | **GID używany do uruchomienia entrypoint procesu kontenera**. Używa domyślnej wartości runtime, jeśli nie ustawiono. Może być też ustawione w SecurityContext. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Wskazuje, że kontener musi działać jako użytkownik inny niż root. Jeśli true, Kubelet zweryfikuje obraz w czasie uruchomienia, aby upewnić się, że nie działa jako UID 0 (root), i nie uruchomi kontenera, jeśli tak jest. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | **UID używany do uruchomienia entrypoint procesu kontenera**. Domyślnie użytkownik określony w metadanych obrazu, jeśli nie podano inaczej. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | **SELinux context stosowany do wszystkich kontenerów**. Jeśli nie podano, runtime kontenera przydzieli losowy SELinux context dla każdego kontenera. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a><br><em>More info about</em> <em><strong>Seccomp</strong></em></p> | **Opcje seccomp używane przez kontenery** w tym podzie. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>supplementalGroups</strong></a><br><em>integer array</em></p> | Lista **grup stosowanych do pierwszego procesu uruchamianego w każdym kontenerze**, oprócz podstawowego GID kontenera. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>sysctls</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#sysctl-v1-core"><em>Sysctl</em></a> <em>array</em><br><em>More info about</em> <a href="https://www.garron.me/en/go2linux/sysctl-linux.html"><em><strong>sysctls</strong></em></a></p> | Sysctls zawiera listę **namespaced sysctls używanych dla poda**. Pody z nieobsługiwanymi sysctls (przez container runtime) mogą nie uruchomić się. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | Ustawienia specyficzne dla Windows stosowane do wszystkich kontenerów. Jeśli nie podano, użyte zostaną opcje z SecurityContext kontenera. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>sysctls</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#sysctl-v1-core"><em>Sysctl</em></a> <em>array</em><br><em>More info about</em> <a href="https://www.garron.me/en/go2linux/sysctl-linux.html"><em><strong>sysctls</strong></em></a></p> | Sysctls zawiera listę **namespaced sysctls używanych dla poda**. Pody z nieobsługiwanymi sysctls (przez runtime kontenera) mogą nie zostać uruchomione. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | Ustawienia specyficzne dla Windows stosowane do wszystkich kontenerów. Jeśli nie podano, zostaną użyte opcje z SecurityContext kontenera. |
## SecurityContext
[**Z dokumentacji:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core)
Ten context jest ustawiany wewnątrz **definicji kontenerów**. Z defensywnego punktu widzenia bezpieczeństwa warto rozważyć:
Ten context jest ustawiany wewnątrz **definicji kontenerów**. Z defensywnego punktu widzenia powinieneś rozważyć:
- **allowPrivilegeEscalation** na **False**
- Nie dodawaj wrażliwych **capabilities** (i usuń te, których nie potrzebujesz)
@@ -38,47 +38,53 @@ Ten context jest ustawiany wewnątrz **definicji kontenerów**. Z defensywnego p
- Jeśli to możliwe, ustaw **readOnlyFilesystem** jako **True**
- Ustaw **runAsNonRoot** na **True** i ustaw **runAsUser**
- Jeśli to możliwe, rozważ **ograniczenie** **permissions** wskazując **seLinuxOptions** i **seccompProfile**
- **NIE** nadawaj dostępu do **privilege** **group** przez **runAsGroup.**
- **NIE** dawaj dostępu do **privilege** **group** przez **runAsGroup.**
Zwróć uwagę, że dla atrybutów ustawionych zarówno w **SecurityContext**, jak i **PodSecurityContext**, pierwszeństwo ma wartość podana w **SecurityContext**.
Zwróć uwagę, że atrybuty ustawione zarówno w **SecurityContext, jak i PodSecurityContext**, mają **pierwszeństwo** w wartości podanej w **SecurityContext**.
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>allowPrivilegeEscalation</strong></a><br><em>boolean</em></p> | **AllowPrivilegeEscalation** kontroluje, czy proces może **uzyskać więcej uprawnień** niż jego proces rodzic. Ten bool bezpośrednio kontroluje, czy flaga no_new_privs zostanie ustawiona dla procesu kontenera. AllowPrivilegeEscalation jest zawsze true, gdy kontener działa jako **Privileged** lub ma **CAP_SYS_ADMIN** |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>allowPrivilegeEscalation</strong></a><br><em>boolean</em></p> | **AllowPrivilegeEscalation** kontroluje, czy proces może **uzyskać więcej uprawnień** niż jego proces nadrzędny. Ten bool bezpośrednio kontroluje, czy flaga no_new_privs zostanie ustawiona dla procesu kontenera. AllowPrivilegeEscalation ma zawsze wartość true, gdy kontener działa jako **Privileged** lub ma **CAP_SYS_ADMIN** |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>capabilities</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#capabilities-v1-core"><em>Capabilities</em></a><br><em>More info about</em> <em><strong>Capabilities</strong></em></p> | **Capabilities do dodania/usunięcia podczas uruchamiania kontenerów**. Domyślnie używany jest domyślny zestaw capabilities. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>privileged</strong></a><br><em>boolean</em></p> | Uruchamia kontener w trybie privileged. Procesy w kontenerach privileged są zasadniczo **równoważne rootowi na hoście**. Domyślnie false. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>procMount</strong></a><br><em>string</em></p> | procMount oznacza **typ proc mount używany przez kontenery**. Domyślnie jest to DefaultProcMount, który używa domyślnych ustawień runtime dla ścieżek tylko do odczytu i maskowanych ścieżek. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>privileged</strong></a><br><em>boolean</em></p> | Uruchom kontener w trybie privileged. Procesy w kontenerach privileged są zasadniczo **równoważne root na hoście**. Domyślnie false. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>procMount</strong></a><br><em>string</em></p> | procMount oznacza **typ proc mount używany przez kontenery**. Domyślnie jest to DefaultProcMount, które używa domyślnych ustawień runtime dla ścieżek tylko do odczytu i zamaskowanych ścieżek. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>readOnlyRootFilesystem</strong></a><br><em>boolean</em></p> | Czy ten **kontener ma root filesystem tylko do odczytu**. Domyślnie false. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | **GID, z którym uruchamiany jest entrypoint** procesu kontenera. Używa domyślnej wartości runtime, jeśli nie ustawiono. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Wskazuje, że kontener musi **działać jako użytkownik nie-root**. Jeśli true, Kubelet zweryfikuje obraz w czasie działania, aby upewnić się, że nie uruchamia się jako UID 0 (root), i nie uruchomi kontenera, jeśli tak się dzieje. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | **UID, z którym uruchamiany jest entrypoint** procesu kontenera. Jeśli nie podano, domyślnie używany jest użytkownik określony w metadanych obrazu. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | **SELinux context, który ma zostać zastosowany do kontenera**. Jeśli nie podano, runtime kontenera przypisze losowy SELinux context dla każdego kontenera. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | **GID używany do uruchomienia entrypoint** procesu kontenera. Używa domyślnej wartości runtime, jeśli nie ustawiono. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Wskazuje, że kontener musi **działać jako użytkownik inny niż root**. Jeśli true, Kubelet zweryfikuje obraz w czasie uruchomienia, aby upewnić się, że nie działa jako UID 0 (root), i nie uruchomi kontenera, jeśli tak jest. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | **UID używany do uruchomienia entrypoint** procesu kontenera. Domyślnie użytkownik określony w metadanych obrazu, jeśli nie podano inaczej. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | **SELinux context stosowany do kontenera**. Jeśli nie podano, runtime kontenera przydzieli losowy SELinux context dla każdego kontenera. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a></p> | **Opcje seccomp** używane przez ten kontener. |
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | **Ustawienia specyficzne dla Windows** stosowane do wszystkich kontenerów. |
## Practical workload review checklist
Podczas przeglądu Pod lub szablonu workload sprawdź zarówno `spec.securityContext`, jak i każdy `securityContext` na poziomie kontenera w `containers`, `initContainers` oraz `ephemeralContainers`. Pola na poziomie kontenera mogą nadpisywać domyślne ustawienia poda, więc bezpiecznie wyglądający domyślny ustawiony dla poda nie gwarantuje, że każdy kontener jest bezpieczny.
Podczas przeglądania Pod lub template workload sprawdź zarówno `spec.securityContext`, jak i każdy `securityContext` na poziomie kontenera w `containers`, `initContainers` oraz `ephemeralContainers`. Pola na poziomie kontenera mogą nadpisywać domyślne ustawienia poda, więc bezpiecznie wyglądający domyślny Pod nie gwarantuje, że każdy kontener jest bezpieczny.
Kombinacje wysokiego ryzyka, które warto priorytetyzować:
Kombinacje wysokiego ryzyka, które należy priorytetyzować:
- `privileged: true`, zwłaszcza z `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports lub mountami socketów runtime.
- Dodane capabilities takie jak `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` lub `DAC_OVERRIDE`.
- `allowPrivilegeEscalation: true` lub brak ustawienia w kontenerach, które mogą wykonywać kod kontrolowany przez atakującego.
- `seccompProfile: Unconfined`, `procMount: Unmasked` lub brak profili runtime w wrażliwych workload.
- Root filesystem z możliwością zapisu lub szerokie montowania wolumenów z zapisem w workload przetwarzających niezaufane dane wejściowe.
- Brak requestów i limitów CPU, memory lub ephemeral-storage w namespace multi-tenant.
- `privileged: true`, szczególnie z `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports lub mountami socketów runtime.
- Dodane capabilities, takie jak `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` lub `DAC_OVERRIDE`.
- `allowPrivilegeEscalation: true` albo brak ustawienia w kontenerach, które mogą wykonywać kod kontrolowany przez atakującego.
- `seccompProfile: Unconfined`, `procMount: Unmasked` lub brak profili runtime w wrażliwych workloadach.
- Zapisywalny root filesystem lub szerokie, zapisywalne mounty woluminów w workloadach przetwarzających niezaufane dane wejściowe.
- Brak requestów i limitów CPU, memory lub ephemeral-storage w przestrzeniach nazw wielodzierżawnych.
- Brak lub nierealistyczne budżety na poziomie poda `spec.resources` oraz podmioty z `patch` lub `update` na podzasobie `resize` poda, ponieważ obsługiwane klastry mogą zmieniać działający stan docelowy CPU i memory bez ponownego tworzenia Poda.
Dla większości workload aplikacyjnych dobrą bazą jest uruchamianie jako nie-root UID, ustawienie `runAsNonRoot: true`, `allowPrivilegeEscalation: false`, usunięcie wszystkich capabilities i dodanie tylko minimalnie wymaganych, użycie `seccompProfile: RuntimeDefault`, preferowanie root filesystem tylko do odczytu oraz unikanie host namespaces, mountów hostPath i trybu privileged.
Kontrola zasobów nie jest częścią `securityContext`, ale warto sprawdzać ją w tym samym przeglądzie workload, ponieważ wyznacza granicę dostępności. Nowoczesny Kubernetes może definiować budżety CPU, memory i hugepage na poziomie Poda pod `spec.resources`, oprócz `resources` na poziomie kontenera. Pod z sidecars może być ograniczony przez łączny envelope Poda, nawet gdy jeden kontener nie ma indywidualnych limitów, podczas gdy lokalne ephemeral storage nadal wymaga osobnych limitów `ephemeral-storage`, `emptyDir.sizeLimit`, LimitRanges i ResourceQuotas. Porównaj też żądane zasoby w spec Poda z `status.containerStatuses[].resources` po żądaniu in-place resize; nieudany lub oczekujący resize może pozostawić żądaną wartość w `spec`, podczas gdy kubelet zachowuje poprzednią alokację runtime i raportuje warunek `PodResizePending`.
Na poziomie klastra używaj etykiet namespace dla [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/), aby egzekwować Kubernetes [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) tam, gdzie to możliwe. Używaj `restricted` dla namespace, które to obsługują, przynajmniej `baseline` dla zwykłych namespace aplikacyjnych, a wyjątki privileged utrzymuj wąskie, udokumentowane i odizolowane do zaufanych namespace platformowych lub pul node.
Dla większości workload aplikacyjnych dobrym punktem wyjścia jest uruchamianie jako nie-root UID, ustawienie `runAsNonRoot: true`, ustawienie `allowPrivilegeEscalation: false`, usunięcie wszystkich capabilities i dodanie z powrotem tylko minimalnie wymaganych, użycie `seccompProfile: RuntimeDefault`, preferowanie root filesystem tylko do odczytu oraz unikanie host namespaces, mountów hostPath i trybu privileged.
Na poziomie klastra używaj etykiet namespace dla [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/), aby wymuszać Kubernetes [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/), gdzie to możliwe. Używaj `restricted` dla namespace, które mogą to obsłużyć, co najmniej `baseline` dla zwykłych namespace aplikacyjnych, a wyjątki privileged utrzymuj wąskie, udokumentowane i odizolowane do zaufanych namespace platformowych lub pule node.
## 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}}