查看原文
其他

Open Policy Agent: Kubernetes 准入控制策略 Top 5

Addo Zhang 云原生指北 2021-12-08

如何使用 Open Policy Agent 实现准入策略控制,可以参考这里

本文翻译自 Open Policy Agent: The Top 5 Kubernetes Admission Control Policies[1]


Kubernetes 开发人员和平台工程师通常承受着非常大的压力,以保持应用程序部署的快速进行,并且总是为了速度和进度而做出妥协。平台团队越来越有责任确保这些妥协(例如管理 Ingress)不会导致客户数据暴露在整个互联网上等后果。

幸运的是,Kubernetes 提供了设置策略的能力,通过检查并防止部署错误将其投入生产,从而避免这些后果。为了确保团队的应用程序不会比信心更重要,以下是现在应该在集群中运行的前五个 Kubernetes 准入控制策略。

1. 可信镜像仓库

此策略很简单,但功能强大:仅允许从受信任的镜像仓库中拉取的容器映像,并且可以选择仅拉取与允许的仓库镜像地址列表匹配的那些镜像。

当然,从互联网(或可信镜像仓库库以外的任何地方)拉取未知镜像会带来风险——例如恶意软件。但是还有其他很好的理由来维护单一的可信来源,例如在企业中实现可支持性。通过确保镜像仅来自受信任的镜像仓库,可以密切控制镜像库存,降低软件熵和蔓延的风险,并提高集群的整体安全性。

相关策略:

•禁止所有带有“latest” tag 的镜像•仅允许签名镜像或匹配特定哈希/SHA 的镜像

策略示例:

package kubernetes.validating.imagesdeny[msg] { some i input.request.kind.kind == "Pod" image := input.request.object.spec.containers[i].image not startswith(image, "hooli.com/") msg := sprintf("Image '%v' comes from untrusted registry", [image])}

2. 标签安全

此策略要求所有 Kubernetes 资源都包含指定的标签并使用适当的格式。由于标签决定了 Kubernetes 对象和策略的分组,包括工作负载可以运行的位置——前端、后端、数据层——以及哪些资源可以发送流量,标签错误会导致生产中无法解释的部署和可支持性问题。此外,如果没有对标签应用方式的访问控制,集群就缺乏基本的安全性。最后,手动输入标签的危险在于错误会蔓延,特别是因为标签在 Kubernetes 中既灵活又强大。应用此策略并确保标签配置正确且一致。

相关政策:

•确保每个工作负载都需要特定的注解(annotations)•指定污点和容忍度以限制可以部署映像的位置

策略示例:

package kubernetes.validating.existencedeny[msg] { not input.request.object.metadata.labels.costcenter msg := "Every resource must have a costcenter label"}deny[msg] { value := input.request.object.metadata.labels.costcenter not startswith(value, "cccode-") msg := sprintf("Costcenter code must start with `cccode-`; found `%v`", [value])}

## 3. 禁止(或指定)特权模式

此策略确保默认情况下容器不能在特权模式下运行 - 除非在允许的情况下排除特定情况(通常很少见)。

通常,希望避免在特权模式下运行容器,因为它提供对主机资源和内核功能的访问——包括禁用主机级保护的能力。虽然容器在某种程度上是隔离的,但它们最终共享相同的内核。这意味着如果特权容器遭到入侵,它可能会成为入侵整个系统的起点。尽管如此,在特权模式下运行还是有正当理由的——只要确保这些时间是例外,而不是规则。

相关政策:

•禁止不安全的能力(capabilities)•禁止容器以 root 身份运行(以非 root 身份运行)•设置 userID

策略示例:

package kubernetes.validating.privilegeddeny[msg] { some c input_container[c] c.securityContext.privileged msg := sprintf("Container '%v' should not run in privileged mode.", [c.name])}input_container[container] { container := input.request.object.spec.containers[_]}input_container[container] { container := input.request.object.spec.initContainers[_]}

定义和控制入口

Ingress 策略允许根据需要公开特定服务(允许 Ingress),或者根据需要不公开任何服务。在 Kubernetes 中,很容易意外启动与公共互联网通信的服务(Kubernetes 故障故事中有很多这样的例子)。同时,过于宽松的 Ingress 会导致启动不必要的外部 LoadBalancer,这也可能会变得非常昂贵(如每月预算支出)非常快!此外,当两个服务尝试共享同一个 Ingress 时,它可能会破坏应用程序。

下面的策略示例防止不同命名空间中的 Ingress 对象共享相同的主机名。这个常见问题意味着新工作负载会从现有工作负载“窃取”互联网流量,这会产生一系列负面后果——从服务中断到数据暴露等等。

相关政策:

•需要 TLS•禁止/允许特定端口

策略示例:

package kubernetes.validating.ingressdeny[msg] { is_ingress input_host := input.request.object.spec.rules[_].host some other_ns, other_name other_host := data.kubernetes.ingresses[other_ns][other_name].spec.rules[_].host [input_ns, input_name] != [other_ns, other_name] input_host == other_host msg := sprintf("Ingress host conflicts with ingress %v/%v", [other_ns, other_name])}input_ns = input.request.object.metadata.namespaceinput_name = input.request.object.metadata.nameis_ingress { input.request.kind.kind == "Ingress" input.request.kind.group == "extensions" input.request.kind.version == "v1beta1"}

5. 定义和控制出口

每个应用程序都需要防护栏来控制出口流量的流动方式,此策略允许你指定集群内和集群外的通信。与 Ingress 一样,默认情况下很容易意外地“允许 Egress”到全世界的每个 IP。有时这甚至不是意外——完全的放开通常是确保可以访问新部署的应用程序的最后努力,即使它过于宽松或引入风险。在集群内级别,还有可能无意中将数据发送到不应该拥有的服务。如果服务受到损害,这两种情况都存在数据泄露和盗窃的风险。另一方面:过于严格,使用 Egress 有时会导致配置错误,从而破坏应用程序。实现两全其美意味着使用此策略选择和指定允许 Egress 发生的时间和服务。

相关政策。

•请参阅上面的入口策略

策略示例:

package kubernetes.validating.egressallow_list := { "10.10.0.0/16", "192.168.100.1/32"}deny[reason] { network_policy_allows_all_egress reason := "Network policy allows access to any IP address."}deny[reason] { count(allow_list) > 0 input.request.kind.kind == "NetworkPolicy" input.request.object.spec.policyTypes[_] == "Egress" ipBlock := input.request.object.spec.egress[_].to[_].ipBlock not any({t | t := net.cidr_contains(allow_list[_], ipBlock.cidr)}) reason := "Network policy allows egress traffic outside of allowed IP ranges."}network_policy_allows_all_egress { input.request.kind.kind == "NetworkPolicy" input.request.object.spec.policyTypes[_] == "Egress" egress := input.request.object.spec.egress[_] not egress.to}

有了这些政策,你就可以专注于构建一个世界级的平台。当然,如果你想为 Kubernetes 添加更多基本策略,请查看 openpolicyagent.org[2]

引用链接

[1] Open Policy Agent: The Top 5 Kubernetes Admission Control Policies: https://thenewstack.io/open-policy-agent-the-top-5-kubernetes-admission-control-policies/
[2] openpolicyagent.org: https://www.openpolicyagent.org/


: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存