From fc1db56aa33af4fecddfcc838bb8dd09e52edc27 Mon Sep 17 00:00:00 2001 From: zhangxiaoyang Date: Thu, 10 Aug 2023 20:12:13 +0800 Subject: [PATCH] [zh-cn] add 2023-03-30-kubescape-validating-admission-policy-library.md chinese version --- ...ape-validating-admission-policy-library.md | 421 ++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 content/zh-cn/blog/_posts/2023-03-30-kubescape-validating-admission-policy-library.md diff --git a/content/zh-cn/blog/_posts/2023-03-30-kubescape-validating-admission-policy-library.md b/content/zh-cn/blog/_posts/2023-03-30-kubescape-validating-admission-policy-library.md new file mode 100644 index 0000000000..6ba1fba4a9 --- /dev/null +++ b/content/zh-cn/blog/_posts/2023-03-30-kubescape-validating-admission-policy-library.md @@ -0,0 +1,421 @@ +--- +layout: blog +title: "Kubernetes 验证准入策略:一个真实示例" +date: 2023-03-30T00:00:00+0000 +slug: kubescape-validating-admission-policy-library +--- + + + + +**作者**:Craig Box (ARMO), Ben Hirschberg (ARMO) + +**译者**:Xiaoyang Zhang (Huawei) + + +准入控制是 Kubernetes 控制平面的重要组成部分,在向服务器提交请求时,可根据批准或更改 API 对象的能力来实现多项内部功能。 +对于管理员来说,定义有关哪些对象可以进入集群的业务逻辑或策略是很有用的。为了更好地支持该场景, +[Kubernetes 在 v1.7 中引入了外部准入控制](/blog/2017/06/kubernetes-1-7-security-hardening-stateful-application-extensibility-updates/)。 + + +除了众多的自定义内部实现外,许多开源项目和商业解决方案还使用用户指定的策略实现准入控制器,包括 +[Kyverno](https://github.com/kyverno/kyverno) 和 Open Policy Agent 的 +[Gatekeep](https://github.com/open-policy-agent/gatekeeper)。 + + +虽然针对策略的准入控制器已经被人采用,但其广泛使用仍存在障碍。 +Webhook 基础设施必须作为生产服务进行维护,且包含所有相关内容。 +如果准入控制 Webhook 失败,则要么必须关闭,从而降低集群的可用性;要么打开,使该功能在策略执行中的使用失效。 +例如,在 “serverless” 环境中,当 Pod 启动以响应网络请求时,网络跳跃和评估时间使准入控制成为处理延迟的重要组成部分。 + + +## 验证准入策略和通用表达语言 {#validating-admission-policies-and-the-common-expression-language} + +Kubernetes 1.26 版本引入了一个折中的、Alpha 状态的解决方案。 +[验证准入策略](/zh-cn/docs/reference/access-authn-authz/validating-admission-policy/)是一种声明式的、 +进程内的方案,用来替代验证准入 Webhook。使用[通用表达语言](https://github.com/google/cel-spec) +(Common Expression Language,CEL) 来声明策略的验证规则。 + + +CEL 是由 Google 根据 Firebase 实时数据库的经验,针对安全和策略用例而开发的。 +它的设计使得它可以安全地嵌入到应用程序中,执行时间在微秒量级,对计算和内存的影响很小。 +v1.23 版本中,[针对 CRD 的验证规则](/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules)将 +CEL 引入了 Kubernetes 生态系统,当时人们注意到该语言将适合实现通过准入控制进行更通用的验证。 + + +## 让 CEL 发挥作用——一个实际例子 {#giving-cel-a-roll-a-practical-example} + +[Kubescape](https://github.com/kubescape/kubescape) 是一个 CNCF 项目, +已成为用户改善 Kubernetes 集群安全状况并验证其合规性的最流行方法之一。 +它的[控件](https://github.com/kubescape/regolibrary)——针对 API 对象的多组测试——是用 +Open Policy Agent 的策略语言 [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) 构建的。 + + +Rego 以复杂性著称,这主要是因为它是一种声明式查询语言(如 SQL)。 +它[被考虑](https://github.com/kubernetes/enhancements/blob/499e28/keps/sig-api-machinery/2876-crd-validation-expression-language/README.md#alternatives)在 +Kubernetes 中使用,但它没有提供与 CEL 相同的沙箱约束。 + + +该项目的一个常见功能要求是能够根据 Kubescape 的发现和输出来实现策略。例如,在扫描 Pod +是否存在[云凭据文件的已知路径](https://hub.armosec.io/docs/c-0020)后, +用户希望能够执行完全不允许这些 Pod 进入的策略。 +Kubescape 团队认为这是一个绝佳的机会,可以尝试将现有的控制措施移植到 CEL,并将其应用为准入策略。 + + +### 策略展示 {#show-me-the-policy} + +我们很快就转换了许多控件并建立了一个验证准入策略的库。让我们看一个例子。 + + +Kubescape 的 [control C-0017](https://hub.armosec.io/docs/c-0017) 涵盖了容器具有不可变(只读)根文件系统的要求。 +根据 [NSA Kubernetes 强化指南](/blog/2021/10/05/nsa-cisa-kubernetes-hardening-guidance/#immutable-container-filesystems), +这是最佳实践,但目前不要求将其作为任何 [Pod 安全标准](/zh-cn/docs/concepts/security/pod-security-standards/)的一部分。 + + +以下是我们用 CEL 的实现方式: + +```yaml +apiVersion: admissionregistration.k8s.io/v1alpha1 +kind: ValidatingAdmissionPolicy +metadata: + name: "kubescape-c-0017-deny-resources-with-mutable-container-filesystem" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["pods"] + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments","replicasets","daemonsets","statefulsets"] + - apiGroups: ["batch"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["jobs","cronjobs"] + validations: + - expression: "object.kind != 'Pod' || object.spec.containers.all(container, has(container.securityContext) && has(container.securityContext.readOnlyRootFilesystem) && container.securityContext.readOnlyRootFilesystem == true)" + message: "Pods having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)" + - expression: "['Deployment','ReplicaSet','DaemonSet','StatefulSet','Job'].all(kind, object.kind != kind) || object.spec.template.spec.containers.all(container, has(container.securityContext) && has(container.securityContext.readOnlyRootFilesystem) && container.securityContext.readOnlyRootFilesystem == true)" + message: "Workloads having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)" + - expression: "object.kind != 'CronJob' || object.spec.jobTemplate.spec.template.spec.containers.all(container, has(container.securityContext) && has(container.securityContext.readOnlyRootFilesystem) && container.securityContext.readOnlyRootFilesystem == true)" + message: "CronJob having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)" +``` + + +此策略为三个可能的 API 组提供匹配约束:Pod 的 `core/v1` 组、负载控制器的 `apps/v1` +和作业控制器的 `batch/v1`。 + +{{< note >}} + +`matchConstraints` 会为你将 API 对象转换为匹配的版本。例如,如果 API 请求的对象是 `apps/v1beta1`, +而你在 matchConstraints 中要匹配 `apps/v1`,那么 API 请求就会从 `apps/v1beta1` 转换为 `apps/v1` 然后进行验证。 +这样做的好处是可以确保验证规则不会被引入新版本的 API 所破坏,否则 API 请求就会通过使用新引入的版本而躲过验证规则的检查。 +{{< /note >}} + + +其中 `validations` 包括对象的 CEL 规则。有三种不同的表达方式,以满足 Pod `spec` +可以位于对象的根部([独立的 Pod](/zh-cn/docs/concepts/configuration/overview/#naked-pods-vs-replicasets-deployments-and-jobs))、 +在 `template` 下(负载控制器或作业)或位于 `jobTemplate`(CronJob)下的情况。 + + +如果任何一个 `spec` 没有将 `readOnlyRootFilesystem` 设为 true,则该对象将不会被接受。 + +{{< note >}} + +在最初的版本中,我们将这三个表达式分组到同一个策略对象中。这意味着可以原子性地启用和禁用它们, +因此不会出现以下情况:用户启用一个 API 组的策略而未启用其他组的策略,从而不小心留下合规性漏洞。 +将它们分成单独的策略将使我们能够使用针对 1.27 版本所作的改进,包括类型检查。 +我们正在与 SIG API Machinery 讨论如何在 API 达到 `v1` 之前最好地解决这个问题。 +{{< /note >}} + + +### 在集群中使用 CEL 库 {#using-the-cel-library-in-your-cluster} + +策略以 Kubernetes 对象的形式提供,并通过[选择算符](/zh-cn/docs/concepts/overview/working-with-objects/labels/#label-selectors)绑定到某些资源。 + + +[Minikube](https://minikube.sigs.k8s.io/docs/) 是一种安装和配置 Kubernetes 集群以进行测试的快速简便的方法。 +安装 Kubernetes v1.26 并启用[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/) +`ValidatingAdmissionPolicy`: + +```shell +minikube start --kubernetes-version=1.26.1 --extra-config=apiserver.runtime-config=admissionregistration.k8s.io/v1alpha1 --feature-gates='ValidatingAdmissionPolicy=true' +``` + + +要在集群中安装策略: + +```shell +# 安装配置 CRD +kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/policy-configuration-definition.yaml +# 安装基础配置 +kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/basic-control-configuration.yaml +# 安装策略 +kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/kubescape-validating-admission-policies.yaml +``` + + +要将策略应用到对象,请创建一个 `ValidatingAdmissionPolicyBinding` 资源。 +让我们把上述 Kubescape C-0017 控件应用到所有带有标签 `policy=enforced` 的命名空间: + + +```shell +# 创建绑定 +kubectl apply -f - < +现在,如果尝试创建一个对象但不指定 `readOnlyRootFilesystem`,该对象将不会被创建。 + +```shell +# 如下命令会失败 +kubectl -n policy-example run nginx --image=nginx --restart=Never +``` + + +输出错误信息: + +``` +The pods "nginx" is invalid: : ValidatingAdmissionPolicy 'kubescape-c-0017-deny-mutable-container-filesystem' with binding 'c0017-binding' denied request: Pods having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017) +``` + + +### 配置 + +策略对象可以包括在不同对象中提供的配置。许多 Kubescape 控件需要配置: +需要哪些标签、允许或拒绝哪些权能、允许从哪些镜像库部署容器等。 +这些控件的默认值在 [ControlConfiguration 对象](https://github.com/kubescape/cel-admission-library/blob/main/configuration/basic-control-configuration.yaml)中定义。 + + +要使用这个配置对象,或者以相同的格式使用你自己的对象,在你绑定对象中添加一个 `paramRef.name` 值: + +```yaml +apiVersion: admissionregistration.k8s.io/v1alpha1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: c0001-binding +spec: + policyName: kubescape-c-0001-deny-forbidden-container-registries + paramRef: + name: basic-control-configuration + matchResources: + namespaceSelector: + matchLabels: + policy: enforced +``` + + +## 总结 {#summary} + +在大多数情况下,将我们的控件转换为 CEL 很简单。我们无法移植整个 Kubescape 库,因为有些控件会检查 +Kubernetes 集群外部的事物,有些控件需要访问准入请求对象中不可用的数据。 +总的来说,我们很高兴将这个库贡献给 Kubernetes 社区,并将继续为 Kubescape 和 Kubernetes 用户开发它。 +我们希望它能成为有用的工具,既可以作为你自己使用的工具,也可以作为你编写自己的策略的范例。 + + +至于验证准入策略功能本身,我们很高兴看到 Kubernetes 引入这一原生功能。 +我们期待看到它进入 Beta 版,然后进入 GA 版,希望能在今年年底前完成。 +值得注意的是,该功能目前还处于 Alpha 阶段,这意味着这是在 Minikube 等环境中试用该功能的绝佳机会。 +然而,它尚未被视为生产就绪且稳定,且不会在大多数托管的 Kubernetes 环境中启用。 +底层功能变得稳定之前,我们不会建议 Kubescape 用户在生产环境中使用这些策略。 +请密切关注 [KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/3488-cel-admission-control/README.md), +当然还有此博客,以获取最终的发布公告。 \ No newline at end of file