授权

Kubernetes 授权机制和支持的授权模式的详细信息。

Kubernetes 授权发生在认证之后。通常,发出请求的客户端必须先进行认证(登录),然后才能允许其请求;但是,Kubernetes 在某些情况下也允许匿名请求。

有关授权如何适应 API 访问控制的更广泛背景,请阅读 控制对 Kubernetes API 的访问

授权判决

Kubernetes API 请求的授权发生在 API 服务器内部。API 服务器会根据所有策略评估所有请求属性,可能还会咨询外部服务,然后允许或拒绝请求。

为了继续,API 请求的所有部分必须由某种授权机制允许。换句话说:默认情况下拒绝访问。

当配置了多个 授权模块时,每个模块都会按顺序进行检查。如果任何授权器批准拒绝请求,则立即返回该决策,并且不会咨询其他授权器。如果所有模块对请求没有意见,则请求将被拒绝。整体拒绝判决意味着 API 服务器会拒绝该请求并响应 HTTP 403(Forbidden)状态。

授权中使用的请求属性

Kubernetes 仅审查以下 API 请求属性

  • user - 认证期间提供的 user 字符串。
  • group - 经过身份验证的用户所属的组名称列表。
  • extra - 由认证层提供的任意字符串键到字符串值的映射。
  • API - 指示请求是否为 API 资源。
  • 请求路径 - 到各种非资源端点的路径,例如 /api/healthz
  • API 请求动词 - API 动词,例如 getlistcreateupdatepatchwatchdeletedeletecollection,用于资源请求。要确定资源 API 端点的请求动词,请参阅 请求动词和授权
  • HTTP 请求动词 - 用于非资源请求的小写 HTTP 方法,例如 getpostputdelete
  • 资源 - 正在访问的资源的 ID 或名称(仅用于资源请求)-- 对于使用 getupdatepatchdelete 动词的资源请求,必须提供资源名称。
  • 子资源 - 正在访问的子资源(仅用于资源请求)。
  • 命名空间 - 正在访问的对象的命名空间(仅用于命名空间资源请求)。
  • API 组 - 正在访问的 API 组(仅用于资源请求)。空字符串表示核心 API 组

请求动词和授权

非资源请求

对除 /api/v1/.../apis/<group>/<version>/... 之外的端点的请求被认为是非资源请求,并使用请求的 HTTP 方法的小写形式作为动词。例如,使用 HTTP 对 /api/healthz 等端点进行 GET 请求将使用 get 作为动词。

资源请求

要确定资源 API 端点的请求动词,Kubernetes 会映射使用的 HTTP 动词并考虑请求是作用于单个资源还是资源集合

HTTP 动词请求动词
POSTcreate
GET, HEADget(用于单个资源)、list(用于集合,包括完整对象内容)、watch(用于监视单个资源或资源集合)
PUTupdate
PATCHpatch
DELETEdelete(用于单个资源)、deletecollection(用于集合)

Kubernetes 有时会使用特殊的动词检查其他权限的授权。例如

  • 特殊情况的 认证
    • impersonate 动词用于核心 API 组中的 usersgroupsserviceaccounts,以及 authentication.k8s.io API 组中的 userextras
  • CertificateSigningRequests 的授权
    • approve 动词用于 CertificateSigningRequests,以及对现有批准的修订的 update
  • RBAC
    • bindescalate 动词用于 rbac.authorization.k8s.io API 组中的 rolesclusterroles 资源。

授权上下文

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
一种特殊用途的授权模式,根据计划运行的 Pod 向 kubelet 授予权限。要了解有关节点授权模式的更多信息,请参阅 节点授权
Webhook
Kubernetes webhook 模式用于授权,会发出同步 HTTP 调用,直到远程 HTTP 服务响应查询才会阻塞请求。您可以编写自己的软件来处理调用,或使用生态系统中的解决方案。

system:masters 组

system:masters 群组是一个 Kubernetes 内置群组,它授予对 API 服务器的无限制访问权限。分配到此群组的任何用户都具有完全的集群管理员权限,绕过 RBAC 或 Webhook 机制施加的任何授权限制。 避免将用户添加到此群组。如果您确实需要授予用户集群管理员权限,可以创建一个 ClusterRoleBinding 到内置的 cluster-admin ClusterRole。

授权模式配置

您可以使用 配置文件命令行参数 配置 Kubernetes API 服务器的授权器链。

您必须选择其中一种配置方法;同时设置 --authorization-config 路径并使用 --authorization-mode--authorization-webhook-* 命令行参数配置授权 webhook 是不允许的。如果您尝试这样做,API 服务器将在启动期间报告错误消息,然后立即退出。

使用授权配置文件配置 API 服务器

功能状态: Kubernetes v1.32 [稳定](默认启用)

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.34 升级到 Kubernetes 1.35,您需要在升级集群之前,确保配置文件是 Kubernetes 1.35 可以理解的格式。如果降级到 1.34,您需要相应地设置配置。

授权配置和重新加载

当 API 服务器检测到文件发生更改时,以及在没有观察到任何更改事件的情况下每 60 秒计划一次,Kubernetes 会重新加载授权配置文件。

命令行授权模式配置

您可以使用以下模式

  • --authorization-mode=ABAC(基于属性的访问控制模式)
  • --authorization-mode=RBAC(基于角色的访问控制模式)
  • --authorization-mode=Node(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 参考

通过工作负载创建或编辑进行权限提升

可以直接或通过启用间接 工作负载管理 的对象,可以在命名空间中创建/编辑 Pod 的用户,可能会在该命名空间中提升其权限。潜在的权限提升途径包括 Kubernetes API 扩展 及其相关的 控制器

权限提升路径

如果允许在命名空间中运行任意 Pod,攻击者或不可信用户可能会以不同的方式在该命名空间中获得额外的权限

  • 在命名空间中挂载任意 Secret
    • 可用于访问其他工作负载的机密信息
    • 可用于获取更特权 ServiceAccount 的服务帐户令牌
  • 在命名空间中使用任意 ServiceAccount
    • 可以作为另一个工作负载执行 Kubernetes API 操作(身份冒充)
    • 可以执行 ServiceAccount 具有的任何特权操作
  • 在命名空间中挂载或使用其他工作负载的 ConfigMap
    • 可用于获取其他工作负载的信息,例如数据库主机名。
  • 在命名空间中挂载其他工作负载的卷
    • 可用于获取其他工作负载的信息并更改它。

检查 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 中的 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
    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

接下来