Este documento foi traduzido usando tecnologia de tradução automática de máquina. Sempre trabalhamos para apresentar traduções precisas, mas não oferecemos nenhuma garantia em relação à integridade, precisão ou confiabilidade do conteúdo traduzido. Em caso de qualquer discrepância, a versão original em inglês prevalecerá e constituirá o texto official.

Esta é uma documentação não divulgada para Admission Controller 1.34-dev.

Migração de PodSecurityPolicy

For Kubernetes ≥ v1.25. PodSecurityPolicy (PSP) foi removido. Agora você pode usar SUSE Security Admission Controller para controle de admissão em seus clusters Kubernetes.

Admission Controller possui políticas separadas para alcançar o mesmo objetivo que uma configuração monolítica de PSP. Cada definição de política Admission Controller funciona como uma seção de configuração diferente na especificação de um PSP. O mapeamento dos campos de configuração do PSP para suas respectivas políticas Admission Controller está na tabela de mapeamento abaixo.

Com Admission Controller, os operadores têm controle granular da configuração de políticas em seus clusters.

Com uma instância de Admission Controller, você pode implantar políticas para substituir o objeto PodSecurityPolicy. Consideramos essas regras neste exemplo:

  • uma PSP desabilitando a elevação de privilégios

  • containers privilegiados → contêineres privilegiados

  • bloqueando pods executando como root

  • forçando um grupo de usuários específico

  • bloqueando namespaces de host

  • permitindo que um pod use apenas a porta 443

A definição YAML deste PSP é:

Definição YAML do PSP
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  allowPrivilegeEscalation: false
  runAsUser:
    rule: MustRunAsNonRoot
  supplementalGroups:
    rule: MustRunAs
    ranges:
      - min: 1000
        max: 65535
  privileged: false
  hostNetwork: false
  hostIPC: false
  hostPID: false
  hostPorts:
    - min: 443
      max: 443

Substituições de Admission Controller para PSP

Agora criaremos Admission Controller políticas para alcançar o mesmo objetivo. Você aplica cada regra com uma política Admission Controller separada. Assim, neste exemplo, você precisa de uma política separada para a aplicação de cada um dos seguintes:

  • elevação de privilégios

  • configuração de usuário e grupo

  • namespaces de host

  • configuração de contêiner privilegiado.

Bloqueando a elevação de privilégios do contêiner

Você pode implantar uma política conforme mostrado abaixo:

comando kubectl para implantação de política
$ kubectl apply -f - <<EOF
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-allow-privilege-escalation
spec:
  module: ghcr.io/kubewarden/policies/allow-privilege-escalation-psp:v0.2.6
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    default_allow_privilege_escalation: false
EOF

Nesse comando, especificamos default_allow_privilege_escalation para ser false. Esta política restringe pods que tentam executar com mais privilégios do que o contêiner pai.

Saída do kubectl que tenta elevar privilégios
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      allowPrivilegeEscalation: true
  - name: sidecar
    image: sidecar
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-allow-privilege-escalation.kubewarden.admission" denied the request: one of the containers has privilege escalation enabled

Configuração de usuário e grupo

Agora, para aplicar a configuração de usuário e grupo, você pode usar a política user-group-psp policy.

Comando kubectl para usar a política user-group-psp-policy
$ kubectl apply -f - <<EOF
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-user-group
spec:
  module: ghcr.io/kubewarden/policies/user-group-psp:v0.4.9
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: true
  settings:
    run_as_user:
      rule: MustRunAsNonRoot
    supplemental_groups:
      rule: MustRunAs
      ranges:
        - min: 1000
          max: 65535
EOF

Você deve configurar a política com mutation: true. É necessário porque a política irá adicionar supplementalGroups quando o usuário não os definir.

Portanto, agora os usuários não podem implantar pods executando como root:

Exemplo de saída onde runAsNonRoot: false
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      runAsNonRoot: false
      runAsUser: 0
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-user-group-fb836.kubewarden.admission" denied the request: RunAsNonRoot should be set to true
Exemplo de saída onde runAsUser: 0
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      runAsNonRoot: true
      runAsUser: 0
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-user-group-fb836.kubewarden.admission" denied the request: Invalid user ID: cannot run container with root ID (0)

Este exemplo abaixo mostra a adição de um grupo suplementar, apesar de não ter sido definido por nós.

Exemplo de adição de um grupo suplementar
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
EOF
pod/nginx created
$ kubectl get pods -o json nginx | jq ".spec.securityContext"
{
  "supplementalGroups": [
    10000
  ]
}

Configuração de contêiner privilegiado

Você precisa substituir a configuração antiga do PSP que bloqueia contêineres privilegiados. É necessário implantar a política-pod-privilegiada. Esta política não precisa de nenhuma configuração. Uma vez em execução, ela bloqueará pods privilegiados.

Aplicando a política-pod-privilegiada
$ kubectl apply -f - <<EOF
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-privileged
spec:
  module: ghcr.io/kubewarden/policies/pod-privileged:v0.2.7
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings: null
EOF

Para testar a política, podemos tentar executar um pod com a configuração privilegiada habilitada:

Pod executado com a configuração privilegiada habilitada
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    securityContext:
      privileged: true
  - name: sleeping-sidecar
    image: alpine
    command: ["sleep", "1h"]
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-privileged.kubewarden.admission" denied the request: Privileged container is not allowed

Configuração de namespace do host

Para finalizar o exercício de migração do PSP, você precisa desativar o compartilhamento de namespace do host. Para isso, usaremos a host-namespace-psp política. Ela permite que o administrador do cluster bloqueie IPC, PID e namespaces de rede individualmente. Ela também define as portas que os pods podem abrir no IP do host.

Desabilitando o compartilhamento de namespace e definindo portas
$ kubectl apply -f - <<EOF
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-hostnamespaces
spec:
  module: ghcr.io/kubewarden/policies/host-namespaces-psp:v0.1.6
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allow_host_ipc: false
    allow_host_pid: false
    allow_host_ports:
      - min: 443
        max: 443
    allow_host_network: false
EOF

Podemos validar a política. O pod não deve ser capaz de compartilhar namespaces do host:

Exemplo de bloqueio de namespace
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostIPC: true
  hostNetwork: false
  hostPID: false
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  - name: sleeping-sidecar
    image: alpine
    command: ["sleep", "1h"]
EOF

Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-hostnamespaces.kubewarden.admission" denied the request: Pod has IPC enabled, but this is not allowed
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostIPC: false
  hostNetwork: true
  hostPID: false
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  - name: sleeping-sidecar
    image: alpine
    command: ["sleep", "1h"]
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-hostnamespaces.kubewarden.admission" denied the request: Pod has host network enabled, but this is not allowed
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostIPC: false
  hostNetwork: false
  hostPID: true
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  - name: sleeping-sidecar
    image: alpine
    command: ["sleep", "1h"]
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-hostnamespaces.kubewarden.admission" denied the request: Pod has host PID enabled, but this is not allowed

Neste último exemplo, o pod deve ser capaz de expor apenas a porta 443. Se outras portas estiverem configuradas em hostPorts, então um erro deve ocorrer.

Tentando usar a porta 80 em hostPorts
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
      - containerPort: 80
        hostPort: 80
  - name: sleeping-sidecar
    image: alpine
    command: ["sleep", "1h"]
EOF
Error from server: error when creating "STDIN": admission webhook "clusterwide-psp-hostnamespaces.kubewarden.admission" denied the request: Pod is using unallowed host ports in containers

Script de migração do PSP

A equipe Admission Controller desenvolveu um script para migração do PSP. Ele utiliza a ferramenta de migração do AppVia. A ferramenta AppVia lê uma configuração YAML do PSP. Em seguida, gera as políticas correspondentes. Faz isso para Admission Controller e outros mecanismos de política.

A ferramenta de migração AppVia está fora do controle dos mantenedores do Kubewarden. Isso significa que é possível que ela gere políticas Admission Controller desatualizadas. Use com cautela. Precisamos de um pull request para o AppVia, para o qual o trabalho está em andamento. Entre em contato conosco para mais informações, se necessário.

O script está disponível no repositório Admission Controllerhttps://github.com/kubewarden/utils/blob/main/scripts/psp-to-kubewarden[utils]. Ele baixa a ferramenta de migração AppVia para o diretório de trabalho para uso. Ele processa os PSPs definidos no contexto padrão kubectl. Em seguida, imprime as definições das políticas do Kubewarden na saída padrão. Os usuários podem redirecionar o conteúdo para um arquivo ou para kubectl diretamente.

Este script funciona apenas em máquinas Linux x86_64.

Vamos analisar um exemplo. Em um cluster com o PSP:

  • bloqueando o acesso aos namespaces de host

  • bloqueando contêineres privilegiados

  • não permitindo a elevação de privilégios

  • removendo as capacidades do contêiner

  • listando os tipos de volume permitidos

  • definindo os usuários e grupos permitidos a serem utilizados

  • controlando o grupo suplementar aplicado aos volumes

  • forçando os contêineres a rodar em um sistema de arquivos raiz somente leitura

O seguinte YAML pode ser utilizado.

A configuração do PSP
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  hostNetwork: false
  hostIPC: false
  hostPID: false
  hostPorts:
    - min: 80
      max: 8080
  privileged: false
  # Required to prevent escalations to root.
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  # Allow core volume types.
  volumes:
    - "configMap"
    - "emptyDir"
    - "projected"
    - "secret"
    - "downwardAPI"
    # Assume that ephemeral CSI drivers & persistentVolumes set up by the cluster admin are safe to use.
    - "csi"
    - "persistentVolumeClaim"
    - "ephemeral"
  runAsUser:
    # Require the container to run without root privileges.
    rule: "MustRunAsNonRoot"
  seLinux:
    # This policy assumes the nodes are using AppArmor rather than SELinux.
    rule: "RunAsAny"
  supplementalGroups:
    rule: "MustRunAs"
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  fsGroup:
    rule: "MustRunAs"
    ranges:
      # Forbid adding the root group.
      - min: 1
        max: 65535
  readOnlyRootFilesystem: true

Admission Controller políticas podem ser aplicadas diretamente a um cluster usando o seguinte comando:

$ ./psp-to-kubewarden | kubectl apply -f -
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
clusteradmissionpolicy.policies.kubewarden.io/psp-privileged-82bf2 created
clusteradmissionpolicy.policies.kubewarden.io/psp-readonlyrootfilesystem-b4a55 created
clusteradmissionpolicy.policies.kubewarden.io/psp-hostnamespaces-a25a2 created
clusteradmissionpolicy.policies.kubewarden.io/psp-volumes-cee05 created
clusteradmissionpolicy.policies.kubewarden.io/psp-capabilities-34d8e created
clusteradmissionpolicy.policies.kubewarden.io/psp-usergroup-878b0 created
clusteradmissionpolicy.policies.kubewarden.io/psp-fsgroup-3b08e created
clusteradmissionpolicy.policies.kubewarden.io/psp-defaultallowprivilegeescalation-b7e87 created

Se os usuários quiserem inspecionar as políticas antes de aplicar, é possível redirecionar o conteúdo para um arquivo ou revisá-lo diretamente no console

Para armazenar as políticas geradas e visualizá-las:

./psp-to-kubewarden > policies.yaml && cat policies.yaml
$ ./psp-to-kubewarden > policies.yaml
$ cat policies.yaml
---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-privileged-eebb9
spec:
  module: registry://ghcr.io/kubewarden/policies/pod-privileged:v0.2.7
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings: null

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-readonlyrootfilesystem-34d7c
spec:
  module: registry://ghcr.io/kubewarden/policies/readonly-root-filesystem-psp:v0.1.6
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings: null

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-hostnamespaces-41314
spec:
  module: registry://ghcr.io/kubewarden/policies/host-namespaces-psp:v0.1.6
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allow_host_ipc: false
    allow_host_pid: false
    allow_host_ports:
      - max: 8080
        min: 80
    allow_host_network: false

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-volumes-2fd34
spec:
  module: registry://ghcr.io/kubewarden/policies/volumes-psp:v0.1.11
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowedTypes:
      - configMap
      - emptyDir
      - projected
      - secret
      - downwardAPI
      - csi
      - persistentVolumeClaim
      - ephemeral

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-capabilities-340fe
spec:
  module: registry://ghcr.io/kubewarden/policies/capabilities-psp:v0.1.13
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    allowed_capabilities: []
    required_drop_capabilities:
      - ALL

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-usergroup-19f7a
spec:
  module: registry://ghcr.io/kubewarden/policies/user-group-psp:v0.4.9
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    run_as_user:
      rule: MustRunAsNonRoot
    supplemental_groups:
      ranges:
        - max: 65535
          min: 1
      rule: MustRunAs

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-fsgroup-52337
spec:
  module: registry://ghcr.io/kubewarden/policies/allowed-fsgroups-psp:v0.1.10
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    ranges:
      - max: 65535
        min: 1
    rule: MustRunAs

---
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
  name: psp-defaultallowprivilegeescalation-6f11b
spec:
  module: registry://ghcr.io/kubewarden/policies/allow-privilege-escalation-psp:v0.2.6
  rules:
    - apiGroups:
        - ""
      apiVersions:
        - v1
      resources:
        - pods
      operations:
        - CREATE
        - UPDATE
  mutating: false
  settings:
    default_allow_privilege_escalation: false

Os nomes das políticas são gerados pela ferramenta de migração do PSP. Você pode querer mudar o nome para algo mais significativo.