From 7f917e75dfc263571f794633be82fa0334a699d3 Mon Sep 17 00:00:00 2001 From: Qiming Teng Date: Thu, 6 Aug 2020 16:50:45 +0800 Subject: [PATCH] [zh] Resync/rework PSP concept The English version reads nothing the same .. and the existing translation failed to include English source. --- .../concepts/policy/pod-security-policy.md | 1256 +++++++++++++++-- 1 file changed, 1128 insertions(+), 128 deletions(-) diff --git a/content/zh/docs/concepts/policy/pod-security-policy.md b/content/zh/docs/concepts/policy/pod-security-policy.md index 1573ff7af2..3c24f027b0 100644 --- a/content/zh/docs/concepts/policy/pod-security-policy.md +++ b/content/zh/docs/concepts/policy/pod-security-policy.md @@ -1,43 +1,81 @@ --- -approvers: -- pweil- title: Pod 安全策略 +content_type: concept +weight: 20 --- + +{{< feature-state state="beta" >}} -`PodSecurityPolicy` 类型的对象能够控制,是否可以向 Pod 发送请求,该 Pod 能够影响被应用到 Pod 和容器的 `SecurityContext`。 -查看 [Pod 安全策略建议](https://git.k8s.io/community/contributors/design-proposals/security-context-constraints.md) 获取更多信息。 - -{{< toc >}} - + +Pod 安全策略使得对 Pod 创建和更新进行细粒度的权限控制成为可能。 + ## 什么是 Pod 安全策略? -_Pod 安全策略_ 是集群级别的资源,它能够控制 Pod 运行的行为,以及它具有访问什么的能力。 -`PodSecurityPolicy` 对象定义了一组条件,指示 Pod 必须按系统所能接受的顺序运行。 -它们允许管理员控制如下方面: - - - -| 控制面 | 字段名称 | -| ------------------------------------------------------------- | --------------------------------- | -| 已授权容器的运行 | `privileged` | -| 为容器添加默认的一组能力 | `defaultAddCapabilities` | -| 为容器去掉某些能力 | `requiredDropCapabilities` | -| 容器能够请求添加某些能力 | `allowedCapabilities` | -| 控制卷类型的使用 | [`volumes`](#controlling-volumes) | -| 主机网络的使用 | [`hostNetwork`](#host-network) | -| 主机端口的使用 | `hostPorts` | -| 主机 PID namespace 的使用 | `hostPID` | -| 主机 IPC namespace 的使用 | `hostIPC` | -| 主机路径的使用 | [`allowedHostPaths`](#allowed-host-paths) | -| 容器的 SELinux 上下文 | [`seLinux`](#selinux) | -| 用户 ID | [`runAsUser`](#runasuser) | -| 配置允许的补充组 | [`supplementalGroups`](#supplementalgroups) | -| 分配拥有 Pod 数据卷的 FSGroup | [`fsGroup`](#fsgroup) | -| 必须使用一个只读的 root 文件系统 | `readOnlyRootFilesystem` | +_Pod 安全策略(Pod Security Policy)_ 是集群级别的资源,它能够控制 Pod 规约 +中与安全性相关的各个方面。 +[PodSecurityPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy) +对象定义了一组 Pod 运行时必须遵循的条件及相关字段的默认值,只有 Pod 满足这些条件 +才会被系统接受。 +Pod 安全策略允许管理员控制如下方面: + +| 控制的角度 | 字段名称 | +| ----------------------------------- | --------------------------------- | +| 运行特权容器 | [`privileged`](#privileged) | +| 使用宿主名字空间 | [`hostPID`、`hostIPC`](#host-namespaces) | +| 使用宿主的网络和端口 | [`hostNetwork`, `hostPorts`](#host-namespaces) | +| 控制卷类型的使用 | [`volumes`](#volumes-and-file-systems) | +| 使用宿主文件系统 | [`allowedHostPaths`](#volumes-and-file-systems) | +| 允许使用特定的 FlexVolume 驱动 | [`allowedFlexVolumes`](#flexvolume-drivers) | +| 分配拥有 Pod 卷的 FSGroup 账号 | [`fsGroup`](#volumes-and-file-systems) | +| 以只读方式访问根文件系统 | [`readOnlyRootFilesystem`](#volumes-and-file-systems) | +| 设置容器的用户和组 ID | [`runAsUser`, `runAsGroup`, `supplementalGroups`](#users-and-groups) | +| 限制 roo 账号特权级提升 | [`allowPrivilegeEscalation`, `defaultAllowPrivilegeEscalation`](#privilege-escalation) | +| Linux 权能字(Capabilities) | [`defaultAddCapabilities`, `requiredDropCapabilities`, `allowedCapabilities`](#capabilities) | +| 设置容器的 SELinux 上下文 | [`seLinux`](#selinux) | +| 指定容器可以挂载的 proc 类型 | [`allowedProcMountTypes`](#allowedprocmounttypes) | +| 指定容器使用的 AppArmor 模版 | [annotations](#apparmor) | +| 指定容器使用的 seccomp 模版 | [annotations](#seccomp) | +| 指定容器使用的 sysctl 模版 | [`forbiddenSysctls`,`allowedUnsafeSysctls`](#sysctl) | _Pod 安全策略_ 由设置和策略组成,它们能够控制 Pod 访问的安全特征。这些设置分为如下三类: @@ -46,180 +84,1142 @@ _Pod 安全策略_ 由设置和策略组成,它们能够控制 Pod 访问的 - *基于被允许的值集合控制* :这种类型的字段会与这组值进行对比,以确认值被允许。 - *基于策略控制* :设置项通过一种策略提供的机制来生成该值,这种机制能够确保指定的值落在被允许的这组值中。 + +## 启用 Pod 安全策略 -### RunAsUser +Pod 安全策略实现为一种可选(但是建议启用)的 +[准入控制器](/zh/docs/reference/access-authn-authz/admission-controllers/#podsecuritypolicy)。 +[启用了准入控制器](/zh/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-control-plug-in) +即可强制实施 Pod 安全策略,不过如果没有授权认可策略之前即启用 +准入控制器 **将导致集群中无法创建任何 Pod**。 + +由于 Pod 安全策略 API(`policy/v1beta1/podsecuritypolicy`)是独立于准入控制器 +来启用的,对于现有集群而言,建议在启用准入控制器之前先添加策略并对其授权。 + +## 授权策略 {#authorizing-policies} +PodSecurityPolicy 资源被创建时,并不执行任何操作。为了使用该资源,需要对 +发出请求的用户或者目标 Pod 的 +[服务账号](/zh/docs/tasks/configure-pod-container/configure-service-account/) +授权,通过允许其对策略执行 `use` 动词允许其使用该策略。 + +大多数 Kubernetes Pod 不是由用户直接创建的。相反,这些 Pod 是由 +[Deployment](/zh/docs/concepts/workloads/controllers/deployment/)、 +[ReplicaSet](/zh/docs/concepts/workloads/controllers/replicaset/) +或者经由控制器管理器模版化的控制器创建。 +赋予控制器访问策略的权限意味着对应控制器所创建的 *所有* Pod 都可访问策略。 +因此,对策略进行授权的优先方案是为 Pod 的服务账号授予访问权限 +(参见[示例](#run-another-pod))。 -### SELinux + +### 通过 RBAC 授权 {#via-rbac} -### SupplementalGroups +[RBAC](/zh/docs/reference/access-authn-authz/rbac/) 是一种标准的 Kubernetes +鉴权模式,可以很容易地用来授权策略访问。 -- *MustRunAs* - 至少需要指定一个范围。默认使用第一个范围的最小值。验证所有范围的值。 -- *RunAsAny* - 没有提供默认值。允许任意指定的 `supplementalGroups` ID。 +首先,某 `Role` 或 `ClusterRole` 需要获得使用 `use` 访问目标策略的权限。 +访问授权的规则看起来像这样: +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: +rules: +- apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - <要授权的策略列表> +``` + +接下来将该 `Role`(或 `ClusterRole`)绑定到授权的用户: -- *MustRunAs* - 至少需要指定一个范围。默认使用第一个范围的最小值。验证在第一个范围内的第一个 ID。 -- *RunAsAny* - 没有提供默认值。允许任意指定的 `fsGroup` ID。 +```yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: <绑定名称> +roleRef: + kind: ClusterRole + name: <角色名称> + apiGroup: rbac.authorization.k8s.io +subjects: +# 授权特定的服务账号 +- kind: ServiceAccount + name: <要授权的服务账号名称> + namespace: +# 授权特定的用户(不建议这样操作) +- kind: User + apiGroup: rbac.authorization.k8s.io + name: <要授权的用户名> +``` + +如果使用的是 `RoleBinding`(而不是 `ClusterRoleBinding`),授权仅限于 +与该 `RoleBinding` 处于同一名字空间中的 Pods。 +可以考虑将这种授权模式和系统组结合,对名字空间中的所有 Pod 授予访问权限。 +```yaml +# 授权该某名字空间中所有服务账号 +- kind: Group + apiGroup: rbac.authorization.k8s.io + name: system:serviceaccounts +# 或者与之等价,授权给某名字空间中所有被认证过的用户 +- kind: Group + apiGroup: rbac.authorization.k8s.io + name: system:authenticated +``` -### 控制卷 + +参阅[角色绑定示例](/zh/docs/reference/access-authn-authz/rbac#role-binding-examples) +查看 RBAC 绑定的更多实例。 +参阅[下文](#example),查看对 PodSecurityPolicy 进行授权的完整示例。 -通过设置 PSP 卷字段,能够控制具体卷类型的使用。当创建一个卷的时候,与该字段相关的已定义卷可以允许设置如下值: + +### 故障排查 {#troubleshooting} +- [控制器管理器组件](/zh/docs/reference/command-line-tools-reference/kube-controller-manager/) + 必须运行在 + [安全的 API 端口](/zh/docs/reference/access-authn-authz/controlling-access/), + 并且一定不能具有超级用户权限。 + 否则其请求会绕过身份认证和鉴权模块控制,从而导致所有 PodSecurityPolicy 对象 + 都被启用,用户亦能创建特权容器。 + 关于配置控制器管理器鉴权相关的详细信息,可参阅 + [控制器角色](/zh/docs/reference/access-authn-authz/rbac/#controller-roles)。 + +## 策略顺序 {#policy-order} +除了限制 Pod 创建与更新,Pod 安全策略也可用来为其所控制的很多字段 +设置默认值。当存在多个策略对象时,Pod 安全策略控制器依据以下条件选择 +策略: + +1. 优先考虑中允许 Pod 不经修改地创建或更新的 PodSecurityPolicy,这些策略 + 不会更改 Pod 字段的默认值或者其他配置。 + 这类非更改性质的 PodSecurityPolicy 对象之间的顺序无关紧要。 +2. 如果必须要为 Pod 设置默认值或者其他配置,(按名称顺序)选择第一个允许 + Pod 操作的 PodSecurityPolicy 对象。 -### 主机网络 - - *HostPorts* , 默认为 `empty`。`HostPortRange` 列表通过 `min`(包含) and `max`(包含) 来定义,指定了被允许的主机端口。 + +{{< note >}} +在更新操作期间(这时不允许更改 Pod 规约),仅使用非更改性质的 +PodSecurityPolicy 来对 Pod 执行验证操作。 +{{< /note >}} -### 允许的主机路径 - - *AllowedHostPaths* 是一个被允许的主机路径前缀的白名单。空值表示所有的主机路径都可以使用。 + +## 示例 {#example} +_本示例假定你已经有一个启动了 PodSecurityPolicy 准入控制器的集群并且 +你拥有集群管理员特权。_ -## 许可 + +### 配置 {#set-up} -许可使用如下的方式为 Pod 创建最终的安全上下文: -1. 检索所有可用的 PSP。 -1. 生成在请求中没有指定的安全上下文设置的字段值。 -1. 基于可用的策略,验证最终的设置。 +为运行此示例,配置一个名字空间和一个服务账号。我们将用这个服务账号来 +模拟一个非管理员账号的用户。 -如果某个策略能够匹配上,该 Pod 就被接受。如果请求与 PSP 不匹配,则 Pod 被拒绝。 +```shell +kubectl create namespace psp-example +kubectl create serviceaccount -n psp-example fake-user +kubectl create rolebinding -n psp-example fake-editor --clusterrole=edit --serviceaccount=psp-example:fake-user +``` -Pod 必须基于 PSP 验证每个字段。 + +创建两个别名,以更清晰地展示我们所使用的用户账号,同时减少一些键盘输入: +```shell +alias kubectl-admin='kubectl -n psp-example' +alias kubectl-user='kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example' +``` - ### 创建一个策略和一个 Pod -在一个文件中定义 PodSecurityPolicy 对象实例。这里的策略只是用来禁止创建有特权 -要求的 Pods。 +在一个文件中定一个示例的 PodSecurityPolicy 对象。 +这里的策略只是用来禁止创建有特权要求的 Pods。 +PodSecurityPolicy 对象的名称必须是合法的 +[DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。 {{< codenew file="policy/example-psp.yaml" >}} + 使用 kubectl 执行创建操作: ```shell kubectl-admin create -f example-psp.yaml ``` -## 获取 Pod 安全策略列表 - -获取已存在策略列表,使用 `kubectl get`: + +现在,作为一个非特权用户,尝试创建一个简单的 Pod: ```shell -$ kubectl get psp -NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES -permissive false [] RunAsAny RunAsAny RunAsAny RunAsAny false [*] -privileged true [] RunAsAny RunAsAny RunAsAny RunAsAny false [*] -restricted false [] RunAsAny MustRunAsNonRoot RunAsAny RunAsAny false [emptyDir secret downwardAPI configMap persistentVolumeClaim projected] +kubectl-user create -f- < +**发生了什么?** 尽管 PodSecurityPolicy 被创建,Pod 的服务账号或者 +`fake-user` 用户都没有使用该策略的权限。 ```shell -$ kubectl edit psp permissive +kubectl-user auth can-i use podsecuritypolicy/example ``` +``` +no +``` + +创建角色绑定,赋予 `fake-user` 使用 `use` 访问示例策略的权限: - -该命令将打开一个默认文本编辑器,在这里能够修改策略。 - - - -## 删除 Pod 安全策略 - -一旦不再需要一个策略,很容易通过 `kubectl` 删除它: + +{{< note >}} +不建议使用这种方法! +欲了解优先考虑的方法,请参见[下节](#run-another-pod)。 +{{< /note >}} ```shell -$ kubectl delete psp permissive -podsecuritypolicy "permissive" deleted +kubectl-admin create role psp:unprivileged \ + --verb=use \ + --resource=podsecuritypolicy \ + --resource-name=example ``` +输出: + +``` +role "psp:unprivileged" created +``` + +```shell +kubectl-admin create rolebinding fake-user:psp:unprivileged \ + --role=psp:unprivileged \ + --serviceaccount=psp-example:fake-user +``` + +输出: + +``` +rolebinding "fake-user:psp:unprivileged" created +``` + +```shell +kubectl-user auth can-i use podsecuritypolicy/example +``` + +输出: + +``` +yes +``` + + +现在重试创建 Pod: + +```shell +kubectl-user create -f- < +此次尝试不出所料地成功了! +不过任何创建特权 Pod 的尝试还是会被拒绝: + +```shell +kubectl-user create -f- < +继续此例之前先删除该 Pod: + +```shell +kubectl-user delete pod pause +``` + + +### 运行另一个 Pod {#run-another-pod} + +我们再试一次,稍微有些不同: + +```shell +kubectl-user create deployment pause --image=k8s.gcr.io/pause +``` + +输出为: + +``` +deployment "pause" created +``` + +```shell +kubectl-user get pods +``` + +输出为: + +``` +No resources found. +``` + +```shell +kubectl-user get events | head -n 2 +``` + +输出为: +``` +LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE +1m 2m 15 pause-7774d79b5 ReplicaSet Warning FailedCreate replicaset-controller Error creating: pods "pause-7774d79b5-" is forbidden: no providers available to validate pod request +``` + + +**发生了什么?** 我们已经为用户 `fake-user` 绑定了 `psp:unprivileged` 角色, +为什么还会收到错误 `Error creating: pods "pause-7774d79b5-" is +forbidden: no providers available to validate pod request +(创建错误:pods "pause-7774d79b5" 被禁止:没有可用来验证 pod 请求的驱动)`? +答案在于源文件 - `replicaset-controller`。 +`fake-user` 用户成功地创建了 Deployment,而后者也成功地创建了 ReplicaSet, +不过当 ReplicaSet 创建 Pod 时,发现未被授权使用示例 PodSecurityPolicy 资源。 + + +为了修复这一问题,将 `psp:unprivileged` 角色绑定到 Pod 的服务账号。 +在这里,因为我们没有给出服务账号名称,默认的服务账号是 `default`。 + +```shell +kubectl-admin create rolebinding default:psp:unprivileged \ + --role=psp:unprivileged \ + --serviceaccount=psp-example:default +``` + +输出为: + +``` +rolebinding "default:psp:unprivileged" created +``` + + +现在如果你给 ReplicaSet 控制器一分钟的时间来重试,该控制器最终将能够 +成功地创建 Pod: + +```shell +kubectl-user get pods --watch +``` + +输出类似于: + +``` +NAME READY STATUS RESTARTS AGE +pause-7774d79b5-qrgcb 0/1 Pending 0 1s +pause-7774d79b5-qrgcb 0/1 Pending 0 1s +pause-7774d79b5-qrgcb 0/1 ContainerCreating 0 1s +pause-7774d79b5-qrgcb 1/1 Running 0 2s +``` + + +### 清理 {#clean-up} + +删除名字空间即可清理大部分示例资源: + +```shell +kubectl-admin delete ns psp-example +``` + +输出类似于: + +``` +namespace "psp-example" deleted +``` + + +注意 `PodSecurityPolicy` 资源不是名字空间域的资源,必须单独清理: + +```shell +kubectl-admin delete psp example +``` + +输出类似于: +``` +podsecuritypolicy "example" deleted +``` + + +### 示例策略 {#example-policies} + +下面是一个你可以创建的约束性非常弱的策略,其效果等价于没有使用 Pod 安全 +策略准入控制器: + +{{< codenew file="policy/privileged-psp.yaml" >}} + + +下面是一个具有约束性的策略,要求用户以非特权账号运行,禁止可能的向 root 权限 +的升级,同时要求使用若干安全机制。 + +{{< codenew file="policy/restricted-psp.yaml" >}} + + +更多的示例可参考 +[Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/#policy-instantiation)。 + + +## 策略参考 {#policy-reference} + +### Privileged + +**Privileged** - 决定是否 Pod 中的某容器可以启用特权模式。 +默认情况下,容器是不可以访问宿主上的任何设备的,不过一个“privileged(特权的)” +容器则被授权访问宿主上所有设备。 +这种容器几乎享有宿主上运行的进程的所有访问权限。 +对于需要使用 Linux 权能字(如操控网络堆栈和访问设备)的容器而言是有用的。 + + +### 宿主名字空间 {#host-namespaces} + +**HostPID** - 控制 Pod 中容器是否可以共享宿主上的进程 ID 空间。 +注意,如果与 `ptrace` 相结合,这种授权可能被利用,导致向容器外的特权逃逸 +(默认情况下 `ptrace` 是被禁止的)。 + +**HostIPC** - 控制 Pod 容器是否可共享宿主上的 IPC 名字空间。 + +**HostNetwork** - 控制是否 Pod 可以使用节点的网络名字空间。 +此类授权将允许 Pod 访问本地回路(loopback)设备、在本地主机(localhost) +上监听的服务、还可能用来监听同一节点上其他 Pod 的网络活动。 + +**HostPorts** -提供可以在宿主网络名字空间中可使用的端口范围列表。 +该属性定义为一组 `HostPortRange` 对象的列表,每个对象中包含 +`min`(含)与 `max`(含)值的设置。 +默认不允许访问宿主端口。 + + +### 卷和文件系统 {#volumes-and-file-systems} + +**Volumes** - 提供一组被允许的卷类型列表。可被允许的值对应于创建卷时可以 +设置的卷来源。卷类型的完整列表可参见 +[卷类型](/zh/docs/concepts/storage/volumes/#types-of-volumes)。 +此外, `*` 可以用来允许所有卷类型。 + +对于新的 Pod 安全策略设置而言,建议设置的卷类型的*最小列表*包含: + +- configMap +- downwardAPI +- emptyDir +- persistentVolumeClaim +- secret +- projected + + +{{< warning >}} +PodSecurityPolicy 并不限制可以被 `PersistentVolumeClaim` 所引用的 +`PersistentVolume` 对象的类型。 +此外 `hostPath` 类型的 `PersistentVolume` 不支持只读访问模式。 +应该仅赋予受信用户创建 `PersistentVolume` 对象的访问权限。 +{{< /warning >}} + + +**FSGroup** - 控制应用到某些卷上的附加用户组。 + + - *MustRunAs* - 要求至少指定一个 `range`。 + 使用范围中的最小值作为默认值。所有 range 值都会被用来执行验证。 + - *MayRunAs* - 要求至少指定一个 `range`。 + 允许不设置 `FSGroups`,且无默认值。 + 如果 `FSGroup` 被设置,则所有 range 值都会被用来执行验证检查。 + - *RunAsAny* - 不提供默认值。允许设置任意 `fsGroup` ID 值。 + + +**AllowedHostPaths** - 设置一组宿主文件目录,这些目录项可以在 `hostPath` 卷中 +使用。列表为空意味着对所使用的宿主目录没有限制。 +此选项定义包含一个对象列表,表中对象包含 `pathPrefix` 字段,用来表示允许 +`hostPath` 卷挂载以所指定前缀开头的路径。 +对象中还包含一个 `readOnly` 字段,用来表示对应的卷必须以只读方式挂载。 +例如: + + +```yaml +allowedHostPaths: + # 下面的设置允许 "/foo"、"/foo/"、"/foo/bar" 等路径,但禁止 + # "/fool"、"/etc/foo" 这些路径。 + # "/foo/../" 总会被当作非法路径。 + - pathPrefix: "/foo" + readOnly: true # 仅允许只读模式挂载 +``` + + + +{{< warning >}} +容器如果对宿主文件系统拥有不受限制的访问权限,就可以有很多种方式提升自己的特权, +包括读取其他容器中的数据、滥用系统服务(如 `kubelet`)`的凭据信息等。 + +由可写入的目录所构造的 `hostPath` 卷能够允许容器写入数据到宿主文件系统, +并且在写入时避开 `pathPrefix` 所设置的目录限制。 +`readOnly: true` 这一设置在 Kubernetes 1.11 版本之后可用。 +必须针对 `allowedHostPaths` 中的 *所有* 条目设置此属性才能有效地限制容器 +只能访问 `pathPrefix` 所指定的目录。 +{{< /warning >}} + +**ReadOnlyRootFilesystem** - 要求容器必须以只读方式挂载根文件系统来运行 +(即不允许存在可写入层)。 + + +### FlexVolume 驱动 {#flexvolume-drivers} + +此配置指定一个可以被 FlexVolume 卷使用的驱动程序的列表。 +空的列表或者 nil 值意味着对驱动没有任何限制。 +请确保[`volumes`](#volumes-and-file-systems) 字段包含了 `flexVolume` 卷类型, +否则所有 FlexVolume 驱动都被禁止。 + + + +```yaml +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: allow-flex-volumes +spec: + # spec d的其他字段 + volumes: + - flexVolume + allowedFlexVolumes: + - driver: example/lvm + - driver: example/cifs +``` + + +### 用户和组 {#users-and-groups} + +**RunAsUser** - 控制使用哪个用户 ID 来运行容器。 + + - *MustRunAs* - 必须配置一个 `range`。使用该范围内的第一个值作为默认值。 + 所有 range 值都被用于验证检查。 +- *MustRunAsNonRoot* - 要求提交的 Pod 具有非零 `runAsUser` 值,或在镜像中 + (使用 UID 数值)定义了 `USER` 环境变量。 + 如果 Pod 既没有设置 `runAsNonRoot`,也没有设置 `runAsUser`,则该 Pod 会被 + 修改以设置 `runAsNonRoot=true`,从而要求容器通过 `USER` 指令给出非零的数值形式 + 的用户 ID。此配置没有默认值。采用此配置时,强烈建议设置 + `allowPrivilegeEscalation=false`。 +- *RunAsAny* - 没有提供默认值。允许指定任何 `runAsUser` 配置。 + + +**RunAsGroup** - 控制运行容器时使用的主用户组 ID。 + + - *MustRunAs* - 要求至少指定一个 `range` 值。第一个 range + 中的最小值作为默认值。所有 range 值都被用来执行验证检查。 + - *MayRunAs* - 不要求设置 `RunAsGroup`。 + 不过,如果指定了 `RunAsGroup` 被设置,所设置值必须处于所定义的范围内。 + - *RunAsAny* - 未指定默认值。允许 `runAsGroup` 设置任何值。 + + +**SupplementalGroups** - 控制容器可以添加的组 ID。 + + - *MustRunAs* - 要求至少指定一个 `range` 值。 + 第一个 range 中的最小值用作默认值。 + 所有 range 值都被用来执行验证检查。 + - *MayRunAs* - 要求至少指定一个 `range` 值。 + 允许不指定 `supplementalGroups` 且不设置默认值。 + 如果 `supplementalGroups` 被设置,则所有 range 值都被用来执行验证检查。 + - *RunAsAny* - 未指定默认值。允许为 `supplementalGroups` 设置任何值。 + + +### 特权提升 {#privilege-escalation} + +这一组选项控制容器的`allowPrivilegeEscalation` 属性。该属性直接决定是否为 +容器进程设置 +[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt) +参数。此参数会禁止 `setuid` 属性的可执行文件更改有效用户 ID(EUID),并且 +禁止启用额外权能的文件。例如,`no_new_privs` 会禁止使用 `ping` 工具。 +如果想有效地实施 `MustRunAsNonRoot` 控制,需要配置这一选项。 + + +**AllowPrivilegeEscalation** - 决定是否用户可以将容器的安全上下文设置为 +`allowPrivilegeEscalation=true`。默认设置下,这样做是允许的,目的是避免 +造成现有的 `setuid` 应用无法运行。将此选项设置为 `false` 可以确保容器的所有 +子进程都无法获得比父进程更多的特权。 + + +**DefaultAllowPrivilegeEscalation** - 为 `allowPrivilegeEscalation` 选项设置 +默认值。不设置此选项时的默认行为是允许特权提升,以便运行 setuid 程序。 +如果不希望运行 setuid 程序,可以使用此字段将选项的默认值设置为禁止,同时 +仍然允许 Pod 显式地请求 `allowPrivilegeEscalation`。 + + +### 权能字 {#capabilities} + +Linux 权能字(Capabilities)将传统上与超级用户相关联的特权作了细粒度的分解。 +其中某些权能字可以用来提升特权,打破容器边界,可以通过 PodSecurityPolicy +来限制。关于 Linux 权能字的更多细节,可参阅 +[capabilities(7)](http://man7.org/linux/man-pages/man7/capabilities.7.html)。 + +下列字段都可以配置为权能字的列表。表中的每一项都是 `ALL_CAPS` 中的一个权能字 +名称,只是需要去掉 `CAP_` 前缀。 + + +**AllowedCapabilities** - 给出可以被添加到容器的权能字列表。 +默认的权能字集合是被隐式允许的那些。空集合意味着只能使用默认权能字集合, +不允许添加额外的权能字。`*` 可以用来设置允许所有权能字。 + + +**RequiredDropCapabilities** - 必须从容器中去除的权能字。 +所给的权能字会从默认权能字集合中去除,并且一定不可以添加。 +`RequiredDropCapabilities` 中列举的权能字不能出现在 +`AllowedCapabilities` 或 `DefaultAddCapabilities` 所给的列表中。 + + +**DefaultAddCapabilities** - 默认添加到容器的权能字集合。 +这一集合是作为容器运行时所设值的补充。 +关于使用 Docker 容器运行引擎时默认的权能字列表,可参阅 +[Docker 文档](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)。 + + +### SELinux + +- *MustRunAs* - 要求必须配置 `seLinuxOptions`。默认使用 `seLinuxOptions`。 + 针对 `seLinuxOptions` 所给值执行验证检查。 +- *RunAsAny* - 没有提供默认值。允许任意指定的 `seLinuxOptions` 选项。 + + +### AllowedProcMountTypes + +`allowedProcMountTypes` 是一组可以允许的 proc 挂载类型列表。 +空表或者 nil 值表示只能使用 `DefaultProcMountType`。 + +`DefaultProcMount` 使用容器运行时的默认值设置来决定 `/proc` 的只读挂载模式 +和路径屏蔽。大多数容器运行时都会屏蔽 `/proc` 下面的某些路径以避免特殊设备或 +信息被不小心暴露给容器。这一配置使所有 `Default` 字符串值来表示。 + +此外唯一的ProcMountType 是 `UnmaskedProcMount`,意味着即将绕过容器运行时的 +路径屏蔽行为,确保新创建的 `/proc` 不会被容器修改。此配置用字符串 +`Unmasked` 来表示。 + + +### AppArmor + +通过 PodSecurityPolicy 上的注解来控制。 +详情请参阅 +[AppArmor 文档](/zh/docs/tutorials/clusters/apparmor/#podsecuritypolicy-annotations)。 -## 启用 Pod 安全策略 + +### Seccomp +Pod 对 seccomp 模版的使用可以通过在 PodSecurityPolicy 上设置注解来控制。 +Seccomp 是 Kubernetes 的一项 alpha 阶段特性。 -1. 已经启用 API 类型 `extensions/v1beta1/podsecuritypolicy`(仅对 1.6 之前的版本) -1. 已经启用许可控制器 `PodSecurityPolicy` -1. 已经定义了自己的策略 +**seccomp.security.alpha.kubernetes.io/defaultProfileName** - 注解用来 +指定为容器配置默认的 seccomp 模版。可选值为: + +- `unconfined` - 如果没有指定其他替代方案,Seccomp 不会被应用到容器进程上 + (Kubernets 中的默认设置)。 +- `runtime/default` - 使用默认的容器运行时模版。 +- `docker/default` - 使用 Docker 的默认 seccomp 模版。自 1.11 版本废弃。 + 应改为使用 `runtime/default`。 +- `localhost/<路径名>` - 指定节点上路径 `/<路径名>` 下的一个 + 文件作为其模版。其中 `` 是通过 `kubelet` 的标志 + `--seccomp-profile-root` 来指定的。 + +**seccomp.security.alpha.kubernetes.io/allowedProfileNames** - 指定可以为 +Pod seccomp 注解配置的值的注解。取值为一个可用值的列表。 +表中每项可以是上述各值之一,还可以是 `*`,用来表示允许所有的模版。 +如果没有设置此注解,意味着默认的 seccomp 模版是不可更改的。 -## 使用 RBAC + +### Sysctl + +默认情况下,所有的安全的 sysctl 都是被允许的。 + + +- `forbiddenSysctls` - 用来排除某些特定的 sysctl。 + 你可以在此列表中禁止一些安全的或者不安全的 sysctl。 + 此选项设置为 `*` 意味着禁止设置所有 sysctl。 +- `allowedUnsafeSysctls` - 用来启用那些被默认列表所禁用的 sysctl, + 前提是所启用的 sysctl 没有被列在 `forbiddenSysctls` 中。 + +参阅 [Sysctl 文档](/zh/docs/tasks/administer-cluster/sysctl-cluster/#podsecuritypolicy)。 + +## {{% heading "whatsnext" %}} + + +- 参阅[Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/) + 了解策略建议。 +- 阅读 [Pod 安全策略参考](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy)了解 API 细节。 -PodSecurityPolicy 认证使用所有可用的策略,包括创建 Pod 的用户,Pod 上指定的服务账户(Service Account)。当 Pod 基于 Deployment、ReplicaSet 创建时,它是创建 Pod 的 Controller Manager,所以如果基于非安全 API 端口运行,允许所有的 PodSecurityPolicy 对象,并且不能够有效地实现细分权限。用户访问给定的 PSP 策略有效,仅当是直接部署 Pod 的情况。更多详情,查看 [PodSecurityPolicy RBAC 示例](https://git.k8s.io/kubernetes/examples/podsecuritypolicy/rbac/README.md),当直接部署 Pod 时,应用 PodSecurityPolicy 控制基于角色和组的已授权容器的访问 。