Kubernetes 鉴权在身份认证之后进行。 通常,发出请求的客户端必须经过身份验证(登录)才能允许其请求; 但是,Kubernetes 在某些情况下也允许匿名请求。
有关鉴权在 API 访问控制中的位置这类进一步的语境信息, 请阅读控制对 Kubernetes API 的访问。
Kubernetes 对 API 请求的鉴权在 API 服务器内进行。 API 服务器根据所有策略评估所有请求属性,可能还会咨询外部服务,然后允许或拒绝该请求。
API 请求的所有部分都必须通过某种鉴权机制才能继续, 换句话说:默认情况下拒绝访问。
当系统配置了多个鉴权模块时,Kubernetes 将按顺序使用每个模块。 如果任何鉴权模块批准或拒绝请求,则立即返回该决定,并且不会与其他鉴权模块协商。 如果所有模块对请求没有意见,则拒绝该请求。 总体拒绝裁决意味着 API 服务器拒绝请求并以 HTTP 403(禁止)状态进行响应。
Kubernetes 仅审查以下 API 请求属性:
user 字符串。/api 或 /healthz。get、list、create、update、patch、watch、
proxy、redirect、delete 和 deletecollection 用于资源请求。
要确定资源 API 端点的请求动词,请参阅请求动词和鉴权。get、post、put 和 delete 用于非资源请求。get、update、patch 和 delete 动词的资源请求,你必须提供资源名称。对于 /api/v1/... 或 /apis/<group>/<version>/...
之外的端点的请求被视为非资源请求(Non-Resource Requests),
并使用该请求的 HTTP 方法的小写形式作为其请求动词。
例如,对 /api 或 /healthz 这类端点的 GET 请求将使用 get 作为其动词。
为了确定资源 API 端点的请求动词,Kubernetes 会映射所使用的 HTTP 动词, 并考虑该请求是否作用于单个资源或资源集合:
| HTTP 动词 | 请求动词 |
|---|---|
POST |
create |
GET、HEAD |
get(针对单个资源)、list(针对集合,包括完整的对象内容)、watch(用于查看单个资源或资源集合) |
PUT |
update |
PATCH |
patch |
DELETE |
delete(针对单个资源)、deletecollection(针对集合) |
get、list 和 watch 动作都可以返回一个资源的完整详细信息。就返回的数据而言,它们是等价的。 例如,对 secrets 使用 list 仍然会显示所有已返回资源的 data 属性。
Kubernetes 有时使用专门的动词以对额外的权限进行鉴权。例如:
users、groups 和 serviceaccounts 以及 authentication.k8s.io
API 组中的 userextras 所使用的 impersonate 动词。rbac.authorization.k8s.io API 组中 roles 和 clusterroles 资源的 bind
和 escalate 动词Kubernetes 需要 REST API 请求所共有的属性, 这意味着 Kubernetes 鉴权可与现有的组织范围或云提供商范围的访问控制系统配合使用, 这些系统可以处理除 Kubernetes API 之外的其他 API。
AlwaysAllowAlwaysDenyABAC(基于属性的访问控制)RBAC(基于角色的访问控制)rbac.authorization.k8s.io API 组来驱动鉴权决策,
允许你通过 Kubernetes API 动态配置权限策略。NodeWebhook启用 AlwaysAllow 模式会绕过鉴权;请勿在你不信任所有潜在 API
客户端(包括你运行的工作负载)的集群上使用该模式。
鉴权机制通常返回“拒绝”或“无意见”的结果;
有关更多信息,请参阅鉴权裁决。
激活 AlwaysAllow 意味着如果所有其他鉴权组件都返回“无意见”,则允许该请求。
例如,--authorization-mode=AlwaysAllow,RBAC 与 --authorization-mode=AlwaysAllow
具有相同的效果,因为 Kubernetes RBAC 不提供否定(拒绝)访问规则。
你不应在可从公共互联网访问 API 服务器的 Kubernetes 集群上使用 AlwaysAllow 模式。
system:masters 组system:masters 组是 Kubernetes 内置的一个组,授予其成员对 API 服务器的无限制访问权限。
任何被分配到此组的用户都具有完全的集群管理员权限,可以绕过由 RBAC 或 Webhook 机制施加的任何鉴权限制。
请避免将用户添加到此组。
如果你确实需要授予某个用户集群管理员权限,可以通过创建一个
ClusterRoleBinding
将其绑定到内置的 cluster-admin ClusterRole。
你可以仅使用配置文件, 或使用命令行参数来配置 Kubernetes API 服务器的鉴权链。
你必须选择两种配置方法之一;不允许同时设置 --authorization-config 路径并使用
--authorization-mode 和 --authorization-webhook-* 命令行参数配置鉴权 Webhook。
如果你尝试这样做,API 服务器会在启动期间报告错误消息,然后立即退出。
Kubernetes v1.32 [stable](默认启用)Kubernetes 允许你配置可包含多个 Webhook 的鉴权链。 该链中的鉴权项可以具有明确定义的参数,这些参数可以按特定顺序检查请求, 从而为你提供细粒度的控制,例如在失败时明确拒绝。
配置文件方法甚至允许你指定 CEL 规则,在将请求发送到 Webhook 之前对其进行预过滤,从而帮助你防止不必要的调用。 修改配置文件时,API 服务器还会自动重新加载鉴权链。
你可以使用 --authorization-config 命令行参数指定鉴权配置的路径。
如果你想使用命令行参数而不是配置文件,这也是一种有效且受支持的方法。 某些鉴权功能(例如:多个 Webhook、Webhook 失败策略和预过滤规则)仅在使用鉴权配置文件时可用。
---
#
# 请勿按原样使用配置,这只是一个示例。
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthorizationConfiguration
authorizers:
- type: Webhook
# 用于描述鉴权人的名称
# 这明确用于监控机制的指标
# 注意
# - 该字段的验证与今天的 K8s 标签的验证方式类似。
# 必填,无默认值
name: webhook
webhook:
# 缓存来自 Webhook 鉴权组件的“鉴权”响应的持续时间
# 与设置 `--authorization-webhook-cache-authorized-ttl` 标志相同
# 默认值:5m0s
authorizedTTL: 30s
# 如果设置为 false,来自 Webhook 的 'authorized' 响应不会被缓存,
# 并且指定的 authorizedTTL 将被忽略/不起作用。
# 等同于将 `--authorization-webhook-cache-authorized-ttl` 标志设置为 `0`。
# 注意:将 authorizedTTL 设置为 `0` 会导致使用其默认值。
# 默认值:true
cacheAuthorizedRequests: true
# 缓存来自 Webhook 鉴权组件的“未授权”响应的持续时间。
# 与设置 `--authorization-webhook-cache-unauthorized-ttl` 标志相同
# 默认值:30s
unauthorizedTTL: 30s
# 如果设置为 false,来自 webhook 的 'unauthorized' 响应不会被缓存,
# 并且指定的 unauthorizedTTL 将被忽略/不起作用。
# 等同于将 `--authorization-webhook-cache-unauthorized-ttl` 标志设置为 `0`。
# 注意:将 unauthorizedTTL 设置为 `0` 会导致使用其默认值。
# 默认值:true
cacheUnauthorizedRequests: true
# Webhook 请求超时
# 允许的最大时间为 30 秒。
# 必填,没有默认值。
timeout: 3s
# 要发送到 Webhook 并期望从 webhook 获得的 authorization.k8s.io SubjectAccessReview 的 API 版本。
# 与设置 `--authorization-webhook-version` 标志相同
# 必填,无默认值
# 有效值:v1beta1、v1
subjectAccessReviewVersion: v1
# MatchConditionSubjectAccessReviewVersion 指定评估 CEL 表达式的 SubjectAccessReview 版本
# 有效值:v1
# 必填,无默认值
matchConditionSubjectAccessReviewVersion: v1
# 当 Webhook 请求无法完成或返回格式错误的响应或评估 matchConditions 时出现错误时,控制鉴权决定。
# 有效值:
# - NoOpinion:继续联系后续鉴权组件,看其中是否有人允许该请求
# - Deny:拒绝请求而不咨询后续鉴权组件
# 必填,没有默认值。
failurePolicy: Deny
connectionInfo:
# 控制 Webhook 如何与服务器通信。
# 有效值:
# - KubeConfigFile:使用 kubeConfigFile 中指定的文件来定位服务器。
# - InClusterConfig:使用集群内配置来调用由 kube-apiserver 托管的 SubjectAccessReview API,kube-apiserver 不允许使用此模式。
type: KubeConfigFile
# 连接信息的 KubeConfig 文件的路径
# 如果 connectionInfo.Type 是 KubeConfig,则为必填项
kubeConfigFile: /kube-system-authz-webhook.yaml
# matchConditions 是将请求发送到此 Webhook 必须满足的条件列表。
# matchConditions 为空列表表示匹配所有请求。
# 最多允许 64 个匹配条件。
#
# 精确匹配逻辑如下(按顺序):
# 1. 如果至少一个 matchCondition 计算结果为 FALSE,则跳过 Webhook。
# 2. 如果所有 matchConditions 计算结果为 TRUE,则调用 Webhook。
# 3. 如果至少一个 matchCondition 计算结果为错误(但没有一个为 FALSE):
# - 如果 FailurePolicy=Deny,则 Webhook 拒绝请求
# - 如果 FailurePolicy=NoOpinion,则忽略错误并跳过 Webhook
matchConditions:
# 表达式表示将由 CEL 评估的表达式。必须评估为布尔值。
# CEL 表达式可以访问 v1 版本中的 SubjectAccessReview 的内容。
# 如果请求变量中 subjectAccessReviewVersion 指定的版本是 v1beta1,
# 在评估 CEL 表达式之前,内容将转换为 v1 版本。
#
# CEL 文档:https://kubernetes.io/zh-cn/docs/reference/using-api/cel/
#
# 仅向 Webhook 发送资源请求
- expression: has(request.resourceAttributes)
# 仅拦截对 kube-system 的请求
- expression: request.resourceAttributes.namespace == 'kube-system'
# 不要拦截来自 kube-system 服务账户的请求
- 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使用配置文件配置鉴权链时,请确保所有控制平面节点具有相同的文件内容。升级/降级集群时,请记下 API 服务器配置。 例如,如果从 Kubernetes 1.34 升级到 Kubernetes 1.35,则需要确保配置文件的格式是 Kubernetes 1.35 可以理解的,然后再升级集群。 如果降级到 1.34,则需要适当设置配置。
当 API 服务器观察到文件的更改时,Kubernetes 会重新加载鉴权配置文件, 如果没有观察到更改事件,则也会按照 60 秒的计划重新加载。
你必须确保重新加载时文件中所有非 Webhook 鉴权组件类型保持不变。
重新加载不能添加或删除节点或 RBAC 鉴权组件(可以重新排序,但不能添加或删除)。
你可以使用以下模式:
--authorization-mode=ABAC(基于属性的访问控制模式)--authorization-mode=RBAC(基于角色的访问控制模式)--authorization-mode=Node(节点鉴权组件)--authorization-mode=Webhook(Webhook 鉴权模式)--authorization-mode=AlwaysAllow(始终允许请求;存在安全风险)--authorization-mode=AlwaysDeny(始终拒绝请求)你可以选择多种鉴权模式;例如:--authorization-mode=Node,Webhook
Kubernetes 根据你在 API 服务器的命令行上指定鉴权模块的顺序来检查鉴权模块, 因此较早的模块具有更高的优先级来允许或拒绝请求。
你不能将 --authorization-mode 命令行参数与用于使用本地文件配置鉴权的
--authorization-config 命令行参数结合使用。
有关 API 服务器命令行参数的更多信息,请阅读
kube-apiserver 参考。
能够直接或通过启用间接工作负载管理的对象在命名空间中创建/编辑 Pod 的用户可能能够在该命名空间中提升其权限。 权限提升的潜在途径包括 Kubernetes API 扩展及其相关的 控制器。
作为集群管理员,授予创建或编辑工作负载的访问权限时请务必小心谨慎。 权限提升路径中记录了有关滥用这些内容的一些细节。
如果你允许攻击者或不值得信任的用户在该命名空间中运行任意 Pod, 则他们可以通过不同的方式在命名空间内获得额外的权限:
作为系统管理员,在部署允许用户更改上述区域的 CustomResourceDefinitions 时应谨慎行事, 这些可能会打开特权升级路径。在配置你的鉴权控制时,请考虑这种变化的后果。
kubectl 提供 auth can-i 子命令,用于快速查询 API 鉴权。
该命令使用 SelfSubjectAccessReview API 来确定当前用户是否可以执行给定操作,
无论使用何种鉴权模式该命令都可以工作。
kubectl auth can-i create deployments --namespace dev
输出类似于:
yes
kubectl auth can-i create deployments --namespace prod
输出类似于:
no
管理员可以将此与用户扮演(User Impersonation) 结合使用,以确定其他用户可以执行的操作。
kubectl auth can-i list secrets --namespace dev --as dave
输出类似于:
no
类似地,检查名字空间 dev 里的 dev-sa 服务账户是否可以列举名字空间
target 里的 Pod:
kubectl auth can-i list pods \
--namespace target \
--as system:serviceaccount:dev:dev-sa
输出类似于:
yes
SelfSubjectAccessReview 是 authorization.k8s.io API 组的一部分,它将 API
服务器鉴权公开给外部服务。该组中的其他资源包括:
SubjectAccessReview
: 对任意用户的访问进行评估,而不仅仅是当前用户。
当鉴权决策被委派给 API 服务器时很有用。例如,kubelet 和扩展 API
服务器使用它来确定用户对自己的 API 的访问权限。
LocalSubjectAccessReview
: 与 SubjectAccessReview 类似,但仅限于特定的名字空间。
SelfSubjectRulesReview
: 返回用户可在名字空间内执行的操作集的审阅。
用户可以快速汇总自己的访问权限,或者用于 UI 中的隐藏/显示动作。
可以通过创建普通的 Kubernetes 资源来查询这些 API,其中返回对象的响应 status
字段是查询的结果,例如:
kubectl create -f - -o yaml << EOF
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
spec:
resourceAttributes:
group: apps
name: deployments
verb: create
namespace: dev
EOF
生成的 SelfSubjectAccessReview 类似于:
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
metadata:
creationTimestamp: null
spec:
resourceAttributes:
group: apps
name: deployments
namespace: dev
verb: create
status:
allowed: true
denied: false