一、Pod安全性标准
Pod 安全性标准定义了三种不同的策略(Policy),以广泛覆盖安全应用场景, 这些策略是叠加式的(Cumulative),安全级别从高度宽松至高度受限。 本篇教程概述了每个策略的要求。
Profile | 描述 |
Privileged | 不受限制的策略,提供最大可能范围的权限许可。此策略允许已知的特权提升。 |
Baseline | 限制性最弱的策略,禁止已知的策略提升。允许使用默认的(规定最少)Pod 配置。 |
Restricted | 限制性非常强的策略,遵循当前的保护 Pod 的最佳实践。 |
二、Profile细节
1、Privileged
Privileged 策略是有目的地开放且完全无限制的策略, 此类策略通常针对由特权较高、受信任的用户所管理的系统级或基础设施级负载。
Privileged 策略定义中限制较少。默认允许的(Allow-by-default)实施机制(例如 gatekeeper) 可以缺省设置为 Privileged。 与此不同,对于默认拒绝(Deny-by-default)的实施机制(如 Pod 安全策略)而言, Privileged 策略应该禁止所有限制。
2、Baseline
Baseline 策略的目标是便于常见的容器化应用采用,同时禁止已知的特权提升。 此策略针对的是应用运维人员和非关键性应用的开发人员。 下面列举的控制应该被实施(禁止):
在下述表格中,通配符(*)意味着一个列表中的所有元素。 例如 spec.containers[*].securityContext 表示所定义的所有容器的安全性上下文对象。 如果所列出的任一容器不能满足要求,整个 Pod 将无法通过校验。
控制(Control) | 策略(Policy) |
HostProcess | Windows Pod 提供了运行 HostProcess 容器 的能力, 这使得对 Windows 节点的特权访问成为可能。 基线策略中对宿主的特权访问是被禁止的。 HostProcess Pod 是 Kubernetes v1.22 版本的 alpha 特性。
限制的字段:
允许的值
|
宿主名字空间 | 必须禁止共享宿主名字空间。
限制的字段:
允许的值:
|
特权容器 | 特权 Pod 关闭了大多数安全性机制,必须被禁止。
限制的字段:
允许的值:
|
权能 | 必须禁止添加除下列字段之外的权能。
限制的字段:
允许的值:
|
HostPath 卷 | 必须禁止 HostPath 卷。
限制的字段:
允许的值:
|
宿主端口 | 应禁止使用宿主端口,或者至少限定为已知列表。
限制的字段:
允许的值:
|
AppArmor | 在受支持的主机上,默认使用 runtime/default AppArmor Profile。 基线策略应避免覆盖或者禁用默认策略,以及限制覆盖一些 Profile 集合的权限。
限制的字段:
允许的值:
|
SELinux | 设置 SELinux 类型的操作是被限制的,设置自定义的 SELinux 用户或角色选项是被禁止的。
限制的字段:
允许的值:
限制的字段:
允许的值:
|
/proc 挂载类型 | 要求使用默认的 /proc 掩码以减小攻击面。
限制的字段:
允许的值:
|
Seccomp | Seccomp Profile 禁止被显式设置为 Unconfined。
限制的字段:
允许的值:
|
Sysctls | Sysctls 可以禁用安全机制或影响宿主上所有容器,因此除了若干“安全”的子集之外,应该被禁止。 如果某 sysctl 是受容器或 Pod 的名字空间限制,且与节点上其他 Pod 或进程相隔离,可认为是安全的。
限制的字段:
允许的值:
|
3、Restricted
Restricted 策略旨在实施当前保护 Pod 的最佳实践,尽管这样作可能会牺牲一些兼容性。 该类策略主要针对运维人员和安全性很重要的应用的开发人员,以及不太被信任的用户。 下面列举的控制需要被实施(禁止):
在下述表格中,通配符(*)意味着一个列表中的所有元素。 例如 spec.containers[*].securityContext 表示 所定义的所有容器 的安全性上下文对象。 如果所列出的任一容器不能满足要求,整个 Pod 将无法通过校验。
控制(Control) | 策略(Policy) |
Baseline策略的所有要求。 | |
卷类型 | 除了限制 HostPath 卷之外,此类策略还限制可以通过 PersistentVolumes 定义的非核心卷类型。
限制的字段:
允许的值:
|
特权提升(v1.8+) | 禁止(通过 SetUID 或 SetGID 文件模式)获得特权提升。
限制的字段:
允许的值:
|
以非 root 账号运行 | 必须要求容器以非 root 用户运行。
限制的字段:
允许的值:
如果 Pod 级别 spec.securityContext.runAsNonRoot 设置为 true,则允许容器组的安全上下文字段设置为 未定义/nil。 |
非 root 用户(v1.23+) | Containers 不可以将 runAsUser 设置为 0
限制的字段:
允许的字段:
|
Seccomp (v1.19+) | Seccomp Profile 必须被显式设置成一个允许的值。禁止使用 Unconfined Profile 或者指定 不存在的 Profile。
限制的字段:
允许的值:
如果 Pod 级别的 spec.securityContext.seccompProfile.type 已设置得当,容器级别的安全上下文字段可以为 未定义/nil。 反过来说,如果 _所有的_ 容器级别的安全上下文字段已设置,则 Pod 级别的字段可为 未定义/nil。 |
权能(v1.22+) | 容器组必须弃用 ALL 权能,并且只允许添加 NET_BIND_SERVICE 权能。
限制的字段:
允许的值:
限制的字段:
允许的值:
|
三、策略实例化
将策略定义从策略实例中解耦出来有助于形成跨集群的策略理解和语言陈述, 以免绑定到特定的下层实施机制。随着相关机制的成熟,这些机制会按策略分别定义在下面。特定策略的实施方法不在这里定义。
1、Pod 安全性准入控制器:
- Privileged 名字空间;
- Baseline 名字空间;
- Restricted 名字空间。
2、替代方案:
在 Kubernetes 生态系统中还在开发一些其他的替代方案,例如:
- Kubewarden
- Kyverno
- OPA Gatekeeper
四、Pod OS字段
Kubernetes 允许使用运行 Linux 或 Windows 的节点。可以在一个集群中混用两种类型的节点。 Kubernetes 中的 Windows 与基于 Linux 的工作负载相比有一些限制和差异。 具体而言,许多 Pod securityContext 字段在 Windows 上不起作用。
v1.24 之前的 Kubelet 不强制处理 Pod OS 字段,如果集群中有些节点运行早于 v1.24 的版本, 则应将限制性的策略锁定到 v1.25 之前的版本。
1、限制性的 Pod Security Standard 变更
Kubernetes v1.25 中的另一个重要变化是限制性的(Restricted) Pod 安全性已更新, 能够处理 pod.spec.os.name 字段。根据 OS 名称,专用于特定 OS 的某些策略对其他 OS 可以放宽限制。
2、OS 特定的策略控制
仅当 .spec.os.name 不是 windows 时,才需要对以下控制进行限制:
- 特权提升
- Seccomp
- Linux 权能
五、常见问题
1、为什么不存在介于 Privileged 和 Baseline 之间的策略类型?
这里定义的三种策略框架有一个明晰的线性递进关系,从最安全(Restricted)到最不安全, 并且覆盖了很大范围的工作负载。特权要求超出 Baseline 策略者通常是特定于应用的需求, 所以我们没有在这个范围内提供标准框架。 这并不意味着在这样的情形下仍然只能使用 Privileged 框架, 只是说处于这个范围的策略需要因地制宜地定义。SIG Auth 可能会在将来考虑这个范围的框架,前提是有对其他框架的需求。
2、安全配置与安全上下文的区别是什么?
安全上下文在运行时配置 Pod 和容器。安全上下文是在 Pod 清单中作为 Pod 和容器规约的一部分来定义的, 所代表的是传递给容器运行时的参数。
安全策略则是控制面用来对安全上下文以及安全性上下文之外的参数实施某种设置的机制。 在 2020 年 7 月, Pod 安全性策略已被废弃, 取而代之的是内置的 Pod 安全性准入控制器。
3、沙箱(Sandboxed)Pod 怎么处理?
现在还没有 API 标准来控制 Pod 是否被视作沙箱化 Pod。 沙箱 Pod 可以通过其是否使用沙箱化运行时(如 gVisor 或 Kata Container)来辨别, 不过目前还没有关于什么是沙箱化运行时的标准定义。
沙箱化负载所需要的保护可能彼此各不相同。例如,当负载与下层内核直接隔离开来时, 限制特权化操作的许可就不那么重要。这使得那些需要更多许可权限的负载仍能被有效隔离。
此外,沙箱化负载的保护高度依赖于沙箱化的实现方法。 因此,现在还没有针对所有沙箱化负载的建议配置。