授权

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

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

有关授权如何在 API 访问控制的更广泛背景下运作的概述,请阅读 控制对 Kubernetes API 的访问

授权裁决

Kubernetes 对 API 请求的授权在 API 服务器内进行。API 服务器会将所有请求属性与所有策略进行评估,并可能还会咨询外部服务,然后允许或拒绝请求。

API 请求的所有部分都必须通过某些授权机制才能继续。换句话说:默认情况下拒绝访问。

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

授权中使用的请求属性

Kubernetes 仅审查以下 API 请求属性

  • 用户 - 身份验证期间提供的用户字符串。
  • - 经过身份验证的用户所属的组名称列表。
  • 额外 - 身份验证层提供的任意字符串键到字符串值的映射。
  • 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
GETHEADget(对于单个资源)、list(对于集合,包括完整对象内容)、watch(用于监视单个资源或资源集合)
PUTupdate
PATCHpatch
DELETEdelete(对于单个资源)、deletecollection(对于集合)

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

  • 特殊情况下的 身份验证
    • 核心 API 组中usersgroupsserviceaccounts上的impersonate动词,以及authentication.k8s.io API 组中的userextras
  • 证书签名请求的授权
    • 证书签名请求的approve动词,以及对现有批准的修订的update
  • RBAC
    • rbac.authorization.k8s.io API 组中rolesclusterroles资源上的bindescalate动词。

授权上下文

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 服务响应查询。您可以编写自己的软件来处理调用,或使用生态系统中的解决方案。

授权模式配置

您可以使用 命令行参数 或(作为一项测试功能)使用 配置文件 来配置 Kubernetes API 服务器的授权器链。

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

命令行授权模式配置

功能状态: Kubernetes v1.8 [稳定]

您可以使用以下模式

  • --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 参考

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

功能状态: Kubernetes v1.30 [测试]

作为一项测试功能,Kubernetes 允许您配置可以包含多个 webhooks 的授权链。该链中的授权项可以具有明确定义的参数,以特定顺序验证请求,为您提供细粒度的控制,例如在失败时明确拒绝。

配置文件方法甚至允许您指定 CEL 规则,以便在将请求分派到 webhooks 之前预先筛选请求,帮助您防止不必要的调用。API 服务器还会在修改配置文件时自动重新加载授权器链。

您可以使用 --authorization-config 命令行参数指定授权配置的路径。

如果您想使用命令行参数而不是配置文件,这也是一种有效且受支持的方法。某些授权功能(例如:多个 webhooks、webhook 失败策略和预筛选规则)仅在您使用授权配置文件时才可用。

示例配置

---
#
# DO NOT USE THE CONFIG AS IS. THIS IS AN EXAMPLE.
#
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:
        # - KubeConfig: 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: KubeConfig
        # Path to KubeConfigFile for connection info
        # Required, if connectionInfo.Type is KubeConfig
        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.user.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.29 升级到 Kubernetes 1.30,您需要确保配置文件采用 Kubernetes 1.30 可以理解的格式,然后再升级集群。如果您降级到 1.29,您需要适当地设置配置。

授权配置和重新加载

当 API 服务器观察到文件发生更改时,Kubernetes 会重新加载授权配置文件,如果未观察到更改事件,还会按 60 秒的计划重新加载。

通过工作负载创建或编辑进行特权升级

可以创建/编辑命名空间中的 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

下一步

上次修改时间:2024 年 5 月 12 日下午 2:28 PST:修复 authorization.md 中的标题 (8201801a97)