翻译自Kubernetes Pod Security Policies with Open Policy Agent

Kubernetes是当今云原生生态系统中最流行的容器编排平台。因此,Kubernetes的安全性也是一个越来越令人感兴趣和关注的领域。

在这篇博文中,首先我将讨论Pod安全策略准入控制器。然后我们将看到Open Policy Agent如何实现Pod安全策略。事实上,在Kubecon + CloudNaticeCon North America 2019的Kubernetes SIG Auth期间,Open Policy Agent / Gatekeeper被提及为Pod安全策略的潜在替代品。

首先,简要了解一下容器、安全和准入控制器。

容器和安全概述

Kubernetes 中的容器是什么?

容器是轻量级的,可移植的,易于管理。在同一主机上运行的容器没有单独的物理/虚拟机。换句话说,容器共享资源、硬件和它们所运行的主机的操作系统内核。因此,使用者围绕哪些进程可以在容器内运行、这些进程有哪些权限、容器是否允许权限升级、使用哪些镜像等问题拥有适当的安全性变得非常重要。

kubernetes 中的 Pod 是什么?

Pod是Kubernetes应用程序的基本执行单元,是Kubernetes对象模型中最小、最简单的单元,由你创建或部署。它是一组由一个或多个容器组成的共享存储/网络,以及如何运行这些容器的规范。

因此,在容器上执行安全策略时,我们检查并应用Pod规范的安全策略。那么,这些政策是如何执行的呢?使用准入控制器。

什么是 Admission Controller ?

准入控制器是kube-apiserver的一部分。在配置被存储在集群设置(etcd)之前,它们拦截对Kubernetes API服务器的请求。一个准入控制器可以是验证性的(验证传入的请求),也可以是突变性的(修改传入的请求),或者两者都是。请参考Kubernetes文档,快速了解各种准入控制器的情况。

使用 Open Policy Agent 作为 Admission Controller

开放政策代理(OPA)是一个开源的、通用的政策引擎,它使把政策写成代码成为可能。OPA提供了一种高水平的声明性语言–Rego–来实现政策即代码。使用OPA,我们可以在微服务、CI/CD管道、API网关等方面执行策略。OPA最重要的用例之一是Kubernetes的策略执行,作为一个准入控制器。

这些策略是在Rego中编写的,并加载到OPA中,作为Kubernetes集群的准入控制器运行。OPA将根据Rego策略评估对Kubernetes API服务器的任何资源创建/更新/删除请求。如果该请求满足所有的策略,该请求就被允许。但即使有一个策略失败,请求也会被拒绝。

Admission Control

关于OPARego 的更多详情,请阅读Rego Docs

现在,让我们来看看Pod安全策略的细节。

Pod Security Policy 是什么?

Pod安全策略(PSP)是一个集群级的资源,作为一个准入控制器来实现。PSP允许用户将安全要求转化为管理Pod规格的具体政策。起初,当一个PodSecurityPolicy资源被创建时,它什么都不做。而为了使用它,请求用户或目标pod的服务账户必须通过允许 “使用 “动词来授权使用该策略。你可以参考Kubernetes文档中的启用Pod安全策略。

请注意,PSP接纳控制器既是验证接纳控制器,又是变异接纳控制器。对于一些参数,PSP录取控制器使用默认值来改变传入的请求。此外,顺序始终是先变异,然后再验证。

我们可以使用 PSP 控制哪些参数?

下表简要介绍了PSP中使用的各种参数和字段。详细解释见Kubernetes文档

Field Kubernetes API Reference (Kind – Version – Group ) Control Aspect
privileged SecurityContext v1 core Running containers in privileged mode
hostPID, hostIPC PodSpec v1 core (https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#podspec-v1-core) Usage of host namespaces

如何使用 OPA 来 实现 PSP ?

我在前面提到,Rego语言允许我们把任何自定义策略写成代码。这意味着,我们可以使用Rego编写上述的Pod安全策略,并将OPA作为一个准入控制器来执行。

让我们快速看下 Rego 实现 privileged pod policy

1
2
3
4
5
6
7
8
9
10
11
12
package kubernetes.admission

deny[message] {
#applies for Pod resources
input.request.kind.kind == "Pod"
#loops through all containers in the request
container := input.request.object.spec.containers[_]
#for each container, check privileged field
container.securityContext.privileged
#if all above statements are true, return message
message := sprintf("Container %v runs in privileged mode.", [container.name])
}

那么,这个策略是做什么的呢?如果输入请求中的任何容器是作为特权容器运行的,它将返回一条信息。

PSP 实践

让我们通过一个基于minikube的基本教程来看看这个策略的运作情况。首先,按照OPA文档中的教程,将OPA设置为准入控制器。这个教程加载一个入口验证策略。取而代之的是,我们将加载上面显示的特权策略。

一旦OPA被设置为minikube上的接纳控制器,使用上面的策略创建一个文件priorleged.rego。然后,在 “OPA “命名空间中,将该策略创建一个configmap

kubectl create configmap privileged-policy --from-file=privileged.rego -n opa

现在,让我们使用以下清单创建一个具有特权的容器的部署。

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
securityContext:
privileged: true

当你尝试创建这个pod的时候,你将注意到因为OPA的存在而动作被拒绝。

1
Error from server (Container nginx runs in privileged mode.): error when creating "privileged-deploy.yaml": admission webhook "validating-webhook.openpolicyagent.org" denied the request: Container nginx runs in privileged mode.

同样,我们可以为其他Pod编写安全策略,并使用OPA进行强制执行。

在此篇教程中,为了简单起见我们使用configmap来加载策略,但这不是生产部署的最佳策略。在生产环境中,你可以从外部的 bundle 服务器中定期的下载 OPA 策略。你所有的策略可以在 bundle 服务中进行维护,另外 OPA 也会定期的下载来保持其最新状态。请查看Bundle API了解更多信息。

简而言之,使用 OPA ,我们可以强制执行 Pod 安全策略。不仅如此,我们还可以使用相同的设置来执行任何其他自定义的安全/基于标准的政策。

PSP中应用OPA的几点关键益处

  • 可以在同一个准入控制器中管理所有的策略避免了分散的管理
  • 完善了 Policy-as-codeCICD 中的实现
  • 使得通过版本控制工具例如 Git 来维护 OPA 策略成为了可能, OPA 也提供了 APIs 来动态的管理策略并进行加载
  • 根据自己的实施进行定制化的拒绝信息

另外,我们也可以部署 OPA 作为 mutating admission controller。这样的话,你也可以完善 PSP Admission Controllermutating 行为。