kubernetes 自身支持的用户管理以及认证功能相当薄弱,支持的 x509 client certs、static token file、service account token 的使用场景和使用方式非常有限, 通常只用于内部组件的认证,不足以支撑常规的账号管理场景。要实现灵活复杂的用户管理/认证功能,需要通过 kubernetes 提供的扩展能力对接到外部系统。
资料:
kubernetes 识别的账号需要包含以下信息:
对接的外部认证系统至少要能够向 kubernetes 提供上述 4 项账号信息。
内置账号功能通常只用于 kubernetes 自身组件(有限用户)的认证。
用户请求 apiserver 的时候通过证书认证,apiserver 从认证证书中解析出用户名,证书中的 common name/CN 是用户名,Organization/O 是用户所在的组。用户证书需要用 kubernetes apiserver 指定的 CA 签署。0
签署一个用户名为 jbeda,隶属 app1 和 app2 两个组的用户证书:
openssl req -new -key jbeda.pem -out jbeda-csr.pem -subj "/CN=jbeda/O=app1/O=app2"
用户证书不包含 UID 以及 Extra Fields 等信息,它通常用于构成 kubernets 的组件的认证,比如 kubelet。
kubernetes apiserver 支持通过 --token-auth-file=
传入用文本描述 token 账号,格式如下:
token,user,uid,"group1,group2,group3"
APIserver 通过 bearer tokens 匹配得到当前用户的信息。
bootstrap 是 kubernetes 自动维护的一个 bear token(需要 apiserver 启动时指定启用),kubernestes 自动将过期的 token 作废并生成新的 bear token。bootstrap token 样式如下:
Authorization: Bearer 781292.db7bc3a58fc5f07e
bootstrap token 会被识别为用户 system:bootstrap:<Token ID>
,隶属于用户组 system:bootstrappers
。
ServiceAccount 是 kubernetes 内置的一种资源类型,隶属于某一 namespace。ServiceAccount 可以挂载到 pod 中,用于 pod 内程序和 apiserver 间的认证。ServiceAccount 的内容如果泄漏到集群外,也可以在集群外使用。
通过 ServiceAccount 认证,用户名识别为 system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)
,隶属于用户组 system:serviceaccounts
和 system:serviceaccounts:(NAMESPACE)
。
apiserver 启动时指定外部的 Identity Provider。用户向 apiserver 请求时,先从 Identity Provider 获取到 token,然后带着 token 访问 apiserver。 apiserver 通过指定的 Identity Provider 验证 token,解析账号信息。
apiserver 收到请求后回调启动配置的 webhook,向 webhook 传入 TokenReview,webhook 向其返回包含 Status 的 TokenReview。
apiserver 向 webhook 传入的 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"]
}
}
webhook 向 apiserver 返回的 TokenReview:
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenReview",
"status": {
"authenticated": true,
"user": {
# Required
"username": "[email protected]",
# 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"]
}
}
这里的 proxy 是在 kubernetes 的 apiserver 之前架设 proxy。proxy 完成用户认证后,将用户的账号信息附加到 header 中转发给 kubernetes apiserver。 kubernetes apiserver 启动指定用于来解读账号信息的 header 名称。
--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-