IBM/portieris

GitHub: IBM/portieris

Kubernetes 准入控制器,通过验证镜像签名和强制安全策略,防止未授权或不可信的容器镜像部署到集群。

Stars: 340 | Forks: 80

![Portieris logo](https://raw.githubusercontent.com/IBM/portieris/main/logos/text_and_logo.svg) [![Go](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/c4a7bb442d102245.svg)](https://github.com/IBM/portieris/actions/workflows/go-portieris.yaml) Portieris 是一个 Kubernetes admission controller,用于强制执行镜像安全策略。您可以为每个 Kubernetes namespace 或在集群级别创建镜像安全策略,并对不同的镜像执行不同的规则。 ## 工作原理 Portieris 使用 Kubernetes mutating admission webhook 在创建资源时对其进行修改,以确保 Kubernetes 仅运行符合策略的镜像。当配置为执行此操作时,Portieris 可以强制执行 Docker Content Trust(带有可选的 trust pinning),或者可以验证使用 Red Hat 的简单签名模型创建的签名,并防止创建使用不可信或未验证镜像的资源。 如果您的云提供商提供 [Notary](https://github.com/notaryproject/notary) 服务器(有时称为 Content Trust),Portieris 将访问该 Notary 服务器中与您正在部署的镜像对应的信任数据。要验证 Red Hat 简单签名,必须能够使用 registry extension APIs 或配置的签名存储来访问这些签名。 当您创建或编辑工作负载时,Kubernetes API server 会向 Portieris 发送请求。AdmissionRequest 包含您工作负载的内容。对于工作负载中的每个镜像,Portieris 都会找到匹配的安全策略。 如果在策略中启用了信任强制执行,Portieris 会从相应的 Notary server 拉取您镜像的签名信息,并且如果存在镜像的签名版本,则创建一个 JSON patch 将工作负载中的镜像名称修改为通过摘要引用的签名镜像。如果在策略中定义了签名者,Portieris 还会检查镜像是否由指定的角色签名,并验证是否使用了指定的密钥对镜像进行签名。 如果策略指定了简单签名,Portieris 将使用策略中提供的公钥和身份规则验证签名,如果验证通过,则将镜像名称修改为摘要引用,以确保并发的标签更改不会影响正在拉取的镜像。 虽然可以同时要求 Notary trust 和简单签名,但这两种方法必须对镜像的签名摘要达成一致。如果这两种方法返回不同的签名摘要,该镜像将被拒绝。不允许使用替代签名方法。 如果您工作负载中的任何镜像不满足策略,则整个工作负载将被阻止部署。 Portieris 接收针对所有类型工作负载的创建或编辑 AdmissionRequests。为了防止 Portieris 影响自动恢复,它会批准存在已知父级的请求。 Portieris 的 Admission Webhook 被配置为 fail closed(故障关闭)。Portieris 的三个实例确保它能够批准自己的升级和自动恢复。如果 Portieris 的所有实例都不可用,Kubernetes 不会自动恢复它,您必须删除 MutatingAdmissionWebhook 以允许 Portieris 恢复。 ## 镜像变更选项 默认行为是在成功准入后变更镜像引用,以便它使用摘要而不是标签来不可变地引用镜像。此行为确保通过在镜像 registry 中进行更改,镜像在验证后被替换的可能性极小。如果没有此保护措施,在准入和镜像拉取之间,以及在准入和由于重新调度而导致的任何后续镜像重新拉取之间都存在一个时间窗口,在此窗口期标签下的镜像可能会发生更改。将镜像切换为摘要形式可确保镜像内容保证是已准入的内容。 某些闭环部署技术通过查看正在运行的容器中的镜像引用来验证正在运行的镜像是否是预期的镜像,并将变更后的镜像引用视为不同,然后尝试纠正这种差异,但没有任何效果。在这种情况下,可能会启动一个无限的协调循环,驱动 Kubernetes API、Portieris 和 registry 流量。为了避免这种情况,您可以在策略行为设置中指定 `mutateImage: false`,这不会更改在此策略下准入的镜像,并防止不良后果。其代价是重新引入了准入和拉取之间的时间窗口,导致其他镜像可以在未经验证的情况下被替换并运行。 仅在绝对必要时使用此选项,并且不要将其与 `trust` 要求一起使用,因为 `notaryV1` 标签不直接链接到 registry 标签,即使在稳定状态下(没有 registry 更改),意外的镜像也可能在信任验证下运行。 请参阅 [镜像变更选项](POLICIES.md#image-mutation-option)。 ## Portieris 指标 Portieris 公开了两个指标,用于监控为工作负载镜像做出的策略决策,这些指标在端口 8080 上可用,并通过 annotations 向 [Prometheus](https://prometheus.io/) 公开。这些指标是: ``` portieris_pod_admission_decision_allow_count portieris_pod_admission_decision_deny_count ``` 这些指标是计数器,每次做出决策时都会递增。 这些指标可以在每个正在运行的 pod 的 `:8080/metrics` 路径上本地查看。 ## 安装 Portieris Portieris 使用 Helm chart 安装。在开始之前,请确保您的集群上安装了 Kubernetes 1.16 或更高版本,并且工作站上安装了 Helm 3.0 或更高版本。 * 要在默认 namespace(`portieris`)中安装 Portieris,请完成以下步骤: 1. 找到您想要运行的 release,请参阅 [Releases](https://github.com/IBM/portieris/releases),并下载 Helm chart 包。 2. 解压 charts,例如,运行: tar xzvf portieris-0.9.4.tgz 3. 生成您的 CA 证书以及 webhook server 的证书/密钥对,并由您创建的 CA 签名。将这些添加到 `values.yaml` 文件中的 `UseGeneratedCerts` 下。务必还将 `enabled` 设置为 true。有关更详细的说明,请参阅 `helm/portieris` 下的 README。 4. 运行: helm install portieris --create-namespace --namespace portieris ./portieris * 要在不同的 namespace(包括现有的 namespace)中安装 Portieris,请省略 `--create-namespace` 选项。因为 namespace 构成了 webhook 证书通用名称的一部分,所以您必须为目标 namespace 生成证书。 1. 运行: sh portieris/gencerts 2. 运行: helm install portieris --create-namespace --namespace ./portieris * 要通过已安装的 [cert-manager](https://cert-manager.io/) 管理证书,您不需要解压 charts。 1. 运行: helm install portieris --set UseCertManager=true portieris-0.9.4.tgz 默认情况下,Portieris 的 admission webhook 在所有 namespace 中运行,包括其自己的安装 namespace,以便 Portieris 能够审查集群中的所有 pod。但是,如果 Portieris 变得不可用,这可能会阻止集群自我修复。 Portieris 还支持跳过设置了特定标签的 namespace。您可以通过在安装命令中添加 `--set AllowAdmissionSkip=true` 来启用此功能,但请确保您控制谁可以向 namespace 添加标签以及谁可以访问带有此标签的 namespace,以免恶意方使用此标签绕过 Portieris。 避免更新死锁的另一种方法是指定 `--set webHooks.failurePolicy=Ignore`。 ## 卸载 Portieris **注意**:当您卸载 Portieris 时,您的所有镜像安全策略都将被删除。 要卸载 Portieris,请运行: ``` helm delete portieris --namespace ``` **注意**: * 如果您不再需要该 namespace,必须通过运行以下命令手动删除它: kubectl delete namespace/ * 如果您在使用 Helm 卸载 Portieris 时遇到问题,请尝试运行清理脚本: helm/cleanup.sh portieris ## 镜像安全策略 镜像安全策略定义了 Portieris 在您集群中的行为。您必须配置自己的策略,以便 Portieris 强制执行您所需的安全态势。[策略](POLICIES.md) 将单独进行描述。 ## 为您的安全策略配置访问控制 您可以配置 Kubernetes role-based access control (RBAC) 规则,以定义哪些用户和应用程序可以修改您的安全策略。有关更多信息,请参阅 [Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) 文档以及 IBM Cloud Kubernetes Service 文档中的 [Controlling user access with IBM Cloud IAM and Kubernetes RBAC](https://cloud.ibm.com/docs/containers?topic=containers-users)。 如果 Portieris 安装时设置了 `AllowAdmissionSkip=true`,您可以通过使用 `securityenforcement.admission.cloud.ibm.com/namespace: skip` 标记 namespace 来防止在该特定 namespace 中调用 Portieris 的 admission webhook。此操作允许该 namespace 中的 pod 在 admission webhook 宕机时恢复,但请注意,该 namespace 中不会应用任何策略。例如,Portieris 安装 namespace 配置了此标签,以允许 Portieris 自身在宕机时恢复。请确保您控制谁可以向 namespace 添加标签以及谁可以访问带有此标签的 namespace,以免恶意方使用此标签绕过 Portieris。 ## 报告安全问题 要报告安全问题,请勿开启 issue。相反,请通过电子邮件将您的报告私下发送至 `alchreg@uk.ibm.com`。
标签:DevSecOps, Docker Content Trust, EVTX分析, Go, IBM, Lerna, mutating admission webhook, Notary, PyVis, Red Hat 简单签名, Ruby工具, Web截图, 上游代理, 内容信任, 准入控制器, 子域名突变, 容器安全, 数字签名验证, 日志审计, 策略执行, 自定义请求头, 请求拦截, 镜像信任, 镜像安全策略, 镜像完整性, 镜像签名