身份验证

此页面概述了 Kubernetes 中的身份验证,重点是身份验证到 Kubernetes API

Kubernetes 中的用户

所有 Kubernetes 集群都有两类用户:由 Kubernetes 管理的服务帐户和普通用户。

假设一个与集群无关的服务管理普通用户,方式如下:

  • 管理员分发私钥
  • 像 Keystone 或 Google 帐户这样的用户存储
  • 包含用户名和密码列表的文件

因此,Kubernetes 没有表示普通用户帐户的对象。 普通用户不能通过 API 调用添加到集群。

即使不能通过 API 调用添加普通用户,但如果用户提供由集群证书颁发机构 (CA) 签名的有效证书,也被视为已通过身份验证。在这种配置中,Kubernetes 从证书的 'subject' 字段中的 common name 字段确定用户名(例如,“/CN=bob”)。然后,基于角色的访问控制 (RBAC) 子系统将确定用户是否有权对资源执行特定操作。

相反,服务帐户是由 Kubernetes API 管理的用户。它们绑定到特定的命名空间,并通过 API 服务器或通过 API 调用手动创建自动创建。

API 请求与普通用户或服务帐户相关联,或者被视为 匿名请求。这意味着集群内或集群外的每个进程,从工作站上键入 kubectl 的用户,到节点上的 kubelets,到控制平面的成员,都必须在向 API 服务器发出请求时进行身份验证,或者被视为匿名用户。

身份验证策略

Kubernetes 使用客户端证书、承载令牌或身份验证代理通过身份验证插件来验证 API 请求。当向 API 服务器发出 HTTP 请求时,插件尝试将以下属性与请求关联起来:

  • 用户名:标识最终用户的字符串。常见值可能是 kube-adminjane@example.com
  • UID:标识最终用户的字符串,并尝试比用户名更一致和唯一。
  • 组:一组字符串,每个字符串指示用户在命名逻辑用户集合中的成员资格。常见值可能是 system:mastersdevops-team
  • 额外字段:一个字符串到字符串列表的映射,其中包含授权者可能觉得有用的附加信息。

匿名请求

如果启用,未被其他配置的身份验证方法拒绝的请求将被视为匿名请求,并赋予用户名 system:anonymous 和组 system:unauthenticated

例如,在配置了令牌身份验证的服务器上,并且启用了匿名访问,提供无效承载令牌的请求将收到 401 Unauthorized 错误。提供没有承载令牌的请求将被视为匿名请求。

如果使用 授权模式 以外的其他 AlwaysAllow,则默认启用匿名访问;可以通过将 --anonymous-auth=false 命令行选项传递给 API 服务器来禁用它。内置的 ABAC 和 RBAC 授权器需要明确授权 system:anonymous 用户或 system:unauthenticated 组;如果您有遗留策略规则(来自 Kubernetes 版本 1.5 或更早版本),则授予对 * 用户或 * 组访问权限的那些遗留规则不会自动允许匿名用户访问。

匿名身份验证器配置

特性状态: Kubernetes v1.34 [稳定](默认启用)

可以使用 AuthenticationConfiguration 来配置匿名身份验证器。如果在 AuthenticationConfiguration 文件中设置了 anonymous 字段,则无法设置 --anonymous-auth 命令行选项。

使用身份验证配置文件配置匿名身份验证器的主要优点是,除了启用和禁用匿名身份验证之外,还可以配置哪些端点支持匿名身份验证。

以下是示例身份验证配置文件:

---
#
# CAUTION: this is an example configuration.
#          Do not use this as-is for your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
anonymous:
  enabled: true
  conditions:
  - path: /livez
  - path: /readyz
  - path: /healthz

在上面的配置中,只有 /livez/readyz/healthz 端点可以被匿名请求访问。任何其他端点都无法匿名访问,即使您的授权配置允许也是如此。

身份验证方法

可以同时启用多种身份验证方法。通常应使用至少两种方法:

  • 服务帐户令牌用于服务帐户
  • 至少另一种方法用于用户身份验证。

当启用多个身份验证器模块时,第一个成功验证请求的模块会短路评估。API 服务器不保证身份验证器运行的顺序。

system:authenticated 组包含在所有已身份验证用户的组列表中。

集成与其他身份验证协议(LDAP、SAML、Kerberos、替代 x509 方案等)可用;例如使用 身份验证代理身份验证 webhook

X.509 客户端证书

任何呈现由集群的客户端信任证书颁发机构 (CA) 签名的有效客户端证书的 Kubernetes 客户端都被视为已通过身份验证。在这种配置中,Kubernetes 从证书的 subject 中的 commonName 字段确定用户名(例如,commonName=bob 表示用户名为“bob”)。然后,Kubernetes 授权机制确定用户是否有权对资源执行特定操作。

通过将 --client-ca-file=<SOMEFILE> 选项传递给 API 服务器来启用客户端证书身份验证。此选项配置集群的客户端信任证书颁发机构。引用的文件必须包含一个或多个 API 服务器在需要验证客户端证书时可以使用的一个或多个证书颁发机构。如果呈现并验证了客户端证书,则主题的 common name 用作请求的用户名。客户端证书还可以使用证书的组织字段指示用户的组 membership。要在用户中包含多个组 membership,请在证书中包含多个组织字段。

请参阅 管理证书,了解如何生成客户端证书,或阅读后面的 示例

兼容 Kubernetes 的客户端证书

您可以呈现由 API 服务器接受的客户端证书信任链中的 CA 颁发的有效证书,并使用它来验证到 Kubernetes 的身份。证书必须有效;API 服务器基于 X.509 notBeforenotAfter 属性进行检查,并且证书必须具有包含客户端身份验证 (ClientAuth) 的扩展密钥用法

用户名映射

Kubernetes 期望客户端证书包含一个 commonName(OID 2.5.4.3)属性,该属性用作主题的用户名。

用户 ID 映射
特性状态: Kubernetes v1.34 [beta](默认启用)

要使用此功能,证书必须包含属性 1.3.6.1.4.1.57683.2,并且必须启用 AllowParsingUserUIDFromCertAuth 特性门控(默认情况下已启用)。

Kubernetes 可以从证书解析一个可选用户 UID。UID 与用户名不同;它是一个不透明的值,其含义由请求证书的人定义,或者由设置证书批准规则的人定义。

例如,在一个集群中,UID 可以是 1042(一个简单的整数),但在另一个证书中,UID 可能是 d3f77937-ec82-4f16-8010-61821abe315a(一个 UUID)。

这里有一个例子来解释这意味着什么。如果你有一个公用名设置为“Ada Lovelace”的证书,并且该证书还具有一个 uid 属性(OID 0.9.2342.19200300.100.1.1),并且 uid 设置为“aaking1815”,Kubernetes 会认为客户端的用户名是“Ada Lovelace”;Kubernetes 会忽略 uid 属性,因为它不是 Kubernetes 查找的 CNCF 特定的 OID。如果你希望 Kubernetes 将 aaking1815 识别为 UID,则必须将其设置为证书主题中 OID 1.3.6.1.4.1.57683.2 属性的值。

组映射

你可以通过将组信息静态地包含在证书中,将用户映射到组。对于用户所属的每个组,将组名作为证书主题中的 organization(OID 2.5.6.4)添加。要包含用户所属的多个组,请在证书主题中包含多个组织(顺序无关紧要)。对于示例用户,证书的专有名称可能是 CN=Ada Lovelace,O=Users,O=Staff,O=Programmers,这将把她放入“Programmers”、“Staff”、“system:authenticated”和“Users”组。

将组信息放入证书是可选的;如果你没有在证书中指定任何组,那么用户将仅是“system:authenticated”组的成员。

节点客户端证书

Kubernetes 可以对节点身份使用相同的方法;节点是 Kubernetes API 服务器的客户端,它们运行一个 kubelet(此外,虽然在这里不太相关,但 API 服务器通常也是每个节点的客户端)。例如:一个名为“server-1a-antarctica42”的节点,域名为“server-1a-antarctica42.cluster.example”,可以使用颁发给“CN=system:node:server-1a-antarctica/42,O=system:nodes”的证书。然后节点的用户名是“system:node:server-1a-antarctica/g42”,并且该节点是“system:authenticated”和“system:nodes”组的成员。

kubelet 使用节点的证书和私钥向集群的 API 服务器进行身份验证。

示例

你可以使用 openssl 命令行工具生成证书签名请求

# This example assumes that you already have a private key alovelace.pem
openssl req -new -key alovelace.pem -out alovelace-csr.pem -subj "/CN=alovelace/O=app1/O=app2"

这将为用户名“alovelace”创建一个签名请求,属于两个组“app1”和“app2”。然后,你可以让你的集群的客户端信任证书颁发机构对该签名请求进行签名,以获得你可以用于集群客户端身份验证的证书。

引导令牌

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

为了简化新集群的引导,Kubernetes 包含一种动态管理的 Bearer 令牌类型,称为 *Bootstrap Token*。这些令牌作为 Secret 存储在 kube-system 命名空间中,可以在其中动态管理和创建。Controller Manager 包含一个 TokenCleaner 控制器,该控制器会在 Bootstrap 令牌过期时删除它们。

令牌的格式为 [a-z0-9]{6}.[a-z0-9]{16}。第一个组件是 Token ID,第二个组件是 Token Secret。你可以在 HTTP 标头中指定令牌,如下所示

Authorization: Bearer 781292.db7bc3a58fc5f07e

你必须使用 --enable-bootstrap-token-auth 标志在 API 服务器上启用 Bootstrap Token 身份验证器。你必须通过 kube-controller-manager 的 --controllers 命令行参数启用 TokenCleaner 控制器。这可以通过类似 --controllers=*,tokencleaner 的方式完成。如果你使用它来引导集群,kubeadm 工具会为你执行此操作。

身份验证器将作为 system:bootstrap:<Token ID> 进行身份验证。它包含在 system:bootstrappers 组中。命名和组经过有意限制,以阻止用户在引导完成后使用这些令牌。用户名和组可用于(并且被 kubeadm 使用)来构建适当的授权策略以支持集群引导。

请参阅 Bootstrap Tokens,以获取有关 Bootstrap Token 身份验证器和控制器的深入文档,以及如何使用 kubeadm 管理这些令牌的信息。

在请求中放置 Bearer 令牌

在使用来自 HTTP 客户端的 Bearer 令牌身份验证时,API 服务器期望一个值为 Bearer <token>Authorization 标头。Bearer 令牌必须是可以放置在 HTTP 标头值中的字符序列,仅使用 HTTP 的编码和引用机制。例如:如果 Bearer 令牌是 31ada4fd-adec-460c-809a-9e56ceb75269,那么它将显示在 HTTP 标头中,如下所示。

Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269

Service Account 令牌

Service Account 是一个自动启用的身份验证器,它使用签名的 Bearer 令牌来验证请求。该插件接受两个可选标志

  • --service-account-key-file 包含 PEM 编码的 x509 RSA 或 ECDSA 私钥或公钥的文件,用于验证 ServiceAccount 令牌。指定的文件可以包含多个密钥,并且可以多次指定该标志,并使用不同的文件。如果未指定,则使用 --tls-private-key-file。
  • --service-account-lookup 如果启用,则从 API 中删除的令牌将被撤销。

Service Account 通常由 API 服务器自动创建,并通过 ServiceAccount Admission Controller 与集群中运行的 Pod 关联。Bearer 令牌被安装到 Pod 中的已知位置,并允许集群内进程与 API 服务器通信。可以使用 PodSpecserviceAccountName 字段显式地将帐户与 Pod 关联。

apiVersion: apps/v1 # this apiVersion is relevant as of Kubernetes 1.9
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3
  template:
    metadata:
    # ...
    spec:
      serviceAccountName: bob-the-bot
      containers:
      - name: nginx
        image: nginx:1.14.2

Service Account Bearer 令牌完全可以用于集群外部,并且可以用于为希望与 Kubernetes API 通信的长期运行作业创建身份。要手动创建 Service Account,请使用 kubectl create serviceaccount (NAME) 命令。这将在当前命名空间中创建一个 Service Account。

kubectl create serviceaccount jenkins
serviceaccount/jenkins created

你可以手动创建一个关联的令牌

kubectl create token jenkins
eyJhbGciOiJSUzI1NiIsImtp...

创建的令牌是一个签名的 JSON Web Token (JWT)。

签名的 JWT 可以用作 Bearer 令牌来验证给定的 Service Account。有关如何在请求中包含令牌,请参阅 上方。通常,这些令牌被安装到 Pod 中以进行集群内访问 API 服务器,但也可以从集群外部使用。

Service Account 使用用户名 system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT) 进行身份验证,并被分配到组 system:serviceaccountssystem:serviceaccounts:(NAMESPACE)

外部集成

Kubernetes 原生支持 JWT 和 OpenID Connect (OIDC);请参阅 JSON Web Token 身份验证

可以使用 身份验证代理 或通过集成到 身份验证 Webhook 来实现与其他身份验证协议(例如:LDAP、SAML、Kerberos、替代 X.509 方案)的集成。

你还可以使用任何发出 客户端 X.509 证书 给客户端的自定义方法,前提是 API 服务器将信任有效的证书。阅读 X.509 客户端证书,了解如何生成证书。

如果你向客户端颁发证书,那么作为云平台管理员,你需要确保证书有效期以及你做出的其他设计选择提供适当的安全级别。

JSON Web Token 身份验证

你可以配置 Kubernetes 使用符合 JSON Web Token (JWT) 的令牌来验证用户。JWT 身份验证机制用于 Kubernetes 本身发出的 ServiceAccount 令牌,你还可以使用它来与其他身份源集成。

身份验证器尝试解析原始 ID 令牌,并验证它是否已由配置的颁发者签名。对于外部颁发的令牌,可以使用 OIDC 发现从颁发者的公共端点发现验证签名所需的公钥。

JWT payload 必须 包含以下声明

{
  "iss": "https://example.com",   // must match the issuer.url
  "aud": ["my-app"],              // at least one of the entries in issuer.audiences must match the "aud" claim in presented JWTs.
  "exp": 1234567890,              // token expiration as Unix time (the number of seconds elapsed since January 1, 1970 UTC)
  "<username-claim>": "user"      // this is the username claim configured in the claimMappings.username.claim or claimMappings.username.expression
}

JWT 出站选择器类型

特性状态: Kubernetes v1.34 [beta](默认启用)

JWT issuer 配置中的 egressSelectorType 字段允许你指定应将所有与 issuer 相关的流量(发现、JWKS、分布式声明等)发送到哪个出站选择器。此功能需要启用 StructuredAuthenticationConfigurationEgressSelector 功能门。

OpenID Connect 令牌

OpenID Connect 是 OAuth2 的一种变体,受某些 OAuth2 提供程序的支持,特别是 Microsoft Entra ID、Salesforce 和 Google。该协议对 OAuth2 的主要扩展是在访问令牌中返回的附加字段,称为 ID Token。此令牌是一个 JSON Web Token (JWT),其中包含众所周知的字段,例如用户的电子邮件,由服务器签名。

为了识别用户,身份验证器使用 OAuth2 token response 中的 id_token(而不是 access_token)作为 Bearer 令牌。有关如何在请求中包含令牌,请参阅 上方

sequenceDiagram participant user as User participant idp as Identity Provider participant kube as kubectl participant api as API Server user ->> idp: 1. 登录到 IdP activate idp idp -->> user: 2. 提供 access_token,
id_token 和 refresh_token deactivate idp activate user user ->> kube: 3. 调用 kubectl
使用 --token 作为 id_token
或者将 token 添加到 .kube/config deactivate user activate kube kube ->> api: 4. 授权: Bearer... deactivate kube activate api api ->> api: 5. JWT 签名有效吗? api ->> api: 6. JWT 是否已过期? (iat+exp) api ->> api: 7. 用户已授权? api -->> kube: 8. 已授权: 执行
操作并返回结果 deactivate api activate kube kube --x user: 9. 返回结果 deactivate kube
  1. 登录到您的身份提供程序

  2. 您的身份提供程序将为您提供一个 access_tokenid_token 和一个 refresh_token

  3. 在使用 kubectl 时,使用 --token 命令行参数使用您的 id_token,或者将其直接添加到您的 kubeconfig

  4. kubectl 将您的 id_token 在名为 Authorization 的 header 中发送到 API 服务器

  5. API 服务器将确保 JWT 签名有效

  6. 检查以确保 id_token 未过期

    如果配置了带有 AuthenticationConfiguration 的 CEL 表达式,则执行声明和/或用户验证。

  7. 确保用户已获得授权

  8. 授权后,API 服务器会将响应返回给 kubectl

  9. kubectl 向用户提供反馈

由于验证您身份所需的所有数据都包含在 id_token 中,Kubernetes 不需要“回家”到身份提供程序。在每个请求都是无状态的模型中,这提供了一个非常可扩展的身份验证解决方案。但这确实带来了一些挑战

  1. Kubernetes 没有“Web 界面”来触发身份验证过程。没有浏览器或界面来收集凭据,这就是为什么您需要先向您的身份提供程序进行身份验证的原因。
  2. id_token 无法撤销,它就像一个证书,因此应该具有较短的生命周期(只有几分钟),因此每隔几分钟必须获取一个新的 token 可能会非常烦人。
  3. 要对 Kubernetes dashboard 进行身份验证,您必须使用 kubectl proxy 命令或注入 id_token 的反向代理。

配置 API 服务器

使用命令行参数

要启用插件,请为 API 服务器配置以下命令行参数

参数描述示例必需
--oidc-issuer-url允许 API 服务器发现公共签名密钥的提供程序的 URL。仅接受使用 https:// 方案的 URL。这通常是提供程序的发现 URL,更改为空路径。如果发行者的 OIDC 发现 URL 是 https://accounts.provider.example/.well-known/openid-configuration,则该值应为 https://accounts.provider.example
--oidc-client-id所有 token 都必须为此颁发的客户端 ID。kubernetes
--oidc-username-claim用作用户名的 JWT claim。默认值为 sub,预计是最终用户的唯一标识符。管理员可以选择其他 claim,例如 emailname,具体取决于他们的提供程序。但是,除了 email 之外的其他 claim 将以发行者 URL 为前缀,以防止与其他插件的命名冲突。sub
--oidc-username-prefix添加到用户名 claim 的前缀,以防止与现有名称(例如 system: 用户)冲突。例如,值 oidc: 将创建诸如 oidc:jane.doe 之类的用户名。如果未提供此参数并且 --oidc-username-claim 的值不是 email,则前缀默认为 ( Issuer URL )#,其中 ( Issuer URL )--oidc-issuer-url 的值。可以使用 - 来禁用所有前缀。oidc
--oidc-groups-claim用作用户组的 JWT claim。如果存在该 claim,则必须是字符串数组。groups
--oidc-groups-prefix添加到组 claim 的前缀,以防止与现有名称(例如 system: 组)冲突。例如,值 oidc: 将创建诸如 oidc:engineeringoidc:infra 之类的组名。oidc
--oidc-required-claim描述 ID Token 中所需的 claim 的键=值对。如果设置,则会验证该 claim 是否存在于 ID Token 中,并且具有匹配的值。重复此参数以指定多个 claim。claim=value
--oidc-ca-file签署您的身份提供程序 Web 证书的 CA 的证书的路径。默认值为主机根 CA。/etc/kubernetes/ssl/kc-ca.pem
--oidc-signing-algs接受的签名算法。默认值为 RS256。允许的值为:RS256、RS384、RS512、ES256、ES384、ES512、PS256、PS384、PS512。这些值由 RFC 7518 https://tools.ietf.org/html/rfc7518#section-3.1 定义。RS512
来自文件的身份验证配置
特性状态: Kubernetes v1.34 [稳定](默认启用)

配置文件方法允许您配置多个 JWT 身份验证器,每个身份验证器具有唯一的 issuer.urlissuer.discoveryURL。配置文件甚至允许您指定 CEL 表达式,以将 claim 映射到用户属性,并验证 claim 和用户信息。API 服务器还会在修改配置文件时自动重新加载身份验证器。您可以使用 apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds 指标来监视 API 服务器上次重新加载配置的时间。

您必须使用 --authentication-config 命令行参数指定身份验证配置文件的路径。如果您想使用命令行参数而不是配置文件,它们将继续按原样工作。要访问新的功能,例如配置多个身份验证器、为发行者设置多个受众,请切换到使用配置文件。

要使用结构化身份验证,请使用 --authentication-config 命令行参数指定 kube-apiserver。以下是结构化身份验证配置文件的示例。

---
#
# CAUTION: this is an example configuration.
#          Do not use this for your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
# list of authenticators to authenticate Kubernetes users using JWT compliant tokens.
# the maximum number of allowed authenticators is 64.
jwt:
- issuer:
    # url must be unique across all authenticators.
    # url must not conflict with issuer configured in --service-account-issuer.
    url: https://example.com # Same as --oidc-issuer-url.
    # discoveryURL, if specified, overrides the URL used to fetch discovery
    # information instead of using "{url}/.well-known/openid-configuration".
    # The exact value specified is used, so "/.well-known/openid-configuration"
    # must be included in discoveryURL if needed.
    #
    # The "issuer" field in the fetched discovery information must match the "issuer.url" field
    # in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
    # This is for scenarios where the well-known and jwks endpoints are hosted at a different
    # location than the issuer (such as locally in the cluster).
    # discoveryURL must be different from url if specified and must be unique across all authenticators.
    discoveryURL: https://discovery.example.com/.well-known/openid-configuration
    # PEM encoded CA certificates used to validate the connection when fetching
    # discovery information. If not set, the system verifier will be used.
    # Same value as the content of the file referenced by the --oidc-ca-file command line argument.
    certificateAuthority: <PEM encoded CA certificates>    
    # audiences is the set of acceptable audiences the JWT must be issued to.
    # At least one of the entries must match the "aud" claim in presented JWTs.
    audiences:
    - my-app # Same as --oidc-client-id.
    - my-other-app
    # this is required to be set to "MatchAny" when multiple audiences are specified.
    audienceMatchPolicy: MatchAny
    # egressSelectorType is an indicator of which egress selection should be used for sending all traffic related
    # to this issuer (discovery, JWKS, distributed claims, etc).  If unspecified, no custom dialer is used.
    # The StructuredAuthenticationConfigurationEgressSelector feature gate must be enabled
    # before you can use the egressSelectorType field.
    # When specified, the valid choices are "controlplane" and "cluster".  These correspond to the associated
    # values in the --egress-selector-config-file.
    # - controlplane: for traffic intended to go to the control plane.
    # - cluster: for traffic intended to go to the system being managed by Kubernetes.
    egressSelectorType: <egress-selector-type>
  # rules applied to validate token claims to authenticate users.
  claimValidationRules:
    # Same as --oidc-required-claim key=value.
  - claim: hd
    requiredValue: example.com
    # Instead of claim and requiredValue, you can use expression to validate the claim.
    # expression is a CEL expression that evaluates to a boolean.
    # all the expressions must evaluate to true for validation to succeed.
  - expression: 'claims.hd == "example.com"'
    # Message customizes the error message seen in the API server logs when the validation fails.
    message: the hd claim must be set to example.com
  - expression: 'claims.exp - claims.nbf <= 86400'
    message: total token lifetime must not exceed 24 hours
  claimMappings:
    # username represents an option for the username attribute.
    # This is the only required attribute.
    username:
      # Same as --oidc-username-claim. Mutually exclusive with username.expression.
      claim: "sub"
      # Same as --oidc-username-prefix. Mutually exclusive with username.expression.
      # if username.claim is set, username.prefix is required.
      # Explicitly set it to "" if no prefix is desired.
      prefix: ""
      # Mutually exclusive with username.claim and username.prefix.
      # expression is a CEL expression that evaluates to a string.
      #
      # 1.  If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
      #     username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
      #     An example claim validation rule expression that matches the validation automatically
      #     applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'.
      #     By explicitly comparing the value to true, we let type-checking see the result will be a boolean, and
      #     to make sure a non-boolean email_verified claim will be caught at runtime.
      # 2.  If the username asserted based on username.expression is the empty string, the authentication
      #     request will fail.
      expression: 'claims.username + ":external-user"'
    # groups represents an option for the groups attribute.
    groups:
      # Same as --oidc-groups-claim. Mutually exclusive with groups.expression.
      claim: "sub"
      # Same as --oidc-groups-prefix. Mutually exclusive with groups.expression.
      # if groups.claim is set, groups.prefix is required.
      # Explicitly set it to "" if no prefix is desired.
      prefix: ""
      # Mutually exclusive with groups.claim and groups.prefix.
      # expression is a CEL expression that evaluates to a string or a list of strings.
      expression: 'claims.roles.split(",")'
    # uid represents an option for the uid attribute.
    uid:
      # Mutually exclusive with uid.expression.
      claim: 'sub'
      # Mutually exclusive with uid.claim
      # expression is a CEL expression that evaluates to a string.
      expression: 'claims.sub'
    # extra attributes to be added to the UserInfo object. Keys must be domain-prefix path and must be unique.
    extra:
      # key is a string to use as the extra attribute key.
      # key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid
      # subdomain as defined by RFC 1123. All characters trailing the first "/" must
      # be valid HTTP Path characters as defined by RFC 3986.
      # k8s.io, kubernetes.io and their subdomains are reserved for Kubernetes use and cannot be used.
      # key must be lowercase and unique across all extra attributes.
    - key: 'example.com/tenant'
      # valueExpression is a CEL expression that evaluates to a string or a list of strings.
      valueExpression: 'claims.tenant'
  # validation rules applied to the final user object.
  userValidationRules:
    # expression is a CEL expression that evaluates to a boolean.
    # all the expressions must evaluate to true for the user to be valid.
  - expression: "!user.username.startsWith('system:')"
    # Message customizes the error message seen in the API server logs when the validation fails.
    message: 'username cannot used reserved system: prefix'
  - expression: "user.groups.all(group, !group.startsWith('system:'))"
    message: 'groups cannot used reserved system: prefix'
  • Claim 验证规则表达式

    jwt.claimValidationRules[i].expression 表示将由 CEL 评估的表达式。CEL 表达式可以访问 token payload 的内容,组织到 claims CEL 变量中。claims 是一个 claim 名称(字符串)到 claim 值(任何类型)的映射。

  • 用户验证规则表达式

    jwt.userValidationRules[i].expression 表示将由 CEL 评估的表达式。CEL 表达式可以访问 userInfo 的内容,组织到 user CEL 变量中。请参阅 UserInfo API 文档,了解 user 的模式。

  • Claim 映射表达式

    jwt.claimMappings.username.expressionjwt.claimMappings.groups.expressionjwt.claimMappings.uid.expression jwt.claimMappings.extra[i].valueExpression 表示将由 CEL 评估的表达式。CEL 表达式可以访问 token payload 的内容,组织到 claims CEL 变量中。claims 是一个 claim 名称(字符串)到 claim 值(任何类型)的映射。

    要了解更多信息,请参阅 CEL 文档

    以下是具有不同 token payload 的 AuthenticationConfiguration 的示例。

    apiVersion: apiserver.config.k8s.io/v1
    kind: AuthenticationConfiguration
    jwt:
    - issuer:
        url: https://example.com
        audiences:
        - my-app
      claimMappings:
        username:
          expression: 'claims.username + ":external-user"'
        groups:
          expression: 'claims.roles.split(",")'
        uid:
          expression: 'claims.sub'
        extra:
        - key: 'example.com/tenant'
          valueExpression: 'claims.tenant'
      userValidationRules:
      - expression: "!user.username.startsWith('system:')" # the expression will evaluate to true, so validation will succeed.
        message: 'username cannot used reserved system: prefix'
    
    TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6ImY3dF9tOEROWmFTQk1oWGw5QXZTWGhBUC04Y0JmZ0JVbFVpTG5oQkgxdXMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNzAzMjMyOTQ5LCJpYXQiOjE3MDExMDcyMzMsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJqdGkiOiI3YzMzNzk0MjgwN2U3M2NhYTJjMzBjODY4YWMwY2U5MTBiY2UwMmRkY2JmZWJlOGMyM2I4YjVmMjdhZDYyODczIiwibmJmIjoxNzAxMTA3MjMzLCJyb2xlcyI6InVzZXIsYWRtaW4iLCJzdWIiOiJhdXRoIiwidGVuYW50IjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjRhIiwidXNlcm5hbWUiOiJmb28ifQ.TBWF2RkQHm4QQz85AYPcwLxSk-VLvQW-mNDHx7SEOSv9LVwcPYPuPajJpuQn9C_gKq1R94QKSQ5F6UgHMILz8OfmPKmX_00wpwwNVGeevJ79ieX2V-__W56iNR5gJ-i9nn6FYk5pwfVREB0l4HSlpTOmu80gbPWAXY5hLW0ZtcE1JTEEmefORHV2ge8e3jp1xGafNy6LdJWabYuKiw8d7Qga__HxtKB-t0kRMNzLRS7rka_SfQg0dSYektuxhLbiDkqhmRffGlQKXGVzUsuvFw7IGM5ZWnZgEMDzCI357obHeM3tRqpn5WRjtB8oM7JgnCymaJi-P3iCd88iu1xnzA
    

    其中 token payload 为

      {
        "aud": "kubernetes",
        "exp": 1703232949,
        "iat": 1701107233,
        "iss": "https://example.com",
        "jti": "7c337942807e73caa2c30c868ac0ce910bce02ddcbfebe8c23b8b5f27ad62873",
        "nbf": 1701107233,
        "roles": "user,admin",
        "sub": "auth",
        "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a",
        "username": "foo"
      }
    

    使用上述 AuthenticationConfiguration 的 token 将生成以下 UserInfo 对象并成功验证用户。

    {
        "username": "foo:external-user",
        "uid": "auth",
        "groups": [
            "user",
            "admin"
        ],
        "extra": {
            "example.com/tenant": ["72f988bf-86f1-41af-91ab-2d7cd011db4a"]
        }
    }
    

    apiVersion: apiserver.config.k8s.io/v1
    kind: AuthenticationConfiguration
    jwt:
    - issuer:
        url: https://example.com
        audiences:
        - my-app
      claimValidationRules:
      - expression: 'claims.hd == "example.com"' # the token below does not have this claim, so validation will fail.
        message: the hd claim must be set to example.com
      claimMappings:
        username:
          expression: 'claims.username + ":external-user"'
        groups:
          expression: 'claims.roles.split(",")'
        uid:
          expression: 'claims.sub'
        extra:
        - key: 'example.com/tenant'
          valueExpression: 'claims.tenant'
      userValidationRules:
      - expression: "!user.username.startsWith('system:')" # the expression will evaluate to true, so validation will succeed.
        message: 'username cannot used reserved system: prefix'
    
    TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6ImY3dF9tOEROWmFTQk1oWGw5QXZTWGhBUC04Y0JmZ0JVbFVpTG5oQkgxdXMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNzAzMjMyOTQ5LCJpYXQiOjE3MDExMDcyMzMsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJqdGkiOiI3YzMzNzk0MjgwN2U3M2NhYTJjMzBjODY4YWMwY2U5MTBiY2UwMmRkY2JmZWJlOGMyM2I4YjVmMjdhZDYyODczIiwibmJmIjoxNzAxMTA3MjMzLCJyb2xlcyI6InVzZXIsYWRtaW4iLCJzdWIiOiJhdXRoIiwidGVuYW50IjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjRhIiwidXNlcm5hbWUiOiJmb28ifQ.TBWF2RkQHm4QQz85AYPcwLxSk-VLvQW-mNDHx7SEOSv9LVwcPYPuPajJpuQn9C_gKq1R94QKSQ5F6UgHMILz8OfmPKmX_00wpwwNVGeevJ79ieX2V-__W56iNR5gJ-i9nn6FYk5pwfVREB0l4HSlpTOmu80gbPWAXY5hLW0ZtcE1JTEEmefORHV2ge8e3jp1xGafNy6LdJWabYuKiw8d7Qga__HxtKB-t0kRMNzLRS7rka_SfQg0dSYektuxhLbiDkqhmRffGlQKXGVzUsuvFw7IGM5ZWnZgEMDzCI357obHeM3tRqpn5WRjtB8oM7JgnCymaJi-P3iCd88iu1xnzA
    

    其中 token payload 为

      {
        "aud": "kubernetes",
        "exp": 1703232949,
        "iat": 1701107233,
        "iss": "https://example.com",
        "jti": "7c337942807e73caa2c30c868ac0ce910bce02ddcbfebe8c23b8b5f27ad62873",
        "nbf": 1701107233,
        "roles": "user,admin",
        "sub": "auth",
        "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a",
        "username": "foo"
      }
    

    使用上述 AuthenticationConfiguration 的 token 将无法通过身份验证,因为未将 hd claim 设置为 example.com。API 服务器将返回 401 Unauthorized 错误。

    apiVersion: apiserver.config.k8s.io/v1
    kind: AuthenticationConfiguration
    jwt:
    - issuer:
        url: https://example.com
        audiences:
        - my-app
      claimValidationRules:
      - expression: 'claims.hd == "example.com"'
        message: the hd claim must be set to example.com
      claimMappings:
        username:
          expression: '"system:" + claims.username' # this will prefix the username with "system:" and will fail user validation.
        groups:
          expression: 'claims.roles.split(",")'
        uid:
          expression: 'claims.sub'
        extra:
        - key: 'example.com/tenant'
          valueExpression: 'claims.tenant'
      userValidationRules:
      - expression: "!user.username.startsWith('system:')" # the username will be system:foo and expression will evaluate to false, so validation will fail.
        message: 'username cannot used reserved system: prefix'
    
    TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6ImY3dF9tOEROWmFTQk1oWGw5QXZTWGhBUC04Y0JmZ0JVbFVpTG5oQkgxdXMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNzAzMjMyOTQ5LCJoZCI6ImV4YW1wbGUuY29tIiwiaWF0IjoxNzAxMTEzMTAxLCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwianRpIjoiYjViMDY1MjM3MmNkMjBlMzQ1YjZmZGZmY2RjMjE4MWY0YWZkNmYyNTlhYWI0YjdlMzU4ODEyMzdkMjkyMjBiYyIsIm5iZiI6MTcwMTExMzEwMSwicm9sZXMiOiJ1c2VyLGFkbWluIiwic3ViIjoiYXV0aCIsInRlbmFudCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0YSIsInVzZXJuYW1lIjoiZm9vIn0.FgPJBYLobo9jnbHreooBlvpgEcSPWnKfX6dc0IvdlRB-F0dCcgy91oCJeK_aBk-8zH5AKUXoFTlInfLCkPivMOJqMECA1YTrMUwt_IVqwb116AqihfByUYIIqzMjvUbthtbpIeHQm2fF0HbrUqa_Q0uaYwgy8mD807h7sBcUMjNd215ff_nFIHss-9zegH8GI1d9fiBf-g6zjkR1j987EP748khpQh9IxPjMJbSgG_uH5x80YFuqgEWwq-aYJPQxXX6FatP96a2EAn7wfPpGlPRt0HcBOvq5pCnudgCgfVgiOJiLr_7robQu4T1bis0W75VPEvwWtgFcLnvcQx0JWg
    

    其中 token payload 为

      {
        "aud": "kubernetes",
        "exp": 1703232949,
        "hd": "example.com",
        "iat": 1701113101,
        "iss": "https://example.com",
        "jti": "b5b0652372cd20e345b6fdffcdc2181f4afd6f259aab4b7e35881237d29220bc",
        "nbf": 1701113101,
        "roles": "user,admin",
        "sub": "auth",
        "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db4a",
        "username": "foo"
      }
    

    使用上述 AuthenticationConfiguration 的 token 将生成以下 UserInfo 对象

    {
        "username": "system:foo",
        "uid": "auth",
        "groups": [
            "user",
            "admin"
        ],
        "extra": {
            "example.com/tenant": ["72f988bf-86f1-41af-91ab-2d7cd011db4a"]
        }
    }
    

    由于用户名以 system: 开头,这将导致用户验证失败。API 服务器将返回 401 Unauthorized 错误。

限制
  1. 通过 CEL 表达式无法使用分布式 claim。

Kubernetes 不提供 OpenID Connect 身份提供程序。您可以使用现有的公共 OpenID Connect 身份提供程序或运行支持 OpenID Connect 协议的您自己的身份提供程序。

为了使身份提供程序与 Kubernetes 协同工作,它必须

  1. 支持 OpenID connect discovery

    使用 OIDC discovery 从发行者的公共端点发现验证签名的公钥。如果您使用身份验证配置文件,则身份提供程序不需要公开公开 discovery 端点。您可以将 discovery 端点托管在与发行者(例如在集群中本地)不同的位置,并在配置文件中指定 issuer.discoveryURL

  2. 以 TLS 运行,且不使用过时的密码

  3. 具有 CA 签名的证书(即使 CA 不是商业 CA 或是自签名)

关于上述第 3 项要求,需要 CA 签名的证书。如果您部署自己的身份提供程序,则必须让您的身份提供程序的 Web 服务器证书由将 CA 标志设置为 TRUE 的证书签名,即使它是自签名。这是由于 GoLang 的 TLS 客户端实现对证书验证的标准非常严格。如果您没有现成的 CA,可以使用标准的证书生成工具创建简单的 CA 和签名的证书和密钥对。

使用 kubectl

选项 1 - OIDC 身份验证器

第一个选项是使用 kubectl oidc 身份验证器,它将 id_token 作为所有请求的 bearer token,并在 token 过期时刷新 token。在登录到您的提供程序后,使用 kubectl 将您的 id_tokenrefresh_tokenclient_idclient_secret 添加到配置插件。

如果提供程序未在其 refresh token 响应中返回 id_token,则该提供程序不受此插件支持,应使用 选项 2(指定 --token)。

kubectl config set-credentials USER_NAME \
   --auth-provider=oidc \
   --auth-provider-arg=idp-issuer-url=( issuer url ) \
   --auth-provider-arg=client-id=( your client id ) \
   --auth-provider-arg=client-secret=( your client secret ) \
   --auth-provider-arg=refresh-token=( your refresh token ) \
   --auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
   --auth-provider-arg=id-token=( your id_token )

例如,在向您的身份提供程序进行身份验证后运行以下命令

kubectl config set-credentials mmosley  \
        --auth-provider=oidc  \
        --auth-provider-arg=idp-issuer-url=https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP  \
        --auth-provider-arg=client-id=kubernetes  \
        --auth-provider-arg=client-secret=1db158f6-177d-4d9c-8a8b-d36869918ec5  \
        --auth-provider-arg=refresh-token=q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXqHega4GAXlF+ma+vmYpFcHe5eZR+slBFpZKtQA= \
        --auth-provider-arg=idp-certificate-authority=/root/ca.pem \
        --auth-provider-arg=id-token=eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knw

这将生成以下配置

users:
- name: mmosley
  user:
    auth-provider:
      config:
        client-id: kubernetes
        client-secret: 1db158f6-177d-4d9c-8a8b-d36869918ec5
        id-token: eyJraWQiOiJDTj1vaWRjaWRwLnRyZW1vbG8ubGFuLCBPVT1EZW1vLCBPPVRybWVvbG8gU2VjdXJpdHksIEw9QXJsaW5ndG9uLCBTVD1WaXJnaW5pYSwgQz1VUy1DTj1rdWJlLWNhLTEyMDIxNDc5MjEwMzYwNzMyMTUyIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29pZGNpZHAudHJlbW9sby5sYW46ODQ0My9hdXRoL2lkcC9PaWRjSWRQIiwiYXVkIjoia3ViZXJuZXRlcyIsImV4cCI6MTQ4MzU0OTUxMSwianRpIjoiMm96US15TXdFcHV4WDlHZUhQdy1hZyIsImlhdCI6MTQ4MzU0OTQ1MSwibmJmIjoxNDgzNTQ5MzMxLCJzdWIiOiI0YWViMzdiYS1iNjQ1LTQ4ZmQtYWIzMC0xYTAxZWU0MWUyMTgifQ.w6p4J_6qQ1HzTG9nrEOrubxIMb9K5hzcMPxc9IxPx2K4xO9l-oFiUw93daH3m5pluP6K7eOE6txBuRVfEcpJSwlelsOsW8gb8VJcnzMS9EnZpeA0tW_p-mnkFc3VcfyXuhe5R3G7aa5d8uHv70yJ9Y3-UhjiN9EhpMdfPAoEB9fYKKkJRzF7utTTIPGrSaSU6d2pcpfYKaxIwePzEkT4DfcQthoZdy9ucNvvLoi1DIC-UocFD8HLs8LYKEqSxQvOcvnThbObJ9af71EwmuE21fO5KzMW20KtAeget1gnldOosPtz1G5EwvaQ401-RPQzPGMVBld0_zMCAwZttJ4knw
        idp-certificate-authority: /root/ca.pem
        idp-issuer-url: https://oidcidp.tremolo.lan:8443/auth/idp/OidcIdP
        refresh-token: q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXq
      name: oidc

一旦您的 id_token 过期,kubectl 将尝试使用您的 refresh_tokenclient_secret 刷新您的 id_token,并将新的值存储到 refresh_tokenid_token.kube/config

选项 2 - 使用 --token 命令行参数

kubectl 命令允许您使用 --token 命令行参数传递 token。将 id_token 复制并粘贴到此选项

kubectl --token=eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL21sYi50cmVtb2xvLmxhbjo4MDQzL2F1dGgvaWRwL29pZGMiLCJhdWQiOiJrdWJlcm5ldGVzIiwiZXhwIjoxNDc0NTk2NjY5LCJqdGkiOiI2RDUzNXoxUEpFNjJOR3QxaWVyYm9RIiwiaWF0IjoxNDc0NTk2MzY5LCJuYmYiOjE0NzQ1OTYyNDksInN1YiI6Im13aW5kdSIsInVzZXJfcm9sZSI6WyJ1c2VycyIsIm5ldy1uYW1lc3BhY2Utdmlld2VyIl0sImVtYWlsIjoibXdpbmR1QG5vbW9yZWplZGkuY29tIn0.f2As579n9VNoaKzoF-dOQGmXkFKf1FMyNV0-va_B63jn-_n9LGSCca_6IVMP8pO-Zb4KvRqGyTP0r3HkHxYy5c81AnIh8ijarruczl-TK_yF5akjSTHFZD-0gRzlevBDiH8Q79NAr-ky0P4iIXS8lY9Vnjch5MF74Zx0c3alKJHJUnnpjIACByfF2SCaYzbWFMUNat-K1PaUk5-ujMBG7yYnr95xD-63n8CO8teGUAAEMx6zRjzfhnhbzX-ajwZLGwGUBT4WqjMs70-6a7_8gZmLZb2az1cZynkFRj2BaCkVT3A2RrjeEwZEtGXlMqKJ1_I2ulrOVsYx01_yD35-rw get nodes

Webhook token 身份验证

Kubernetes webhook authentication 是一种进行 HTTP 调用以验证 bearer token 的机制。

就如何配置 API 服务器而言

  • --authentication-token-webhook-config-file 一个描述如何访问远程 webhook 服务的配置文件。
  • --authentication-token-webhook-cache-ttl 缓存身份验证决策的时间。默认值为两分钟。
  • --authentication-token-webhook-version 确定是使用 authentication.k8s.io/v1beta1 还是 authentication.k8s.io/v1 TokenReview 对象向 webhook 发送/接收信息。默认值为 v1beta1

配置文件使用 kubeconfig 文件格式。在该文件中,clusters 指的是远程服务,而 users 指的是 API 服务器 webhook。一个例子是

# Kubernetes API version
apiVersion: v1
# kind of the API object
kind: Config
# clusters refers to the remote service.
clusters:
  - name: name-of-remote-authn-service
    cluster:
      certificate-authority: /path/to/ca.pem         # CA for verifying the remote service.
      server: https://authn.example.com/authenticate # URL of remote service to query. 'https' recommended for production.

# users refers to the API server's webhook configuration.
users:
  - name: name-of-api-server
    user:
      client-certificate: /path/to/cert.pem # cert for the webhook plugin to use
      client-key: /path/to/key.pem          # key matching the cert

# kubeconfig files require a context. Provide one for the API server.
current-context: webhook
contexts:
- context:
    cluster: name-of-remote-authn-service
    user: name-of-api-server
  name: webhook

当客户端尝试使用 bearer token(如上文 所述)向 API 服务器进行身份验证时,身份验证 webhook 会将 JSON 序列化的 TokenReview 对象(包含该 token)发布到远程服务。

请注意,webhook API 对象与其他的 Kubernetes API 对象一样,受到相同的 版本兼容性规则 的约束。实现者应检查请求的 apiVersion 字段,以确保正确反序列化,并且必须使用与请求相同版本的 TokenReview 对象进行响应。

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "TokenReview",
  "spec": {
    # Opaque bearer token sent to the API server
    "token": "014fbff9a07c...",

    # Optional list of the audience identifiers for the server the token was presented to.
    # Audience-aware token authenticators (for example, OIDC token authenticators)
    # should verify the token was intended for at least one of the audiences in this list,
    # and return the intersection of this list and the valid audiences for the token in the response status.
    # This ensures the token is valid to authenticate to the server it was presented to.
    # If no audiences are provided, the token should be validated to authenticate to the Kubernetes API server.
    "audiences": ["https://myserver.example.com", "https://myserver.internal.example.com"]
  }
}

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "spec": {
    # Opaque bearer token sent to the API server
    "token": "014fbff9a07c...",

    # Optional list of the audience identifiers for the server the token was presented to.
    # Audience-aware token authenticators (for example, OIDC token authenticators)
    # should verify the token was intended for at least one of the audiences in this list,
    # and return the intersection of this list and the valid audiences for the token in the response status.
    # This ensures the token is valid to authenticate to the server it was presented to.
    # If no audiences are provided, the token should be validated to authenticate to the Kubernetes API server.
    "audiences": ["https://myserver.example.com", "https://myserver.internal.example.com"]
  }
}

远程服务应填写请求的 status 字段,以指示登录是否成功。响应体的 spec 字段将被忽略,并且可以省略。远程服务必须使用其收到的相同的 TokenReview API 版本返回响应。bearer token 成功验证时将返回

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      # Required
      "username": "janedoe@example.com",
      # Optional
      "uid": "42",
      # Optional group memberships
      "groups": ["developers", "qa"],
      # Optional additional information provided by the authenticator.
      # This should not contain confidential data, as it can be recorded in logs
      # or API objects, and is made available to admission webhooks.
      "extra": {
        "extrafield1": [
          "extravalue1",
          "extravalue2"
        ]
      }
    },
    # Optional list audience-aware token authenticators can return,
    # containing the audiences from the `spec.audiences` list for which the provided token was valid.
    # If this is omitted, the token is considered to be valid to authenticate to the Kubernetes API server.
    "audiences": ["https://myserver.example.com"]
  }
}

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      # Required
      "username": "janedoe@example.com",
      # Optional
      "uid": "42",
      # Optional group memberships
      "groups": ["developers", "qa"],
      # Optional additional information provided by the authenticator.
      # This should not contain confidential data, as it can be recorded in logs
      # or API objects, and is made available to admission webhooks.
      "extra": {
        "extrafield1": [
          "extravalue1",
          "extravalue2"
        ]
      }
    },
    # Optional list audience-aware token authenticators can return,
    # containing the audiences from the `spec.audiences` list for which the provided token was valid.
    # If this is omitted, the token is considered to be valid to authenticate to the Kubernetes API server.
    "audiences": ["https://myserver.example.com"]
  }
}

未成功请求将返回

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "TokenReview",
  "status": {
    "authenticated": false,
    # Optionally include details about why authentication failed.
    # If no error is provided, the API will return a generic Unauthorized message.
    # The error field is ignored when authenticated=true.
    "error": "Credentials are expired"
  }
}

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": false,
    # Optionally include details about why authentication failed.
    # If no error is provided, the API will return a generic Unauthorized message.
    # The error field is ignored when authenticated=true.
    "error": "Credentials are expired"
  }
}

认证反向代理

API 服务器可以配置为从请求头值(例如 X-Remote-User)识别用户。它设计用于与设置这些头的认证反向代理结合使用。

使用认证反向代理与 用户模拟不同。使用用户模拟时,一个用户请求 API 服务器将请求视为由另一个用户发起的。使用认证反向代理时,API 服务器信任其直接客户端提供有关发起原始请求的主体身份的信息。

请参阅 web 请求头配置,了解如何使用命令行参数进行配置。

示例

例如,使用此配置

--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-

此请求

GET / HTTP/1.1
X-Remote-User: fido
X-Remote-Group: dogs
X-Remote-Group: dachshunds
X-Remote-Extra-Acme.com%2Fproject: some-project
X-Remote-Extra-Scopes: openid
X-Remote-Extra-Scopes: profile

将产生此用户信息

name: fido
groups:
- dogs
- dachshunds
extra:
  acme.com/project:
  - some-project
  scopes:
  - openid
  - profile

客户端证书

为了防止 header 欺骗,认证反向代理需要向 API 服务器呈现一个有效的客户端证书,以便在检查请求头之前,根据指定的 CA 进行验证。

请参阅 命令行选项参考,了解有关请求头身份验证模式的信息。

除非您了解风险以及保护 CA 使用的机制,否则不要重用在不同上下文中使用的 CA。

静态 token 文件集成

当在命令行中提供 --token-auth-file=<SOMEFILE> 选项时,API 服务器会从文件中读取静态 bearer token。在 Kubernetes 1.35 中,token 持续时间无限,并且无法在不重新启动 API 服务器的情况下更改 token 列表。

token 文件是一个 CSV 文件,至少包含 3 列:token、用户名、用户 uid,后跟一个逗号分隔的可选组名列表。

使用静态 token 文件适用于本质上是长期的、静态的,并且可能永远不会轮换的 token。它也适用于客户端位于控制平面内的特定 API 服务器,例如监控代理。

如果您在集群配置期间使用此方法,然后过渡到将长期使用的不同身份验证方法,则应停用用于引导的 token(这需要重新启动每个 API 服务器)。

对于其他情况,尤其是当非常快速的 token 轮换很重要时,Kubernetes 项目建议使用 webhook token 认证器,而不是此机制。

用户模拟

用户模拟提供了一种方法,用户可以通过模拟 header 代表另一个用户行事

身份验证配置

您可以使用 命令行参数配置文件配置 Kubernetes 身份验证。

通常,您会混合使用这些方法。

通过命令行参数配置

您可以使用以下命令行参数来配置集群的控制平面如何验证客户端身份。

API 服务器的 命令行参考更详细地描述了所有相关的命令行参数。

匿名身份验证配置

--anonymous-auth
控制是否允许未经验证的客户端通过 API 服务器的安全端口发出请求。匿名请求的用户名是 system:anonymous,组名是 system:unauthenticated。另请参阅 匿名请求

引导 token 配置

--enable-bootstrap-token-auth
设置此标志后,您可以使用 引导 token 进行身份验证。

证书身份验证配置

--client-ca-file
在使用 X.509 证书身份验证时,用于验证客户端身份的信任锚的路径。

OIDC 配置

--oidc-ca-file
在使用 OIDC 时,用于验证客户端身份的信任锚的路径。
--oidc-client-id
OpenID Connect 客户端的客户端 ID。
--oidc-username-claim
用于指定用户名的 JWT 声明的名称。用作用户名的声明。默认声明名称是 sub,因为这应该是最终用户的唯一标识符。您可以选择其他声明,例如 emailname。对于 subemail 以外的声明,kube-apiserver 会在组名前面添加一个前缀(以防止命名冲突)。
--oidc-username-prefix
添加到用户名声明的前缀,以防止与现有名称(例如 system: 用户)冲突。例如,值 oidc: 将创建用户名,如 oidc:jane.doe。如果未提供此参数,并且 --oidc-username-claim 的值为 email 以外的值,则默认前缀为 ( Issuer URL )#,其中 ( Issuer URL )--oidc-issuer-url 的值。您可以将前缀值指定为 - 以禁用用户名加前缀。
--oidc-groups-claim
用于指定用户组的自定义 OpenID Connect 声明的名称。token 中的声明必须是字符串数组。没有默认值。
--oidc-groups-prefix
添加到组声明的前缀,以防止与现有名称(例如 system: 组)冲突。例如,值 oidc: 将创建组名,如 oidc:engineeringoidc:infra。默认前缀是 oidc:
--oidc-issuer-url
OpenID issuer 的 URL。URL 方案必须https。如果 issuer 的 OIDC 发现 URL 是 https://accounts.provider.example/.well-known/openid-configuration,则该值应为 https://accounts.provider.example
--oidc-required-claim
必须存在于 token 中的声明,然后 Kubernetes 才能验证客户端。格式为 key=value。您可以多次指定此参数。
--oidc-signing-algs
接受的签名算法。允许的值为:RS256、RS384、RS512、ES256、ES384、ES512、PS256、PS384、PS512。这些值由 RFC 7518 定义。默认值为 RS512

ServiceAccount 配置

--api-audiences
定义 ServiceAccount token 的身份验证受众。
--service-account-extend-token-expiration
此标志启用在 token 生成期间的投影 ServiceAccount 过期时间扩展,这有助于从旧 token 安全过渡到绑定 ServiceAccount token 功能。请参阅 验证 ServiceAccount 凭据
--service-account-issuer
ServiceAccount token issuer 的标识符。issuer 在每个发出的 token 的 iss 声明中声明此标识符。Kubernetes 项目建议在此处使用 URL,并将方案设置为 https
--service-account-jwks-uri
覆盖在 /.well-known/openid-configuration 处提供的 discovery document 中的 JSON Web Key Set 的 URI
--service-account-key-file
指向包含 PEM 编码的 X.509 公钥或私钥(RSA 或 ECDSA)的文件,用于验证 ServiceAccount token。指定的文件可以包含多个密钥,并且可以使用不同的路径多次指定该参数。
--service-account-lookup
如果为 true,API 服务器将在身份验证期间将 ServiceAccount token 验证为存在于 etcd 中。
--service-account-max-token-expiration
由 service account token issuer 创建的 token 的最大有效期限,为 Kubernetes 持续时间字符串。
--service-account-signing-endpoint
正在侦听的外部 JWT 签名器的套接字路径。您可以使用它与外部 token 签名器集成。
--service-account-signing-key-file
指向包含 service account token issuer 的当前私钥的文件。在 API 服务器运行时对该文件所做的更改不会被重新读取。

静态 token 配置

--token-auth-file
指向 静态 bearer token 配置文件的路径。在 API 服务器运行时对该文件所做的更改不会被重新读取。

Webhook 身份验证配置

--authentication-token-webhook-cache-ttl
API 服务器应缓存验证 token 的 HTTP 调用结果的时间长度(作为 Kubernetes 持续时间规范)。
--authentication-token-webhook-config-file
指向 kubeconfig 格式的客户端配置,该配置指定 API 服务器在发出 HTTP 调用时如何进行身份验证。在 API 服务器运行时对该文件所做的更改不会被重新读取。
--authentication-token-webhook-version
在向 webhook 发出 HTTP 调用以检查 token 时,要使用的 TokenReview 的 API 版本。

Web 请求身份验证配置

--requestheader-client-ca-file
必需。 指向包含用于验证认证代理身份的信任锚的 PEM 编码证书捆绑包的文件。
在检查请求头以获取用户名之前,必须呈现有效的 客户端证书,并根据指定的文件中的证书颁发机构进行验证。
--requestheader-allowed-names
可选。 逗号分隔的 Common Name (CN) 值列表。
如果设置,在检查请求头以获取用户名之前,必须呈现 CN 在指定列表中的有效客户端证书。如果为空,则允许任何 CN。
--requestheader-username-headers
必需;不区分大小写。 要检查的 header 名称,按顺序查找用户身份。
包含值的第一个 header 将用作用户名。
--requestheader-group-headers
可选;不区分大小写。 要检查的 header 名称,按顺序查找用户的组。
X-Remote-Group 建议使用。所有指定标头中的所有值都用作组名。
--requestheader-extra-headers-prefix
可选;不区分大小写。 用于查找以确定用户额外信息的标头前缀。
X-Remote-Extra- 建议使用。额外数据通常由配置的授权插件使用。以任何指定的任何前缀开头的任何标头都将删除该前缀。标头名称的其余部分将小写化并 百分比解码,然后成为额外的键,标头值是额外的 值。

通过配置文件进行配置

特性状态: Kubernetes v1.34 [稳定](默认启用)

当您将 --authentication-config 命令行参数指定给 kube-apiserver 时,API 服务器将加载您指定的路径中的文件,并使用该文件中的内容来配置身份验证。

该文件中的内容可以在 API 服务器运行时更改,如果您这样做,API 服务器将在之后重新读取该文件。

配置文件路径

--authentication-config
这个特殊的命令行参数指定您希望 使用配置文件配置身份验证

示例

这是一个 Kubernetes(结构化)身份验证配置文件的示例

---
#
# CAUTION: this is an example configuration.
#          Check and amend this before you use it in your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1
kind: AuthenticationConfiguration
anonymous:
  enabled: false

client-go 凭据插件

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

k8s.io/client-go 以及使用它的工具,例如 kubectlkubelet 能够执行外部命令以接收用户凭据。

此功能旨在用于与 k8s.io/client-go 本身不支持的身份验证协议(LDAP、Kerberos、OAuth2、SAML 等)集成的客户端。该插件实现协议特定的逻辑,然后返回不透明的凭据以使用。几乎所有凭据插件用例都需要服务器端组件,并支持 webhook 令牌身份验证器 来解释客户端插件生成的凭据格式。

用例示例

在假设的使用案例中,组织将运行一个外部服务,该服务会交换 LDAP 凭据以获取用户特定的签名令牌。该服务还能够响应 webhook 令牌身份验证器 请求以验证令牌。要求用户在其工作站上安装凭据插件。

对 API 进行身份验证

  • 用户发出 kubectl 命令。
  • 凭据插件提示用户提供 LDAP 凭据,与外部服务交换凭据以获取令牌。
  • 凭据插件将令牌返回给 client-go,client-go 将其作为对 API 服务器的承载令牌使用。
  • API 服务器使用 webhook 令牌身份验证器TokenReview 提交给外部服务。
  • 外部服务验证令牌上的签名并返回用户的用户名和组。

配置

凭据插件通过 kubectl 配置文件 作为用户字段进行配置。

apiVersion: v1
kind: Config
users:
- name: my-user
  user:
    exec:
      # Command to execute. Required.
      command: "example-client-go-exec-plugin"

      # API version to use when decoding the ExecCredentials resource. Required.
      #
      # The API version returned by the plugin MUST match the version listed here.
      #
      # To integrate with tools that support multiple versions (such as client.authentication.k8s.io/v1beta1),
      # set an environment variable, pass an argument to the tool that indicates which version the exec plugin expects,
      # or read the version from the ExecCredential object in the KUBERNETES_EXEC_INFO environment variable.
      apiVersion: "client.authentication.k8s.io/v1"

      # Environment variables to set when executing the plugin. Optional.
      env:
      - name: "FOO"
        value: "bar"

      # Arguments to pass when executing the plugin. Optional.
      args:
      - "arg1"
      - "arg2"

      # Text shown to the user when the executable doesn't seem to be present. Optional.
      installHint: |
        example-client-go-exec-plugin is required to authenticate
        to the current cluster.  It can be installed:

        On macOS: brew install example-client-go-exec-plugin

        On Ubuntu: apt-get install example-client-go-exec-plugin

        On Fedora: dnf install example-client-go-exec-plugin

        ...        

      # Whether or not to provide cluster information, which could potentially contain
      # very large CA data, to this exec plugin as a part of the KUBERNETES_EXEC_INFO
      # environment variable.
      provideClusterInfo: true

      # The contract between the exec plugin and the standard input I/O stream. If the
      # contract cannot be satisfied, this plugin will not be run and an error will be
      # returned. Valid values are "Never" (this exec plugin never uses standard input),
      # "IfAvailable" (this exec plugin wants to use standard input if it is available),
      # or "Always" (this exec plugin requires standard input to function). Required.
      interactiveMode: Never
clusters:
- name: my-cluster
  cluster:
    server: "https://172.17.4.100:6443"
    certificate-authority: "/etc/kubernetes/ca.pem"
    extensions:
    - name: client.authentication.k8s.io/exec # reserved extension name for per cluster exec config
      extension:
        arbitrary: config
        this: can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo
        you: ["can", "put", "anything", "here"]
contexts:
- name: my-cluster
  context:
    cluster: my-cluster
    user: my-user
current-context: my-cluster

apiVersion: v1
kind: Config
users:
- name: my-user
  user:
    exec:
      # Command to execute. Required.
      command: "example-client-go-exec-plugin"

      # API version to use when decoding the ExecCredentials resource. Required.
      #
      # The API version returned by the plugin MUST match the version listed here.
      #
      # To integrate with tools that support multiple versions (such as client.authentication.k8s.io/v1),
      # set an environment variable, pass an argument to the tool that indicates which version the exec plugin expects,
      # or read the version from the ExecCredential object in the KUBERNETES_EXEC_INFO environment variable.
      apiVersion: "client.authentication.k8s.io/v1beta1"

      # Environment variables to set when executing the plugin. Optional.
      env:
      - name: "FOO"
        value: "bar"

      # Arguments to pass when executing the plugin. Optional.
      args:
      - "arg1"
      - "arg2"

      # Text shown to the user when the executable doesn't seem to be present. Optional.
      installHint: |
        example-client-go-exec-plugin is required to authenticate
        to the current cluster.  It can be installed:

        On macOS: brew install example-client-go-exec-plugin

        On Ubuntu: apt-get install example-client-go-exec-plugin

        On Fedora: dnf install example-client-go-exec-plugin

        ...        

      # Whether or not to provide cluster information, which could potentially contain
      # very large CA data, to this exec plugin as a part of the KUBERNETES_EXEC_INFO
      # environment variable.
      provideClusterInfo: true

      # The contract between the exec plugin and the standard input I/O stream. If the
      # contract cannot be satisfied, this plugin will not be run and an error will be
      # returned. Valid values are "Never" (this exec plugin never uses standard input),
      # "IfAvailable" (this exec plugin wants to use standard input if it is available),
      # or "Always" (this exec plugin requires standard input to function). Optional.
      # Defaults to "IfAvailable".
      interactiveMode: Never
clusters:
- name: my-cluster
  cluster:
    server: "https://172.17.4.100:6443"
    certificate-authority: "/etc/kubernetes/ca.pem"
    extensions:
    - name: client.authentication.k8s.io/exec # reserved extension name for per cluster exec config
      extension:
        arbitrary: config
        this: can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo
        you: ["can", "put", "anything", "here"]
contexts:
- name: my-cluster
  context:
    cluster: my-cluster
    user: my-user
current-context: my-cluster

相对命令路径解释为相对于配置文件的目录。如果 KUBECONFIG 设置为 /home/jane/kubeconfig 并且 exec 命令是 ./bin/example-client-go-exec-plugin,则将执行二进制文件 /home/jane/bin/example-client-go-exec-plugin

- name: my-user
  user:
    exec:
      # Path relative to the directory of the kubeconfig
      command: "./bin/example-client-go-exec-plugin"
      apiVersion: "client.authentication.k8s.io/v1"
      interactiveMode: Never

输入和输出格式

执行的命令会将 ExecCredential 对象打印到 stdoutk8s.io/client-go 使用返回的凭据在 status 中对 Kubernetes API 进行身份验证。执行的命令将 ExecCredential 对象作为输入通过 KUBERNETES_EXEC_INFO 环境变量传递。此输入包含有用的信息,例如返回的 ExecCredential 对象的预期 API 版本以及插件是否可以使用 stdin 与用户交互。

当从交互式会话(即终端)运行时,stdin 可以直接暴露给插件。插件应使用来自 KUBERNETES_EXEC_INFO 环境变量的输入 ExecCredential 对象的 spec.interactive 字段,以确定是否提供了 stdin。插件的 stdin 要求(即 stdin 是可选的、严格必需的还是从未使用于插件成功运行)通过 kubeconfig 中的 user.exec.interactiveMode 字段声明(有关有效值,请参见下表)。user.exec.interactiveMode 字段在 client.authentication.k8s.io/v1beta1 中是可选的,在 client.authentication.k8s.io/v1 中是必需的。

interactiveMode 值
interactiveMode含义
永不此 exec 插件从不需要使用标准输入,因此无论是否可用标准输入,都将运行该 exec 插件。如果标准输入可用于用户输入,则将提供给此 exec 插件。
IfAvailable此 exec 插件希望在可用时使用标准输入,但即使标准输入不可用,也可以运行。因此,无论是否可用 stdin 进行用户输入,都将运行该 exec 插件。如果标准输入可用于用户输入,则将提供给此 exec 插件。
Always此 exec 插件需要标准输入才能运行,因此只有在可用标准输入进行用户输入时才会运行该 exec 插件。如果标准输入不可用于用户输入,则 exec 插件将不会运行,并且 exec 插件运行程序将返回错误。

要使用承载令牌凭据,插件会在 ExecCredential 的状态中返回一个令牌

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token"
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token"
  }
}

或者,可以返回 PEM 编码的客户端证书和密钥以使用 TLS 客户端身份验证。如果插件在后续调用中返回不同的证书和密钥,k8s.io/client-go 将关闭与服务器的现有连接以强制新的 TLS 握手。

如果指定,clientKeyDataclientCertificateData 都必须存在。

clientCertificateData 包含发送到服务器的附加中间证书。

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "status": {
    "clientCertificateData": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "clientKeyData": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "status": {
    "clientCertificateData": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "clientKeyData": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
  }
}

可选地,响应可以包括格式为 RFC 3339 时间戳的凭据的到期时间。

存在或不存在到期时间的影响如下

  • 如果包含到期时间,则承载令牌和 TLS 凭据将缓存到达到到期时间,或者如果服务器响应 401 HTTP 状态代码,或者在进程退出时。
  • 如果省略到期时间,则承载令牌和 TLS 凭据将缓存到服务器响应 401 HTTP 状态代码或直到进程退出为止。

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token",
    "expirationTimestamp": "2018-03-05T17:30:20-08:00"
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "status": {
    "token": "my-bearer-token",
    "expirationTimestamp": "2018-03-05T17:30:20-08:00"
  }
}

为了使 exec 插件能够获取集群特定信息,请在 kubeconfig 中的 user.exec 字段上设置 provideClusterInfo。然后,插件将在 KUBERNETES_EXEC_INFO 环境变量中提供此集群特定信息。可以使用此环境变量中的信息来执行集群特定的凭据获取逻辑。以下 ExecCredential 清单描述了一个集群信息样本。

{
  "apiVersion": "client.authentication.k8s.io/v1",
  "kind": "ExecCredential",
  "spec": {
    "cluster": {
      "server": "https://172.17.4.100:6443",
      "certificate-authority-data": "LS0t...",
      "config": {
        "arbitrary": "config",
        "this": "can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo",
        "you": ["can", "put", "anything", "here"]
      }
    },
    "interactive": true
  }
}

{
  "apiVersion": "client.authentication.k8s.io/v1beta1",
  "kind": "ExecCredential",
  "spec": {
    "cluster": {
      "server": "https://172.17.4.100:6443",
      "certificate-authority-data": "LS0t...",
      "config": {
        "arbitrary": "config",
        "this": "can be provided via the KUBERNETES_EXEC_INFO environment variable upon setting provideClusterInfo",
        "you": ["can", "put", "anything", "here"]
      }
    },
    "interactive": true
  }
}

客户端的身份验证信息的 API 访问

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

您可以使用 SelfSubjectReview API 来确定您的 Kubernetes 集群如何将您的身份验证信息映射到将您识别为客户端。无论您是作为用户(通常代表真实的人)还是作为 ServiceAccount 进行身份验证,这都有效。

在典型的 Kubernetes 集群中,所有经过身份验证的用户都可以创建 SelfSubjectReviews。对执行此操作的访问权限由内置的 system:basic-user ClusterRole 允许。

客户端能够了解自己的身份对于解决 Kubernetes 集群中使用的复杂的身份验证流程非常有用;例如,如果您使用 webhook 令牌身份验证身份验证代理

如果您想在命令行上查询此信息,请参阅 CLI 访问身份验证信息

通过 HTTP 访问身份验证信息

SelfSubjectReviews 没有可配置的字段。在接收到请求后,Kubernetes API 服务器将状态填充为用户属性并将其返回给用户。这不会将命名资源持久保存到您的集群中:您无法获取 SelfSubjectReview,并且一旦您的 POST 请求完成,它将被丢弃。

请求示例(正文将是 SelfSubjectReview)

POST /apis/authentication.k8s.io/v1/selfsubjectreviews
{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview"
}

响应示例

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview",
  "status": {
    "userInfo": {
      "username": "janedoe@example.com",
      "groups": [
        "viewers",
        "editors",
        "system:authenticated"
      ]
    }
  }
}

此示例响应没有显示所有可用字段;并非所有身份验证机制都会填充每个可用字段。请参阅 SelfSubjectReview API 参考 以查看哪些字段可用。

这是一个也包含 uidextra 字段的另一个示例

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview",
  "status": {
    "userInfo": {
      "username": "janedoe@example.com",
      "groups": [
        "viewers",
        "editors",
        "system:authenticated"
      ],
      "uid": "000042",
      "extra": {
        "firstName": [
          "Jane"
        ],
        "familyName": [
          "Doe"
        ],
        "projectAssignments": [
          "web-frontend",
          "ai-training-proof-of-concept"
        ],
      }
    }
  }
}

这些可选字段中的数据来自您的身份验证集成或它使用的用户数据库。用户名、UID、额外信息以及所有不以 system: 开头的组都来自 Kubernetes 之外的来源。

当通过 HTTP 查询 Kubernetes API 时,您可以使用 Accept: HTTP 标头请求 JSON 或 YAML 响应;例如

POST /apis/authentication.k8s.io/v1/selfsubjectreviews HTTP/1.1
Accept: application/json;q=1.0
Content-Type: application/json
…other request headers

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview"
}

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview",
  "status": {
    "userInfo": {
      "username": "jane.doe",
      "uid": "b79dbf30-0c6a-11ed-861d-0242ac120002",
      "groups": [
        "students",
        "teachers",
        "system:authenticated"
      ],
      "extra": {
        "skills": [
          "reading",
          "learning"
        ],
        "subjects": [
          "math",
          "sports"
        ]
      }
    }
  }
}

POST /apis/authentication.k8s.io/v1/selfsubjectreviews HTTP/1.1
Accept: application/yaml;q=1.0
Content-Type: application/json
…other request headers

{
  "apiVersion": "authentication.k8s.io/v1",
  "kind": "SelfSubjectReview"
}

apiVersion: authentication.k8s.io/v1
kind: SelfSubjectReview
status:
  userInfo:
    username: jane.doe
    uid: b79dbf30-0c6a-11ed-861d-0242ac120002
    groups:
    - students
    - teachers
    - system:authenticated
    extra:
      skills:
      - reading
      - learning
      subjects:
      - math
      - sports

CLI 访问身份验证信息

为了方便起见,还提供了 kubectl auth whoami 子命令

kubectl auth whoami

输出类似于

  ATTRIBUTE         VALUE
  Username          george.boole
  Groups            [system:authenticated]

请参阅 kubectl auth whoami 以获取更多详细信息。

接下来

最后修改时间为太平洋标准时间 2025 年 9 月 20 日下午 3:37:改进 SelfSubjectReview 的解释 (9e7351e19a)