授权
Kubernetes 授权发生在身份认证之后。通常,客户端发出请求后,必须先进行身份认证(登录),然后才能允许其请求;但是,在某些情况下,Kubernetes 也允许匿名请求。
有关授权如何融入更广泛的 API 访问控制上下文的概述,请阅读控制对 Kubernetes API 的访问。
授权裁决
Kubernetes API 请求的授权发生在 API 服务器内部。API 服务器根据所有策略评估所有请求属性,可能还会咨询外部服务,然后允许或拒绝请求。
API 请求的所有部分都必须通过某种授权机制允许才能继续。换句话说:默认情况下,访问是被拒绝的。
配置多个授权模块时,将依次检查每个模块。如果任何授权器**批准**或**拒绝**请求,则该决定会立即返回,并且不再咨询其他授权器。如果所有模块都对请求**没有意见**,则该请求将被拒绝。总体拒绝裁决意味着 API 服务器拒绝请求并以 HTTP 403 (Forbidden) 状态响应。
授权中使用的请求属性
Kubernetes 仅审查以下 API 请求属性:
- 用户 - 身份认证期间提供的 `user` 字符串。
- 组 - 已认证用户所属的组名称列表。
- 额外信息 - 身份认证层提供的任意字符串键到字符串值的映射。
- API - 指示请求是否用于 API 资源。
- 请求路径 - 指向杂项非资源端点的路径,如 `/api` 或 `/healthz`。
- API 请求动词 - API 动词,如 `get`、`list`、`create`、`update`、`patch`、`watch`、`delete` 和 `deletecollection` 用于资源请求。要确定资源 API 端点的请求动词,请参阅请求动词和授权。
- HTTP 请求动词 - 小写的 HTTP 方法,如 `get`、`post`、`put` 和 `delete` 用于非资源请求。
- 资源 - 正在访问的资源的 ID 或名称(仅适用于资源请求)——对于使用 `get`、`update`、`patch` 和 `delete` 动词的资源请求,你必须提供资源名称。
- 子资源 - 正在访问的子资源(仅适用于资源请求)。
- 命名空间 - 正在访问的对象的命名空间(仅适用于命名空间资源请求)。
- API 组 - 正在访问的API 组(仅适用于资源请求)。空字符串表示**核心**API 组。
请求动词和授权
非资源请求
对除 `/api/v1/...` 或 `/apis/
资源请求
为了确定资源 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 有时会使用专用动词检查额外权限的授权。例如:
- 身份认证的特殊情况
- 核心 API 组中 `users`、`groups` 和 `serviceaccounts` 上的 **impersonate** 动词,以及 `authentication.k8s.io` API 组中的 `userextras`。
- CertificateSigningRequest 的授权
- CertificateSigningRequests 的 **approve** 动词,以及现有批准修订的 **update** 动词。
- RBAC
- `rbac.authorization.k8s.io` API 组中 `roles` 和 `clusterroles` 资源上的 **bind** 和 **escalate** 动词。
授权上下文
Kubernetes 期望 REST API 请求共有的属性。这意味着 Kubernetes 授权与现有组织范围或云提供商范围的访问控制系统协同工作,这些系统除了 Kubernetes API 之外还可能处理其他 API。
授权模式
Kubernetes API 服务器可以使用以下几种授权模式之一来授权请求:
AlwaysAllow
- 此模式允许所有请求,这带来了安全风险。仅当你不需要对 API 请求进行授权时(例如,用于测试)才使用此授权模式。
AlwaysDeny
- 此模式阻止所有请求。仅用于测试时使用此授权模式。
- `ABAC`(基于属性的访问控制)
- Kubernetes ABAC 模式定义了一种访问控制范例,通过结合属性的策略授予用户访问权限。策略可以使用任何类型的属性(用户属性、资源属性、对象、环境属性等)。
- `RBAC`(基于角色的访问控制)
- Kubernetes RBAC 是一种根据企业内个人用户的角色来管理对计算机或网络资源的访问的方法。在此上下文中,访问是指单个用户执行特定任务的能力,例如查看、创建或修改文件。
在此模式下,Kubernetes 使用 `rbac.authorization.k8s.io` API 组来驱动授权决策,允许你通过 Kubernetes API 动态配置权限策略。 Node
- 一种特殊用途的授权模式,根据 kubelet 计划运行的 Pods 授予 kubelet 权限。要了解有关节点授权模式的更多信息,请参阅节点授权。
Webhook
- Kubernetes Webhook 模式用于授权,它会进行同步 HTTP 回调,阻塞请求直到远程 HTTP 服务响应查询。你可以编写自己的软件来处理回调,也可以使用生态系统中的解决方案。
警告
启用 `AlwaysAllow` 模式会绕过授权;如果群集中**所有**潜在的 API 客户端(包括你运行的工作负载)都不可信,请勿使用此模式。
授权机制通常返回**拒绝**或**无意见**结果;有关此内容的更多信息,请参阅授权裁决。激活 `AlwaysAllow` 意味着如果所有其他授权器都返回“无意见”,则允许请求。例如,`--authorization-mode=AlwaysAllow,RBAC` 与 `--authorization-mode=AlwaysAllow` 具有相同的效果,因为 Kubernetes RBAC 不提供负面(拒绝)访问规则。
你不应在 API 服务器可以通过公共互联网访问的 Kubernetes 集群上使用 `AlwaysAllow` 模式。
`system:masters` 组
`system:masters` 组是 Kubernetes 内置组,它授予对 API 服务器的无限制访问权限。分配给此组的任何用户都拥有完整的集群管理员权限,绕过 RBAC 或 Webhook 机制施加的任何授权限制。避免将用户添加到此组。如果你确实需要授予用户集群管理员权限,可以创建指向内置 `cluster-admin` ClusterRole 的ClusterRoleBinding。
授权模式配置
你可以使用配置文件或命令行参数来配置 Kubernetes API 服务器的授权器链。
你必须选择两种配置方法之一;不允许同时设置 `--authorization-config` 路径并使用 `--authorization-mode` 和 `--authorization-webhook-*` 命令行参数配置授权 Webhook。如果你尝试这样做,API 服务器将在启动期间报告错误消息,然后立即退出。
使用授权配置文件配置 API 服务器
Kubernetes v1.32 [stable]
(默认启用:true)Kubernetes 允许你配置可包含多个 Webhook 的授权链。该链中的授权项可以具有定义明确的参数,以特定顺序验证请求,从而为你提供精细的控制,例如在失败时明确拒绝。
配置文件方法甚至允许你指定CEL 规则来预过滤请求,然后再将其分派给 Webhook,从而帮助你防止不必要的调用。当配置文件被修改时,API 服务器还会自动重新加载授权器链。
你使用 `--authorization-config` 命令行参数指定授权配置文件的路径。
如果你想使用命令行参数而不是配置文件,这也是一种有效且受支持的方法。某些授权功能(例如:多个 Webhook、Webhook 故障策略和预过滤规则)仅在使用授权配置文件时才可用。
配置示例
---
#
# DO NOT USE THE CONFIG AS IS. THIS IS AN EXAMPLE.
#
apiVersion: apiserver.config.k8s.io/v1
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
# If set to false, 'authorized' responses from the webhook are not cached
# and the specified authorizedTTL is ignored/has no effect.
# Same as setting `--authorization-webhook-cache-authorized-ttl` flag to `0`.
# Note: Setting authorizedTTL to `0` results in its default value being used.
# Default: true
cacheAuthorizedRequests: true
# The duration to cache 'unauthorized' responses from the webhook
# authorizer.
# Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
# Default: 30s
unauthorizedTTL: 30s
# If set to false, 'unauthorized' responses from the webhook are not cached
# and the specified unauthorizedTTL is ignored/has no effect.
# Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag to `0`.
# Note: Setting unauthorizedTTL to `0` results in its default value being used.
# Default: true
cacheUnauthorizedRequests: true
# 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
使用配置文件配置授权器链时,请确保所有控制平面节点都具有相同的文件内容。在升级/降级集群时,请注意 API 服务器配置。例如,如果从 Kubernetes 1.33 升级到 Kubernetes 1.34,你需要确保配置文件采用 Kubernetes 1.34 可以理解的格式,然后才能升级集群。如果降级到 1.33,你需要适当地设置配置。
授权配置和重新加载
当 API 服务器观察到文件更改时,Kubernetes 会重新加载授权配置文件;如果在 60 秒内没有观察到更改事件,也会按 60 秒的计划重新加载。
注意
你必须确保所有非 Webhook 授权器类型在重新加载时在文件中保持不变。
重新加载**不能**添加或删除 Node 或 RBAC 授权器(它们可以重新排序,但不能添加或删除)。
命令行授权模式配置
你可以使用以下模式:
- `--authorization-mode=ABAC`(基于属性的访问控制模式)
- `--authorization-mode=RBAC`(基于角色的访问控制模式)
- `--authorization-mode=Node`(节点授权器)
- `--authorization-mode=Webhook`(Webhook 授权模式)
- `--authorization-mode=AlwaysAllow`(始终允许请求;存在安全风险)
- `--authorization-mode=AlwaysDeny`(始终拒绝请求)
你可以选择多种授权模式;例如:`--authorization-mode=Node,RBAC,Webhook`
Kubernetes 根据你在 API 服务器命令行上指定的顺序检查授权模块,因此较早的模块具有更高的优先级来允许或拒绝请求。
你不能将 `--authorization-mode` 命令行参数与用于使用本地文件配置授权的 `--authorization-config` 命令行参数结合使用。
有关 API 服务器命令行参数的更多信息,请阅读 `kube-apiserver` 参考。
通过创建或编辑工作负载进行特权升级
允许在命名空间中创建/编辑 Pods 的用户(无论是直接还是通过启用间接工作负载管理的对象)可能能够升级他们在该命名空间中的特权。潜在的特权升级途径包括 Kubernetes API 扩展及其关联的控制器。
注意
作为集群管理员,在授予创建或编辑工作负载的权限时要小心。有关如何滥用这些权限的一些详细信息记录在升级路径中。升级路径
如果你允许攻击者或不可信用户在该命名空间中运行任意 Pods,那么他们可以通过以下不同方式在该命名空间中获得额外特权:
- 在该命名空间中挂载任意 Secret
- 可用于访问为其他工作负载准备的机密信息
- 可用于获取权限更高的 ServiceAccount 的服务账户令牌
- 在该命名空间中使用任意 ServiceAccounts
- 可以作为其他工作负载执行 Kubernetes API 操作(模拟)
- 可以执行该 ServiceAccount 拥有的任何特权操作
- 挂载或使用为该命名空间中其他工作负载准备的 ConfigMaps
- 可用于获取为其他工作负载准备的信息,例如数据库主机名。
- 在该命名空间中挂载为其他工作负载准备的卷
- 可用于获取为其他工作负载准备的信息,并对其进行更改。
注意
作为系统管理员,在部署允许用户更改上述区域的 CustomResourceDefinitions 时,应该谨慎。这些可能会打开特权升级路径。在决定授权控制时,请考虑此类更改的后果。检查 API 访问
`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
管理员可以将其与用户模拟结合使用,以确定其他用户可以执行哪些操作。
kubectl auth can-i list secrets --namespace dev --as dave
输出类似于:
no
类似地,要检查命名空间 `dev` 中的名为 `dev-sa` 的 ServiceAccount 是否可以在命名空间 `target` 中列出 Pods:
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 隐藏/显示操作很有用。
这些 API 可以通过创建正常的 Kubernetes 资源进行查询,其中返回对象的响应 `status` 字段是查询结果。例如:
kubectl create -f - -o yaml << EOF
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
spec:
resourceAttributes:
group: apps
resource: deployments
verb: create
namespace: dev
EOF
生成的 SelfSubjectAccessReview 类似于:
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
metadata:
creationTimestamp: null
spec:
resourceAttributes:
group: apps
resource: deployments
namespace: dev
verb: create
status:
allowed: true
denied: false
下一步
- 要了解有关身份认证的更多信息,请参阅身份认证。
- 有关概述,请阅读控制对 Kubernetes API 的访问。
- 要了解有关准入控制的更多信息,请参阅使用准入控制器。
- 阅读有关Kubernetes 中的通用表达式语言的更多信息。