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 b8762e59a..1628948a4 100644 --- a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md +++ b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md @@ -1,12 +1,12 @@ -# Exposing Services in Kubernetes +# Expondo Serviços no Kubernetes {{#include ../../banners/hacktricks-training.md}} -Há **diferentes maneiras de expor services** no Kubernetes para que tanto endpoints **internos** quanto endpoints **externos** possam acessá-los. Essa configuração do Kubernetes é bem crítica, pois o administrator pode dar acesso a **attackers a services they shouldn't be able to access**. +Existem **diferentes maneiras de expor services** no Kubernetes para que tanto endpoints **internos** quanto endpoints **externos** possam acessá-los. Essa configuração do Kubernetes é bastante crítica, pois o administrador pode dar acesso a **attackers a serviços que eles não deveriam conseguir acessar**. -### Automatic Enumeration +### Enumeração Automática -Antes de começar a enumerar as maneiras que o K8s oferece para expor services ao público, saiba que se você puder listar namespaces, services e ingresses, você pode encontrar tudo exposto ao público com: +Antes de começar a enumerar as maneiras que o K8s oferece para expor services ao público, saiba que, se você puder listar namespaces, services e ingresses, poderá encontrar tudo exposto ao público com: ```bash kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do echo "Namespace: $ns" @@ -20,7 +20,7 @@ done | grep -v "ClusterIP" ``` ### ClusterIP -Um serviço **ClusterIP** é o **service** padrão do Kubernetes. Ele fornece um **service dentro** do seu cluster que outros apps dentro do seu cluster podem acessar. **Não há acesso externo**. +Um serviço **ClusterIP** é o **service** padrão do Kubernetes. Ele fornece um **service dentro** do seu cluster que outros apps dentro do seu cluster podem acessar. Não há **acesso externo**. No entanto, isso pode ser acessado usando o Kubernetes Proxy: ```bash @@ -30,7 +30,7 @@ Agora, você pode navegar pela Kubernetes API para acessar services usando este `http://localhost:8080/api/v1/proxy/namespaces//services/:/` -Por exemplo, você poderia usar a seguinte URL: +Por exemplo, você pode usar a seguinte URL: `http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/` @@ -58,13 +58,13 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam ``` ### NodePort -Quando **NodePort** é utilizado, uma porta designada é disponibilizada em todos os Nodes (representando as Virtual Machines). O **tráfego** direcionado para essa porta específica é então sistematicamente **roteado para o service**. Normalmente, esse método não é recomendado devido às suas desvantagens. +Quando **NodePort** é utilizado, uma porta designada é disponibilizada em todos os Nodes (representando as Virtual Machines). **Traffic** direcionado para essa porta específica é então sistematicamente **roteado para o service**. Normalmente, esse método não é recomendado devido às suas desvantagens. List all NodePorts: ```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,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort ``` -Um exemplo de especificação NodePort: +Um exemplo de especificação de NodePort: ```yaml apiVersion: v1 kind: Service @@ -81,28 +81,39 @@ targetPort: 80 nodePort: 30036 protocol: TCP ``` -Se você **não especificar** o **nodePort** no yaml (é a porta que será aberta), uma porta no **intervalo de 30000–32767 será usada**. +Se você **não especificar** o **nodePort** no yaml (é a porta que será aberta), uma porta no **intervalo 30000–32767 será usada**. + +Ao revisar Services NodePort ou LoadBalancer, também inspecione os campos traffic-policy, porque eles alteram quais nodes e backends são úteis a partir de uma determinada origem: +```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` preserva o IP de origem original do cliente para tráfego NodePort/LoadBalancer e evita encaminhamento para endpoints em outros nodes. Um node sem um endpoint local pronto pode descartar o tráfego mesmo que o Service tenha endpoints em outro lugar. +- `externalTrafficPolicy: Cluster` é o padrão e pode encaminhar por qualquer node, mas os logs do backend podem ver IPs de node em vez do IP real do cliente externo. +- `internalTrafficPolicy: Local` limita o tráfego do Service dentro do cluster a endpoints locais ao node de origem. Isso é routing por locality, não um boundary de autorização. +- `sessionAffinity: ClientIP` pode fazer testes repetidos a partir de um cliente atingirem o mesmo backend, escondendo outros endpoints prontos durante verificações manuais. +- `trafficDistribution` e os EndpointSlice topology hints podem preferir endpoints da mesma zone ou do mesmo node em clusters mais novos; trate isso como preferências de routing, não como política de security rígida. ### LoadBalancer -Expõe o Service externamente **usando um load balancer do cloud provider**. No GKE, isso iniciará um [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) que fornecerá um único endereço IP que encaminhará todo o tráfego para o seu service. No AWS, ele lançará um Load Balancer. +Expõe o Service externamente **usando um load balancer do cloud provider**. No GKE, isso iniciará um [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) que fornecerá um único endereço IP que encaminhará todo o tráfego para o seu service. Na AWS, ele lançará um Load Balancer. Você precisa pagar por um LoadBalancer por service exposto, o que pode ser caro. -Liste todos os LoadBalancers: +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 ``` ### External IPs > [!TIP] -> External IPs são expostos por serviços do tipo Load Balancers e geralmente são usados quando um Cloud Provider Load Balancer externo está sendo usado. +> External IPs são expostos por services do tipo Load Balancers e geralmente são usados quando um external Cloud Provider Load Balancer está sendo usado. > -> Para encontrá-los, verifique os load balancers com valores no campo `EXTERNAL-IP`. +> Para encontrá-los, verifique load balancers com valores no campo `EXTERNAL-IP`. O tráfego que ingressa no cluster com o **external IP** (como **destination IP**), na porta do Service, será **roteado para um dos endpoints do Service**. `externalIPs` não são gerenciados pelo Kubernetes e são de responsabilidade do administrador do cluster. -`externalIPs` é um campo sensível de controle de rota porque um usuário que pode defini-lo pode reivindicar tráfego para um endereço IP que o proprietário do Service não deveria controlar se a rede ao redor rotear esse IP para o cluster. O Kubernetes anunciou a descontinuação e a remoção planejada de `externalIPs` do Service na v1.36, então prefira mecanismos de exposição controlados por controller, como integrações de LoadBalancer ou Gateway API quando possível, e restrinja/autorize esse campo com cuidado enquanto ele ainda existir. +`externalIPs` é um campo sensível de controle de rota porque um usuário que consegue defini-lo pode reivindicar tráfego para um endereço IP que o owner do Service não deveria controlar, se a rede ao redor rotear esse IP para o cluster. O Kubernetes anunciou a depreciação e a remoção planejada de `externalIPs` de Service na v1.36, então prefira mecanismos de exposição controlados por controller, como integrações LoadBalancer ou Gateway API quando possível, e restrinja/valide esse campo com cuidado enquanto ele ainda existir. Na spec do Service, `externalIPs` pode ser especificado junto com qualquer um dos `ServiceTypes`. No exemplo abaixo, "`my-service`" pode ser acessado por clients em "`80.11.12.10:80`" (`externalIP:port`) ```yaml @@ -123,7 +134,7 @@ externalIPs: ``` ### ExternalName -[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services of type ExternalName **mapeiam um Service para um nome DNS**, e não para um seletor típico como `my-service` ou `cassandra`. Você especifica esses Services com o parâmetro `spec.externalName`. +[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services do tipo ExternalName **mapeiam um Service para um nome DNS**, não para um selector típico como `my-service` ou `cassandra`. Você especifica esses Services com o parâmetro `spec.externalName`. Esta definição de Service, por exemplo, mapeia o Service `my-service` no namespace `prod` para `my.database.example.com`: ```yaml @@ -136,7 +147,7 @@ spec: type: ExternalName externalName: my.database.example.com ``` -Ao pesquisar o host `my-service.prod.svc.cluster.local`, o cluster DNS Service retorna um registro `CNAME` com o valor `my.database.example.com`. Acessar `my-service` funciona da mesma forma que outros Services, mas com a diferença crucial de que a **redireção acontece no nível de DNS** em vez de via proxy ou forwarding. +Ao consultar o host `my-service.prod.svc.cluster.local`, o cluster DNS Service retorna um registro `CNAME` com o valor `my.database.example.com`. Acessar `my-service` funciona da mesma forma que outros Services, mas com a diferença crucial de que **o redirecionamento acontece no nível do DNS** em vez de via proxying ou forwarding. Liste todos os ExternalNames: ```bash @@ -144,7 +155,7 @@ kubectl get services --all-namespaces | grep ExternalName ``` ### EndpointSlices -EndpointSlices mostram os endereços e portas concretos de backend para os quais um Service atualmente roteia. Elas são especialmente úteis quando um Service não tem selector, quando labels não explicam o caminho do tráfego, ou quando apenas alguns backends estão prontos. +EndpointSlices mostram os endereços e portas concretos de backend para os quais um Service atualmente encaminha. Eles são especialmente úteis quando um Service não tem selector, quando labels não explicam o caminho do tráfego, ou quando apenas alguns backends estão prontos. Liste os EndpointSlices associados aos Services: ```bash @@ -153,17 +164,17 @@ kubectl get endpointslice -n -l kubernetes.io/service-name= -l kubernetes.io/service-name= \ -o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port' ``` -Ao revisar a exposição, compare o seletor do Service com o `targetRef` do EndpointSlice, os endereços do endpoint, as condições de readiness e as portas. Um Service sem selector pode ser combinado com EndpointSlices gerenciados manualmente e encaminhar tráfego para destinos que não são Pods ou inesperados. +Ao revisar a exposição, compare o selector do Service com o `targetRef` do EndpointSlice, os endereços dos endpoints, as condições de readiness e as ports. Um Service sem selector pode ser combinado com EndpointSlices gerenciados manualmente e rotear tráfego para destinos que não são Pod ou inesperados. ### Ingress -Ao contrário de todos os exemplos acima, **Ingress NÃO é um tipo de service**. Em vez disso, ele fica **na frente de multiple services e atua como um “smart router”** ou ponto de entrada para o seu cluster. +Ao contrário de todos os exemplos acima, **Ingress não é um tipo de service**. Em vez disso, ele fica **na frente de múltiplos services e atua como um “smart router”** ou ponto de entrada para o seu cluster. -Você pode fazer muitas coisas diferentes com um Ingress, e existem **muitos tipos de Ingress controllers que têm capacidades diferentes**. +Você pode fazer muitas coisas diferentes com um Ingress, e há **muitos tipos de Ingress controllers que têm capacidades diferentes**. -O Ingress controller padrão do GKE vai provisionar um [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) para você. Isso permitirá fazer roteamento baseado em path e também baseado em subdomínio para backend services. Por exemplo, você pode enviar tudo em foo.yourdomain.com para o service foo, e tudo sob o path yourdomain.com/bar/ para o service bar. +O Ingress controller padrão do GKE vai criar um [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) para você. Isso permitirá fazer tanto roteamento baseado em path quanto em subdomain para backend services. Por exemplo, você pode enviar tudo em foo.yourdomain.com para o service foo, e tudo abaixo do path yourdomain.com/bar/ para o service bar. -O YAML para um objeto Ingress no GKE com um [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) pode parecer assim: +O YAML de um objeto Ingress no GKE com um [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) pode se parecer com isto: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress @@ -201,15 +212,15 @@ Liste todos os ingresses: ```bash kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' ``` -Embora, neste caso, seja melhor obter as informações de cada uma, uma por uma, para lê-las melhor: +Embora, neste caso, seja melhor obter as informações de cada um individualmente para lê-las melhor: ```bash kubectl get ingresses --all-namespaces -o=yaml ``` ### Gateway API -Gateway API é a nova API do Kubernetes para expor Services. Ela separa os objetos Gateway, de propriedade da infraestrutura, dos objetos Route, de propriedade da aplicação, como HTTPRoute. Isso é útil para delegation, mas também significa que a exposição pode ser dividida entre namespaces. +Gateway API é a nova Kubernetes API para expor Services. Ela separa os objetos Gateway, pertencentes à infraestrutura, dos objetos Route, pertencentes à aplicação, como HTTPRoute. Isso é útil para delegation, mas também significa que a exposição pode ser dividida entre namespaces. -List Gateway API exposure objects: +Listar objetos de exposição do Gateway API: ```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 ``` -Verifique os listeners do Gateway, namespaces de rotas permitidos, `parentRefs` da Route, hostnames, filters, backend references e status conditions, como se a route foi aceita. Uma Route aceita por um shared Gateway pode expor um backend mesmo quando nenhum objeto Ingress legado existe. +Verifique os listeners do Gateway, os namespaces de rotas permitidos, `parentRefs` da Route, `hostnames`, filters, backend references e status conditions, como se a route foi accepted. Uma Route accepted por um shared Gateway pode expor um backend mesmo quando não existe nenhum objeto Ingress legacy. ### 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 fec32ca02..f98913c80 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md @@ -2,20 +2,20 @@ {{#include ../../banners/hacktricks-training.md}} -**O autor original desta página é** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(leia o post original dele** [**aqui**](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 +## Arquitetura & Basics -### O que o Kubernetes faz? +### What does Kubernetes do? - Permite executar container/s em um container engine. -- O Schedule permite containers de forma eficiente. +- A schedule permite que containers sejam gerenciados de forma eficiente. - Mantém containers vivos. -- Permite comunicação entre containers. +- Permite comunicações entre containers. - Permite deployment techniques. -- Trata volumes de informação. +- Lida com volumes de informação. -### Architecture +### Arquitetura ![Kubernetes architecture diagram showing control plane components, API server, kubelet, kube-proxy, pods, and worker nodes](https://sickrov.github.io/media/Screenshot-68.jpg) @@ -39,6 +39,8 @@ 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! @@ -105,7 +107,7 @@ $ minikube delete ``` ### Kubectl Basics -**`Kubectl`** é a ferramenta de linha de comando para clusters kubernetes. Ela se comunica com o Api server do processo master para executar ações em kubernetes ou para solicitar dados. +**`Kubectl`** é a ferramenta de linha de comando para clusters kubernetes. Ela se comunica com o Api server do processo master para executar ações em kubernetes ou solicitar dados. ```bash kubectl version #Get client and server version kubectl get pod @@ -138,7 +140,7 @@ kubectl apply -f deployment.yml ``` ### Minikube Dashboard -O dashboard permite ver mais facilmente o que o minikube está executando; você pode encontrar a URL para acessá-lo em: +O dashboard permite ver com mais facilidade o que o minikube está executando, você pode encontrar a URL para acessá-lo em: ``` minikube dashboard --url @@ -153,12 +155,12 @@ http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kube ``` ### YAML configuration files examples -Cada configuration file tem 3 partes: **metadata**, **specification** (o que precisa ser launched), **status** (desired state).\ -Dentro da specification do deployment configuration file você pode encontrar o template definido com uma nova configuration structure definindo a image para run: +Cada arquivo de configuração tem 3 partes: **metadata**, **specification** (o que precisa ser iniciado), **status** (estado desejado).\ +Dentro da specification do arquivo de configuração de deployment, você pode encontrar o template definido com uma nova estrutura de configuração que define a image a ser executada: -**Exemplo de Deployment + Service declarados no mesmo configuration file (from** [**here**](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)**)** -Como um service geralmente está relacionado a um deployment, é possível declarar ambos no mesmo configuration file (o service declarado neste config é acessível apenas internamente): +Como um service normalmente está relacionado a um deployment, é possível declarar ambos no mesmo arquivo de configuração (o service declarado nesta config só é acessível internamente): ```yaml apiVersion: apps/v1 kind: Deployment @@ -207,7 +209,7 @@ targetPort: 27017 ``` **Exemplo de configuração de serviço externo** -Este serviço será acessível externamente (verifique os atributos `nodePort` e `type: LoadBlancer`): +Este serviço estará acessível externamente (verifique os atributos `nodePort` e `type: LoadBlancer`): ```yaml --- apiVersion: v1 @@ -227,9 +229,9 @@ nodePort: 30000 > [!NOTE] > Isso é útil para testes, mas, em produção, você deve ter apenas serviços internos e um Ingress para expor a aplicação. -**Example of Ingress config file** +**Exemplo de arquivo de configuração do Ingress** -Isso exporá a aplicação em `http://dashboard.com`. +Isso irá expor a aplicação em `http://dashboard.com`. ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress @@ -269,7 +271,7 @@ name: mongodb-configmap data: database_url: mongodb-service ``` -Então, dentro de uma **deployment config**, esse endereço pode ser especificado da seguinte forma para que seja carregado dentro do env do pod: +Então, dentro de um **deployment config** esse endereço pode ser especificado da seguinte forma para que ele seja carregado dentro do env do pod: ```yaml [...] spec: @@ -290,18 +292,18 @@ name: mongodb-configmap key: database_url [...] ``` -**Exemplo de configuração de volume** +**Example of volume config** Você pode encontrar diferentes exemplos de arquivos yaml de configuração de storage em [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\ -**Observe que volumes não estão dentro de namespaces** +**Note that volumes aren't inside namespaces** ### Namespaces -Kubernetes suporta **múltiplos clusters virtuais** apoiados pelo mesmo cluster físico. Esses clusters virtuais são chamados de **namespaces**. Eles foram criados para uso em ambientes com muitos users distribuídos entre várias teams ou projects. Para clusters com poucos até dezenas de users, você não precisa criar ou sequer pensar em namespaces. Você só deve começar a usar namespaces para ter um melhor controle e organização de cada parte da aplicação implantada no kubernetes. +Kubernetes suporta **multiple virtual clusters** apoiados pelo mesmo cluster físico. Esses virtual clusters são chamados de **namespaces**. Eles são destinados ao uso em ambientes com muitos usuários distribuídos entre múltiplos teams ou projects. Para clusters com alguns até dezenas de usuários, você não deve precisar criar ou pensar em namespaces. Você só deve começar a usar namespaces para ter um melhor controle e organização de cada parte da application implantada em kubernetes. -Namespaces fornecem um escopo para nomes. Os nomes dos resources precisam ser únicos dentro de um namespace, mas não entre namespaces. Namespaces não podem ser aninhados uns dentro dos outros e **cada** **resource** do Kubernetes só pode estar **em** **um** **namespace**. +Namespaces fornecem um scope para nomes. Os nomes dos resources precisam ser únicos dentro de um namespace, mas não entre namespaces. Namespaces não podem ser aninhados uns dentro dos outros e **cada** **resource** do Kubernetes só pode estar em **um** **namespace**. -Existem 4 namespaces por padrão se você estiver usando minikube: +Existem 4 namespaces por default se você estiver usando minikube: ``` kubectl get namespace NAME STATUS AGE @@ -310,7 +312,7 @@ kube-node-lease Active 1d kube-public Active 1d kube-system Active 1d ``` -- **kube-system**: Não é para o uso dos usuários e você não deve tocar nele. É para processos do master e do kubectl. +- **kube-system**: Não é destinado ao uso dos usuários e você não deve mexer nele. É para processos do master e do kubectl. - **kube-public**: Dados acessíveis publicamente. Contém um configmap que contém informações do cluster - **kube-node-lease**: Determina a disponibilidade de um node - **default**: O namespace que o usuário usará para criar resources @@ -319,14 +321,14 @@ kube-system Active 1d kubectl create namespace my-namespace ``` > [!NOTE] -> Note que a maioria dos recursos do Kubernetes (por exemplo, pods, services, replication controllers e outros) estão em alguns namespaces. No entanto, outros recursos como namespace resources e low-level resources, como nodes e persistenVolumes, não estão em um namespace. Para ver quais recursos do Kubernetes estão e não estão em um namespace: +> Note que a maioria dos recursos do Kubernetes (por exemplo, pods, services, replication controllers e outros) estão em alguns namespaces. No entanto, outros recursos como namespace resources e recursos de baixo nível, como nodes e persistenVolumes, não estão em um namespace. Para ver quais recursos do Kubernetes estão e não estão em um namespace: > > ```bash -> kubectl api-resources --namespaced=true #Em um namespace -> kubectl api-resources --namespaced=false #Não em um namespace +> kubectl api-resources --namespaced=true #In a namespace +> kubectl api-resources --namespaced=false #Not in a namespace > ``` -Você pode salvar o namespace para todos os comandos kubectl subsequentes nesse contexto. +Você pode salvar o namespace para todos os comandos subsequentes do kubectl nesse contexto. ```bash kubectl config set-context --current --namespace= ``` @@ -336,11 +338,11 @@ Helm é o **package manager** para Kubernetes. Ele permite empacotar arquivos YA ``` helm search ``` -Helm também é um template engine que permite gerar arquivos de config com variables: +Helm também é um template engine que permite gerar config files com variables: ## Kubernetes secrets -Um **Secret** é um objeto que **contém dados sensíveis** como uma password, um token ou uma key. Essas informações, de outra forma, poderiam ser colocadas em uma especificação de Pod ou em uma image. Users podem criar Secrets e o system também cria Secrets. O nome de um objeto Secret deve ser um **DNS subdomain name** válido. Leia aqui [a documentação oficial](https://kubernetes.io/docs/concepts/configuration/secret/). +Um **Secret** é um object que **contém dados sensíveis** como uma password, um token ou uma key. Essas informações, de outra forma, poderiam ser colocadas em uma Pod specification ou em uma image. Users podem criar Secrets e o system também cria Secrets. O nome de um Secret object deve ser um **DNS subdomain name** válido. Leia aqui [a documentação oficial](https://kubernetes.io/docs/concepts/configuration/secret/). Secrets podem ser coisas como: @@ -348,9 +350,9 @@ Secrets podem ser coisas como: - OAuth tokens. - Credentials, Passwords (plain text ou b64 + encryption). - Information ou comments. -- Código, strings de connection de database… . +- Database connection code, strings… . -Existem diferentes types de secrets em Kubernetes +Existem diferentes types of secrets no Kubernetes | Builtin Type | Usage | | ----------------------------------- | ----------------------------------------- | @@ -364,13 +366,13 @@ Existem diferentes types de secrets em Kubernetes | bootstrap.kubernetes.io/token | bootstrap token data | > [!NOTE] -> **O type Opaque é o padrão, o típico par key-value definido por users.** +> **O tipo Opaque é o default, o típico par key-value definido pelos users.** -**How secrets works:** +**Como 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) -O seguinte arquivo de configuration define um **secret** chamado `mysecret` com 2 pares key-value `username: YWRtaW4=` e `password: MWYyZDFlMmU2N2Rm`. Ele também define um **pod** chamado `secretpod` que terá `username` e `password` definidos em `mysecret` expostos nas **environment variables** `SECRET_USERNAME` \_\_ e \_\_ `SECRET_PASSWOR`. Ele também irá **mount** o secret `username` dentro de `mysecret` no path `/etc/foo/my-group/my-username` com permissões `0640`. +O seguinte configuration file define um **secret** chamado `mysecret` com 2 pares key-value `username: YWRtaW4=` e `password: MWYyZDFlMmU2N2Rm`. Ele também define uma **pod** chamada `secretpod` que terá `username` e `password` definidos em `mysecret` expostos nas **environment variables** `SECRET_USERNAME` \_\_ e \_\_ `SECRET_PASSWOR`. Ele também vai **mount** o secret `username` dentro de `mysecret` no path `/etc/foo/my-group/my-username` com permissões `0640`. ```yaml:secretpod.yaml apiVersion: v1 kind: Secret @@ -420,13 +422,13 @@ kubectl get pods #Wait until the pod secretpod is running kubectl exec -it secretpod -- bash env | grep SECRET && cat /etc/foo/my-group/my-username && echo ``` -### Secrets em etcd +### Segredos em etcd **etcd** é um **key-value store** consistente e altamente disponível usado como backing store do Kubernetes para todos os dados do cluster. Vamos acessar os secrets armazenados em etcd: ```bash cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd ``` -Você verá certificados, chaves e URLs que estão localizados no FS. Depois de obtê-los, você poderá se conectar ao etcd. +Você verá certs, keys e URLs que estão localizados no FS. Uma vez que os obtenha, você poderá se conectar ao etcd. ```bash #ETCDCTL_API=3 etcdctl --cert --key --cacert endpoint=[] health @@ -440,7 +442,7 @@ ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key ``` **Adicionando encryption ao ETCD** -Por padrão, todos os secrets são **armazenados em plain** text dentro do etcd, a menos que você aplique uma camada de encryption. O exemplo a seguir é baseado em [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) +Por padrão, todos os secrets são **armazenados em texto puro** dentro do etcd, a menos que você aplique uma camada de encryption. O seguinte exemplo é baseado em [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,29 +456,29 @@ keys: secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key - identity: {} ``` -Depois disso, você precisa definir a flag `--encryption-provider-config` no `kube-apiserver` para apontar para a localização do arquivo de config criado. Você pode modificar `/etc/kubernetes/manifest/kube-apiserver.yaml` e adicionar as seguintes linhas: +Depois disso, você precisa definir a flag `--encryption-provider-config` no `kube-apiserver` para apontar para o local do arquivo de configuração criado. Você pode modificar `/etc/kubernetes/manifest/kube-apiserver.yaml` e adicionar as seguintes linhas: ```yaml containers: - command: - kube-apiserver - --encriyption-provider-config=/etc/kubernetes/etcd/ ``` -Role para baixo em the volumeMounts: +Role para baixo em `volumeMounts`: ```yaml - mountPath: /etc/kubernetes/etcd name: etcd readOnly: true ``` -Role até hostPath em volumeMounts: +Role para baixo em volumeMounts até hostPath: ```yaml - hostPath: path: /etc/kubernetes/etcd type: DirectoryOrCreate name: etcd ``` -**Verifying that data is encrypted** +**Verificando que os dados estão encriptados** -Data é criptografado quando escrito no etcd. Depois de reiniciar seu `kube-apiserver`, qualquer secret criado ou atualizado deverá ser criptografado ao ser armazenado. Para verificar, você pode usar o programa de linha de comando `etcdctl` para recuperar o conteúdo do seu secret. +Os dados são encriptados quando gravados em etcd. Após reiniciar o seu `kube-apiserver`, qualquer secret novo criado ou atualizado deve ser encriptado quando armazenado. Para verificar, você pode usar o programa de linha de comando `etcdctl` para recuperar o conteúdo do seu secret. 1. Crie um novo secret chamado `secret1` no namespace `default`: @@ -488,10 +490,10 @@ kubectl create secret generic secret1 -n default --from-literal=mykey=mydata `ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C` -onde `[...]` devem ser os argumentos adicionais para conectar ao servidor etcd. +onde `[...]` deve ser os argumentos adicionais para conectar ao servidor etcd. -3. Verifique se o secret armazenado tem o prefixo `k8s:enc:aescbc:v1:` que indica que o provider `aescbc` criptografou os dados resultantes. -4. Verifique se o secret é descriptografado corretamente quando recuperado via a API: +3. Verifique se o secret armazenado tem o prefixo `k8s:enc:aescbc:v1:` que indica que o provider `aescbc` encriptou os dados resultantes. +4. Verifique se o secret é corretamente desencriptado quando recuperado via a API: ``` kubectl describe secret secret1 -n default @@ -499,18 +501,18 @@ kubectl describe secret secret1 -n default deve corresponder a `mykey: bXlkYXRh`, mydata está encoded, confira [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) para decodificar completamente o secret. -**Since secrets are encrypted on write, performing an update on a secret will encrypt that content:** +**Como os secrets são encriptados na escrita, fazer uma atualização em um secret encriptará esse conteúdo:** ``` kubectl get secrets --all-namespaces -o json | kubectl replace -f - ``` **Dicas finais:** -- Tente não manter secrets no FS, obtenha-os de outros lugares. +- Tente não manter secrets no FS; obtenha-os de outros lugares. - Confira [https://www.vaultproject.io/](https://www.vaultproject.io) para adicionar mais proteção aos seus secrets. - [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) -## Referências +## References {{#ref}} https://sickrov.github.io/ @@ -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 de05e9c77..bb90da935 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 @@ -10,21 +10,21 @@ Ao especificar o security context de um Pod, você pode usar vários atributos. - Ter **runASNonRoot** como **True** - Configurar **runAsUser** -- Se possível, considerar **limitar** **permissões** indicando **seLinuxOptions** e **seccompProfile** -- **NÃO** dar acesso a **privilege** **group** via **runAsGroup** e **supplementaryGroups** +- Se possível, considere **limitar** **permissions** indicando **seLinuxOptions** e **seccompProfile** +- **NÃO** dar acesso de **group** com **privilege** via **runAsGroup** e **supplementaryGroups** | Parameter | Description | -|

fsGroup
integer

|

Um grupo suplementar especial que se aplica a todos os containers em um pod. Alguns tipos de volume permitem que o Kubelet altere a ownership desse volume para que pertença ao pod:
1. O GID de ownership será o FSGroup
2. O bit setgid é definido (novos arquivos criados no volume pertencerão ao FSGroup)
3. Os bits de permissão são combinados com rw-rw---- Se não estiver definido, o Kubelet não modificará a ownership nem as permissões de nenhum volume

| +|

fsGroup
integer

|

Um grupo suplementar especial que se aplica a todos os containers em um pod. Alguns tipos de volume permitem que o Kubelet altere a propriedade desse volume para que ele pertença ao pod:
1. O GID proprietário será o FSGroup
2. O bit setgid é definido (novos arquivos criados no volume pertencerão ao FSGroup)
3. Os bits de permissão são OR'd com rw-rw---- Se não estiver definido, o Kubelet não modificará a propriedade nem as permissões de nenhum volume

| -|

fsGroupChangePolicy
string

| Isso define o comportamento de **alterar a ownership e a permissão do volume** antes de ser exposto dentro do Pod. | +|

fsGroupChangePolicy
string

| Isso define o comportamento de **alterar a propriedade e as permissões do volume** antes de ser exposto dentro do Pod. | |

runAsGroup
integer

| O **GID para executar o entrypoint do processo do container**. Usa o padrão do runtime se não estiver definido. Também pode ser definido em SecurityContext. | |

runAsNonRoot
boolean

| Indica que o container deve executar como um usuário não-root. Se true, o Kubelet validará a imagem em runtime para garantir que ela não execute como UID 0 (root) e falhará ao iniciar o container se isso acontecer. | -|

runAsUser
integer

| O **UID para executar o entrypoint do processo do container**. Por padrão, usa o usuário especificado nos metadados da imagem se não for informado. | -|

seLinuxOptions
SELinuxOptions
More info about seLinux

| O **SELinux context a ser aplicado a todos os containers**. Se não for especificado, o runtime do container alocará um SELinux context aleatório para cada container. | +|

runAsUser
integer

| O **UID para executar o entrypoint do processo do container**. O padrão é o usuário especificado nos metadados da imagem, se não for informado. | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| O **contexto SELinux a ser aplicado a todos os containers**. Se não for especificado, o runtime do container alocará um contexto SELinux aleatório para cada container. | |

seccompProfile
SeccompProfile
More info about Seccomp

| As **opções de seccomp a serem usadas pelos containers** neste pod. | |

supplementalGroups
integer array

| Uma lista de **grupos aplicados ao primeiro processo executado em cada container**, além do GID primário do container. | -|

sysctls
Sysctl array
More info about sysctls

| Sysctls contêm uma lista de **sysctls namespaced usados para o pod**. Pods com sysctls não suportados (pelo runtime do container) podem falhar ao iniciar. | -|

windowsOptions
WindowsSecurityContextOptions

| As configurações específicas de Windows aplicadas a todos os containers. Se não forem especificadas, serão usadas as opções dentro do SecurityContext de um container. | +|

sysctls
Sysctl array
More info about sysctls

| Sysctls mantêm uma lista de **sysctls com namespace usados para o pod**. Pods com sysctls não suportados (pelo container runtime) podem falhar ao iniciar. | +|

windowsOptions
WindowsSecurityContextOptions

| As configurações específicas do Windows aplicadas a todos os containers. Se não forem especificadas, serão usadas as opções dentro do SecurityContext de um container. | ## SecurityContext @@ -37,48 +37,54 @@ Este context é definido dentro das **definições dos containers**. Do ponto de - **privileged** como **False** - Se possível, definir **readOnlyFilesystem** como **True** - Definir **runAsNonRoot** como **True** e definir um **runAsUser** -- Se possível, considerar **limitar** **permissões** indicando **seLinuxOptions** e **seccompProfile** -- **NÃO** dar acesso a **privilege** **group** via **runAsGroup.** +- Se possível, considere **limitar** **permissions** indicando **seLinuxOptions** e **seccompProfile** +- **NÃO** dar acesso de **group** com **privilege** via **runAsGroup.** -Observe que, dos atributos definidos em **SecurityContext e PodSecurityContext**, o valor especificado em **SecurityContext** tem **precedência**. +Observe que, nos atributos definidos em **SecurityContext e PodSecurityContext**, o valor especificado em **SecurityContext** tem **precedência**. -|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** controla se um processo pode **obter mais privilégios** do que seu processo pai. Esse bool controla diretamente se a flag no_new_privs será definida no processo do container. AllowPrivilegeEscalation é sempre true quando o container é executado como **Privileged** ou tem **CAP_SYS_ADMIN** | +|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** controla se um processo pode **obter mais privilégios** do que seu processo pai. Este bool controla diretamente se a flag no_new_privs será definida no processo do container. AllowPrivilegeEscalation é sempre true quando o container é executado como **Privileged** ou possui **CAP_SYS_ADMIN** | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|

capabilities
Capabilities
More info about Capabilities

| As **capabilities para adicionar/remover ao executar containers**. O padrão é o conjunto default de capabilities. | -|

privileged
boolean

| Executa o container em modo privilegiado. Processos em containers privilegiados são essencialmente **equivalentes a root no host**. O padrão é false. | -|

procMount
string

| procMount indica o **tipo de proc mount a ser usado para os containers**. O padrão é DefaultProcMount, que usa os defaults do runtime do container para caminhos readonly e caminhos mascarados. | -|

readOnlyRootFilesystem
boolean

| Se este **container tem um root filesystem somente leitura**. O padrão é false. | +|

capabilities
Capabilities
More info about Capabilities

| As **capabilities a adicionar/remover ao executar containers**. O padrão é o conjunto padrão de capabilities. | +|

privileged
boolean

| Executa o container em modo privileged. Processos em containers privileged são, essencialmente, **equivalentes a root no host**. O padrão é false. | +|

procMount
string

| procMount indica o **tipo de proc mount a ser usado pelos containers**. O padrão é DefaultProcMount, que usa os padrões do container runtime para caminhos somente leitura e caminhos mascarados. | +|

readOnlyRootFilesystem
boolean

| Se este **container tem um filesystem raiz somente leitura**. O padrão é false. | |

runAsGroup
integer

| O **GID para executar o entrypoint** do processo do container. Usa o padrão do runtime se não estiver definido. | |

runAsNonRoot
boolean

| Indica que o container deve **executar como um usuário não-root**. Se true, o Kubelet validará a imagem em runtime para garantir que ela não execute como UID 0 (root) e falhará ao iniciar o container se isso acontecer. | -|

runAsUser
integer

| O **UID para executar o entrypoint** do processo do container. Por padrão, usa o usuário especificado nos metadados da imagem se não for informado. | -|

seLinuxOptions
SELinuxOptions
More info about seLinux

| O **SELinux context a ser aplicado ao container**. Se não for especificado, o runtime do container alocará um SELinux context aleatório para cada container. | +|

runAsUser
integer

| O **UID para executar o entrypoint** do processo do container. O padrão é o usuário especificado nos metadados da imagem, se não for informado. | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| O **contexto SELinux a ser aplicado ao container**. Se não for especificado, o runtime do container alocará um contexto SELinux aleatório para cada container. | |

seccompProfile
SeccompProfile

| As **opções de seccomp** a serem usadas por este container. | -|

windowsOptions
WindowsSecurityContextOptions

| As **configurações específicas de Windows** aplicadas a todos os containers. | +|

windowsOptions
WindowsSecurityContextOptions

| As **configurações específicas do Windows** aplicadas a todos os containers. | ## Practical workload review checklist -Ao revisar um Pod ou template de workload, inspecione tanto `spec.securityContext` quanto cada `securityContext` em nível de container dentro de `containers`, `initContainers` e `ephemeralContainers`. Campos em nível de container podem sobrescrever os defaults do pod, então um default do pod que parece seguro não garante que todo container seja seguro. +Ao revisar um Pod ou template de workload, inspecione tanto `spec.securityContext` quanto cada `securityContext` no nível do container em `containers`, `initContainers` e `ephemeralContainers`. Campos no nível do container podem sobrescrever os padrões do pod, então um pod aparentemente seguro não garante que todo container seja seguro. Combinações de alto risco para priorizar: -- `privileged: true`, especialmente com `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports ou mounts de socket do runtime. +- `privileged: true`, especialmente com `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports ou montagens de socket do runtime. - Capabilities adicionadas como `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` ou `DAC_OVERRIDE`. -- `allowPrivilegeEscalation: true` ou não definido em containers que podem executar código controlado por atacante. +- `allowPrivilegeEscalation: true` ou não definido em containers que podem executar código controlado por attacker. - `seccompProfile: Unconfined`, `procMount: Unmasked` ou perfis de runtime ausentes em workloads sensíveis. -- root filesystems graváveis ou mounts de volume graváveis amplos em workloads que processam entrada não confiável. -- Falta de requests e limits de CPU, memória ou ephemeral-storage em namespaces multi-tenant. +- Root filesystems graváveis ou montagens de volumes amplamente graváveis em workloads que processam input não confiável. +- Ausência de requests e limits de CPU, memory ou ephemeral-storage em namespaces multi-tenant. +- Ausência de budgets de `spec.resources` no nível do pod ou budgets irreais, e principals com `patch` ou `update` no subrecurso `resize` do Pod, porque clusters suportados podem alterar o estado desejado de CPU e memory em execução sem recriar o Pod. -Para a maioria dos application workloads, uma boa baseline é executar com um UID não-root, definir `runAsNonRoot: true`, definir `allowPrivilegeEscalation: false`, remover todas as capabilities e adicionar de volta apenas as mínimas necessárias, usar `seccompProfile: RuntimeDefault`, preferir um root filesystem somente leitura e evitar host namespaces, mounts de hostPath e modo privilegiado. +Os controles de recursos não fazem parte de `securityContext`, mas revise-os no mesmo passe do workload porque eles definem o limite de disponibilidade. O Kubernetes moderno pode definir budgets de CPU, memory e hugepage no nível do Pod em `spec.resources` além de `resources` no nível do container. Um Pod com sidecars pode ser limitado por um envelope agregado do Pod mesmo quando um container não tem limites individuais, enquanto o armazenamento efêmero local ainda precisa de limites separados de `ephemeral-storage`, `emptyDir.sizeLimit`, LimitRanges e ResourceQuotas. Compare também os recursos desejados no Pod spec com `status.containerStatuses[].resources` após uma solicitação de resize in-place; um resize falho ou pendente pode deixar o valor solicitado em `spec` enquanto o kubelet mantém a alocação anterior em runtime e reporta uma condição `PodResizePending`. -Em nível de cluster, use labels de namespace do [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) para लागूer os Kubernetes [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) quando possível. Use `restricted` para namespaces que suportem isso, pelo menos `baseline` para namespaces comuns de aplicação e mantenha exceções privileged estreitas, documentadas e isoladas em namespaces de plataforma ou node pools confiáveis. +Para a maioria dos workloads de aplicação, uma base boa é executar como um UID não-root, definir `runAsNonRoot: true`, definir `allowPrivilegeEscalation: false`, remover todas as capabilities e adicionar de volta apenas as mínimas necessárias, usar `seccompProfile: RuntimeDefault`, preferir um root filesystem somente leitura e evitar host namespaces, montagens `hostPath` e modo privileged. + +No nível do cluster, use labels de namespace do [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) para लागूm impor os [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) do Kubernetes sempre que possível. Use `restricted` para namespaces que suportem isso, pelo menos `baseline` para namespaces comuns de aplicação, e mantenha exceções privileged pequenas, documentadas e isoladas em namespaces de plataforma confiáveis ou 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}}