Kubernetes 1.30:多 Webhook 和模块化授权变得更加容易
随着 Kubernetes 1.30 发布,我们 (SIG Auth) 将结构化授权配置(Structured Authorization Configuration)提升至 Beta 阶段。
今天的文章重点讨论**授权**(authorization):决定某人可以访问哪些内容和不能访问哪些内容。你可以查看昨天的一篇文章,了解 Kubernetes v1.30 在**认证**(authentication,即确定执行任务的人是谁,并验证其身份)方面的新特性。
引言
为了满足系统管理员和开发人员日益复杂的需求,Kubernetes 不断演进。API 服务器授权是确保集群安全性和完整性的关键方面。直到最近,kube-apiserver 中授权链的配置还相对严格,仅限于一组命令行标志,并且授权链中只允许一个 webhook。虽然这种方法功能正常,但限制了集群管理员定义复杂、细粒度授权策略所需的灵活性。最新的结构化授权配置(Structured Authorization Configuration)功能(KEP-3221)旨在通过引入一种更结构化、更灵活的方式来配置授权链,从而彻底改变这一方面,重点是启用多个 webhook 并提供明确的控制机制。
改进的必要性
长期以来,集群管理员一直希望能够在 API 服务器处理链中指定多个授权 webhook,并能够控制每个 webhook 的详细行为,例如超时和失败策略。这种需求源于创建分层安全策略的需求,其中请求可以按照特定顺序针对多个标准或规则集进行验证。之前的限制也使得难以动态配置授权链,从而无法有效地管理复杂的授权场景。
结构化授权配置功能通过引入一种配置文件格式来配置 Kubernetes API 服务器授权链,解决了这些限制。此格式允许在授权链中指定多个 webhook(所有其他授权类型最多指定一次)。每个 webhook 授权器都有明确定义的参数,包括超时设置、失败策略以及使用 CEL 规则调用 webhook 的条件,以便在请求分发到 webhook 之前对其进行预过滤,帮助你避免不必要的调用。配置还支持自动重载,确保可以在不重启 kube-apiserver 的情况下动态应用更改。此功能解决了当前的限制,并为更有效地保护和管理 Kubernetes 集群开辟了新的可能性。
配置示例
下面是一个结构化授权配置示例,以及所有字段的描述、默认值和可能的值。
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthorizationConfiguration
authorizers:
- type: Webhook
# Name used to describe the authorizer
# This is explicitly used in monitoring machinery for metrics
# Note:
# - Validation for this field is similar to how K8s labels are validated today.
# Required, with no default
name: webhook
webhook:
# The duration to cache 'authorized' responses from the webhook
# authorizer.
# Same as setting `--authorization-webhook-cache-authorized-ttl` flag
# Default: 5m0s
authorizedTTL: 30s
# The duration to cache 'unauthorized' responses from the webhook
# authorizer.
# Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
# Default: 30s
unauthorizedTTL: 30s
# Timeout for the webhook request
# Maximum allowed is 30s.
# Required, with no default.
timeout: 3s
# The API version of the authorization.k8s.io SubjectAccessReview to
# send to and expect from the webhook.
# Same as setting `--authorization-webhook-version` flag
# Required, with no default
# Valid values: v1beta1, v1
subjectAccessReviewVersion: v1
# MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview
# version the CEL expressions are evaluated against
# Valid values: v1
# Required, no default value
matchConditionSubjectAccessReviewVersion: v1
# Controls the authorization decision when a webhook request fails to
# complete or returns a malformed response or errors evaluating
# matchConditions.
# Valid values:
# - NoOpinion: continue to subsequent authorizers to see if one of
# them allows the request
# - Deny: reject the request without consulting subsequent authorizers
# Required, with no default.
failurePolicy: Deny
connectionInfo:
# Controls how the webhook should communicate with the server.
# Valid values:
# - KubeConfigFile: use the file specified in kubeConfigFile to locate the
# server.
# - InClusterConfig: use the in-cluster configuration to call the
# SubjectAccessReview API hosted by kube-apiserver. This mode is not
# allowed for kube-apiserver.
type: KubeConfigFile
# Path to KubeConfigFile for connection info
# Required, if connectionInfo.Type is KubeConfigFile
kubeConfigFile: /kube-system-authz-webhook.yaml
# matchConditions is a list of conditions that must be met for a request to be sent to this
# webhook. An empty list of matchConditions matches all requests.
# There are a maximum of 64 match conditions allowed.
#
# The exact matching logic is (in order):
# 1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
# 2. If ALL matchConditions evaluate to TRUE, then the webhook is called.
# 3. If at least one matchCondition evaluates to an error (but none are FALSE):
# - If failurePolicy=Deny, then the webhook rejects the request
# - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
matchConditions:
# expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
# CEL expressions have access to the contents of the SubjectAccessReview in v1 version.
# If version specified by subjectAccessReviewVersion in the request variable is v1beta1,
# the contents would be converted to the v1 version before evaluating the CEL expression.
#
# Documentation on CEL: https://kubernetes.ac.cn/docs/reference/using-api/cel/
#
# only send resource requests to the webhook
- expression: has(request.resourceAttributes)
# only intercept requests to kube-system
- expression: request.resourceAttributes.namespace == 'kube-system'
# don't intercept requests from kube-system service accounts
- expression: "!('system:serviceaccounts:kube-system' in request.groups)"
- type: Node
name: node
- type: RBAC
name: rbac
- type: Webhook
name: in-cluster-authorizer
webhook:
authorizedTTL: 5m
unauthorizedTTL: 30s
timeout: 3s
subjectAccessReviewVersion: v1
failurePolicy: NoOpinion
connectionInfo:
type: InClusterConfig
以下配置示例说明了需要指定多个 webhook,并设置不同参数、优先级顺序和失败模式的实际场景。
保护已安装的 CRD
确保自定义资源定义(CRD)在集群启动时可用一直是一个关键需求。控制器协调这些 CRD 的一个障碍是缺乏保护机制,而这可以通过多个授权 webhook 来实现。以前这是不可能的,因为在 Kubernetes API 服务器授权链中指定多个授权 webhook 根本不可行。现在,借助结构化授权配置功能,管理员可以指定多个 webhook,从而在 RBAC 不足的情况下提供解决方案,特别是在拒绝 '非系统' 用户访问某些 CRD 的权限时。
此场景的假设如下
- “受保护”的 CRD 已安装。
- 它们只能由
admin
组中的用户修改。
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthorizationConfiguration
authorizers:
- type: Webhook
name: system-crd-protector
webhook:
unauthorizedTTL: 30s
timeout: 3s
subjectAccessReviewVersion: v1
matchConditionSubjectAccessReviewVersion: v1
failurePolicy: Deny
connectionInfo:
type: KubeConfigFile
kubeConfigFile: /files/kube-system-authz-webhook.yaml
matchConditions:
# only send resource requests to the webhook
- expression: has(request.resourceAttributes)
# only intercept requests for CRDs
- expression: request.resourceAttributes.resource.resource = "customresourcedefinitions"
- expression: request.resourceAttributes.resource.group = ""
# only intercept update, patch, delete, or deletecollection requests
- expression: request.resourceAttributes.verb in ['update', 'patch', 'delete','deletecollection']
- type: Node
- type: RBAC
防止不必要的嵌套 webhook
系统管理员希望在使用 Open Policy Agent 等框架将请求发送到 webhook 之前,对其应用特定的验证。过去,这需要在添加到授权链的 webhook 中运行嵌套 webhook 才能达到预期的结果。结构化授权配置功能简化了此过程,提供了结构化的 API,以便在需要时选择性地触发其他 webhook。它还允许管理员为每个 webhook 设置不同的失败策略,从而确保更一致和可预测的响应。
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthorizationConfiguration
authorizers:
- type: Webhook
name: system-crd-protector
webhook:
unauthorizedTTL: 30s
timeout: 3s
subjectAccessReviewVersion: v1
matchConditionSubjectAccessReviewVersion: v1
failurePolicy: Deny
connectionInfo:
type: KubeConfigFile
kubeConfigFile: /files/kube-system-authz-webhook.yaml
matchConditions:
# only send resource requests to the webhook
- expression: has(request.resourceAttributes)
# only intercept requests for CRDs
- expression: request.resourceAttributes.resource.resource = "customresourcedefinitions"
- expression: request.resourceAttributes.resource.group = ""
# only intercept update, patch, delete, or deletecollection requests
- expression: request.resourceAttributes.verb in ['update', 'patch', 'delete','deletecollection']
- type: Node
- type: RBAC
- name: opa
type: Webhook
webhook:
unauthorizedTTL: 30s
timeout: 3s
subjectAccessReviewVersion: v1
matchConditionSubjectAccessReviewVersion: v1
failurePolicy: Deny
connectionInfo:
type: KubeConfigFile
kubeConfigFile: /files/opa-default-authz-webhook.yaml
matchConditions:
# only send resource requests to the webhook
- expression: has(request.resourceAttributes)
# only intercept requests to default namespace
- expression: request.resourceAttributes.namespace == 'default'
# don't intercept requests from default service accounts
- expression: "!('system:serviceaccounts:default' in request.groups)"
下一步是什么?
从 Kubernetes 1.30 开始,此功能处于 Beta 阶段,并默认启用。对于 Kubernetes v1.31,我们预计此功能将继续处于 Beta 阶段,同时收集更多用户反馈。一旦准备好达到 GA 状态,功能标志将被移除,配置文件版本将升级到 v1。
在 Kubernetes 文档网站上了解有关此功能的更多信息:结构化授权配置。你还可以关注 KEP-3221,以便跟踪未来 Kubernetes 版本中的进展。
行动呼吁
在本文中,我们介绍了 Kubernetes v1.30 中结构化授权配置功能的优势以及一些实际场景的配置示例。要使用此功能,你必须使用 --authorization-config
命令行参数指定授权配置文件的路径。从 Kubernetes 1.30 开始,此功能处于 Beta 阶段,并默认启用。如果你想继续使用命令行标志而不是配置文件,它们仍将按原样工作。同时指定 --authorization-config
和 --authorization-modes
/--authorization-webhook-*
是无效的。你需要从 kube-apiserver 命令中移除旧的标志。
以下 kind 集群配置在 APIserver 上设置该命令行参数,以从文件目录中的文件(authorization_config.yaml
)加载 AuthorizationConfiguration。所有需要的 kubeconfig 和证书文件也可以放在 files 目录中。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
StructuredAuthorizationConfiguration: true # enabled by default in v1.30
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
metadata:
name: config
apiServer:
extraArgs:
authorization-config: "/files/authorization_config.yaml"
extraVolumes:
- name: files
hostPath: "/files"
mountPath: "/files"
readOnly: true
nodes:
- role: control-plane
extraMounts:
- hostPath: files
containerPath: /files
我们非常希望听到你对此功能的反馈。特别是,我们希望获得 Kubernetes 集群管理员和授权 webhook 实现者在与这个新 API 集成过程中的反馈。请通过 Kubernetes Slack 上的 #sig-auth-authorizers-dev 频道与我们联系。
如何参与
如果你有兴趣帮助开发此功能、分享反馈或参与任何其他正在进行的 SIG Auth 项目,请通过 Kubernetes Slack 上的 #sig-auth 频道与我们联系。
也欢迎你参加每隔一周周三举行的 SIG Auth 双周会议。
致谢
此功能由来自多家公司的贡献者共同推动完成。我们衷心感谢所有为此付出时间和精力的贡献者。