本文档采用自动化机器翻译技术翻译。 尽管我们力求提供准确的译文,但不对翻译内容的完整性、准确性或可靠性作出任何保证。 若出现任何内容不一致情况,请以原始 英文 版本为准,且原始英文版本为权威文本。

这是尚未发布的文档。 Admission Controller 1.34-dev.

PodSecurityPolicy 迁移

适用于 Kubernetes ≥ v1.25。 PodSecurityPolicy(PSP)已被移除。现在您可以在您的 Kubernetes 集群中使用 SUSE Security Admission Controller 进行准入控制。

Admission Controller 拥有单独的策略,以实现与单体 PSP 配置相同的目标。每个 Admission Controller 策略定义在 PSP 的规范中作为不同的配置部分。PSP 配置字段与其各自的 Admission Controller 策略的映射关系见下方 映射表

使用 Admission Controller,操作员可以在其集群中对策略配置进行细粒度控制。

使用 Admission Controller 实例,您可以部署策略以替代 PodSecurityPolicy 对象。我们在这个例子中考虑这些规则:

  • 禁用特权升级的 PSP

  • 特权容器

  • 阻止以 root 身份运行的 Pod

  • 强制特定用户组

  • 阻止主机名称空间

  • 允许一个 Pod 仅使用端口 443

此 PSP 的 YAML 定义为:

PSP YAML 定义
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

Admission Controller 替换 PSP

现在我们将创建 Admission Controller 策略以实现相同的目标。 您通过单独的 Admission Controller 策略来强制执行每条规则。 因此,在这个例子中,您需要为以下每项分别创建一个策略:

  • 特权升级

  • 用户和组配置

  • 主机名称空间

  • 特权容器配置。

阻止容器特权升级

您可以按如下所示部署策略:

用于策略部署的 kubectl 命令
$ 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

在该命令中,我们已指定 default_allow_privilege_escalationfalse。此策略限制尝试以比父容器更高特权运行的 Pods。

尝试提升特权的 kubectl 输出
$ 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

用户和组配置

现在,为了强制执行用户和组配置,您可以使用 user-group-psp 策略

kubectl 命令以使用 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

您应该使用`mutation: true`配置策略。这是必需的,因为当用户未定义它们时,策略将添加https://kubernetes.io/docs/concepts/security/pod-security-policy/#users-and-groups[supplementalGroups]。

因此,现在用户无法以 root 身份部署 Pod:

示例输出,其中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
示例输出,其中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)

下面的示例显示了添加一个https://kubernetes.io/docs/concepts/security/pod-security-policy/#users-and-groups[supplemental group],尽管它并未被我们定义。

示例添加一个补充组
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
  ]
}

特权容器配置

您需要替换阻止特权容器的旧PSP配置。部署https://github.com/kubewarden/pod-privileged-policy[pod-privileged policy]是必要的。此策略不需要任何设置。一旦运行,它将阻止特权 Pod。

应用pod-privileged-policy
$ 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

为了测试该策略,我们可以尝试运行一个启用特权配置的pod:

启用特权配置的pod运行
$ 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

主机名称空间配置

为了完成 PSP 迁移练习,您需要禁用主机名称空间共享。为此,我们将使用https://github.com/kubewarden/host-namespaces-psp-policy[host-namespace-psp policy]。它允许集群管理员单独阻止 IPC、PID 和网络名称空间。它还设置了 Pod 可以在主机 IP 上开放的端口。

禁用名称空间共享并设置端口
$ 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

我们可以验证该策略。 该 Pod 不应能够共享主机名称空间:

阻止名称空间示例
$ 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

在这个最后的示例中,Pod 只能暴露端口 443。 如果在 hostPorts 中配置了其他端口,则应发生错误。

尝试在 hostPorts 中使用端口 80
$ 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

PSP 迁移脚本

Admission Controller团队开发了一个用于PSP迁移的脚本。它使用来自https://github.com/appvia/psp-migration[AppVia]的迁移工具。AppVia 工具读取 PSP YAML 配置。它会生成相应的策略。它为 Admission Controller 和其他策略引擎执行此操作。

AppVia 迁移工具不在 Kubewarden 维护者的控制之下。 这意味着它可能会生成过时的 Admission Controller 策略。请谨慎使用。我们需要一个AppVia的拉取请求,目前正在进行中。 如果需要更多信息,请与我们联系。

该脚本可在Admission Controllerhttps://github.com/kubewarden/utils/blob/main/scripts/psp-to-kubewarden[utils]储存库中获得。它将 AppVia 迁移工具下载到工作目录中以供使用。它处理在 kubectl 默认上下文中定义的 PSP。然后它在标准输出上打印 Kubewarden 策略定义。用户可以将内容重定向到文件或直接到`kubectl`。

该脚本仅在 Linux x86_64 机器上工作。

让我们看一个例子。在具有 PSP 的集群中:

  • 阻止访问主机名称空间

  • 阻止特权容器

  • 不允许特权升级

  • 丢弃容器能力

  • 列出允许的卷类型

  • 定义允许使用的用户和组

  • 控制应用于卷的补充组

  • 强制容器在只读根文件系统中运行

以下 YAML 可以使用。

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 策略可以使用以下命令直接应用于集群:

$ ./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

如果用户想在应用之前检查策略,可以将内容重定向到文件或直接在控制台中查看

要存储生成的策略并查看它们:

./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

策略名称由 PSP 迁移工具生成。 您可能想将名称更改为更有意义的名称。