证书和证书签名请求
Kubernetes 证书和信任捆绑 API 通过为 Kubernetes API 的客户端提供一个编程接口来请求和获取 X.509 证书,从而实现 X.509 凭据供应的自动化。
还对分发 信任捆绑 提供了实验性(alpha)支持。
证书签名请求
Kubernetes v1.19 [稳定]
证书签名请求 (CSR) 资源用于请求由指定签名者签署证书,之后可以在最终签署之前批准或拒绝该请求。
请求签名过程
证书签名请求资源类型允许客户端根据签名请求要求签发 X.509 证书。证书签名请求对象在 spec.request
字段中包含一个 PEM 编码的 PKCS#10 签名请求。证书签名请求使用 spec.signerName
字段指定签名者(正在向其发出请求的接收者)。请注意,在 API 版本 certificates.k8s.io/v1
之后,spec.signerName
是一个必需的键。在 Kubernetes v1.22 及更高版本中,客户端可以选择设置 spec.expirationSeconds
字段来请求为已签发的证书指定有效期。此字段的最小有效值为 600
,即十分钟。
创建后,证书签名请求必须在签署之前获得批准。根据所选的签名者,证书签名请求可能会被 控制器 自动批准。否则,证书签名请求必须通过 REST API(或 client-go)或通过运行 kubectl certificate approve
手动批准。同样,证书签名请求也可以被拒绝,这告诉配置的签名者它不能签署该请求。
对于已批准的证书,下一步是签署。相关的签名控制器首先验证签名条件是否满足,然后创建证书。签名控制器随后更新证书签名请求,将新证书存储到现有证书签名请求对象的 status.certificate
字段中。status.certificate
字段为空或包含一个以 PEM 格式编码的 X.509 证书。在签名者执行此操作之前,证书签名请求 status.certificate
字段为空。
一旦 status.certificate
字段被填充,请求就已完成,客户端现在可以从证书签名请求资源中获取已签署的证书 PEM 数据。如果批准条件不满足,签名者可以拒绝证书签名。
为了减少集群中遗留的旧证书签名请求资源的数量,垃圾回收控制器会定期运行。垃圾回收会删除在一段时间内状态没有改变的证书签名请求。
- 已批准的请求:在 1 小时后自动删除
- 拒绝的请求:在 1 小时后自动删除
- 失败的请求:在 1 小时后自动删除
- 待处理的请求:在 24 小时后自动删除
- 所有请求:在已签发的证书过期后自动删除
证书签名授权
允许创建证书签名请求并检索任何证书签名请求
- 动词:
create
、get
、list
、watch
,组:certificates.k8s.io
,资源:certificatesigningrequests
例如
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-creator
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- create
- get
- list
- watch
允许批准证书签名请求
- 动词:
get
、list
、watch
,组:certificates.k8s.io
,资源:certificatesigningrequests
- 动词:
update
,组:certificates.k8s.io
,资源:certificatesigningrequests/approval
- 动词:
approve
,组:certificates.k8s.io
,资源:signers
,资源名称:<signerNameDomain>/<signerNamePath>
或<signerNameDomain>/*
例如
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve
允许签署证书签名请求
- 动词:
get
、list
、watch
,组:certificates.k8s.io
,资源:certificatesigningrequests
- 动词:
update
,组:certificates.k8s.io
,资源:certificatesigningrequests/status
- 动词:
sign
,组:certificates.k8s.io
,资源:signers
,资源名称:<signerNameDomain>/<signerNamePath>
或<signerNameDomain>/*
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-signer
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/status
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- sign
签名者
签名者抽象地代表可能签署或已签署安全证书的实体或实体。
任何在特定集群之外可用的签名者都应提供有关签名者工作方式的信息,以便使用者可以了解这对证书签名请求和(如果启用)集群信任捆绑 的意义。
这包括
- 信任分发:信任锚(CA 证书或证书捆绑)如何分发。
- 允许的主题:对不允许的主题的任何限制和行为。
- 允许的 x509 扩展:包括 IP subjectAltNames、DNS subjectAltNames、Email subjectAltNames、URI subjectAltNames 等,以及在请求不允许的扩展时所采取的行为。
- 允许的密钥使用/扩展密钥使用:对签名者确定的使用以外的使用方式的任何限制和行为,这些使用方式在 CSR 中指定。
- 到期/证书有效期:是固定由签名者设置、由管理员配置、由 CSR
spec.expirationSeconds
字段确定,等等,以及当签名者确定的到期时间与 CSRspec.expirationSeconds
字段不同时的行为。 - 允许/不允许的 CA 位:以及当 CSR 包含对 CA 证书的请求而签名者不允许时所采取的行为。
通常,证书签名请求的 status.certificate
字段包含一个单个 PEM 编码的 X.509 证书,一旦 CSR 被批准并且证书被签发。一些签名者将多个证书存储到 status.certificate
字段中。在这种情况下,签名者的文档应指定附加证书的含义;例如,这可能是证书加上在 TLS 握手期间要呈现的中介证书。
如果您想使信任锚(根证书)可用,这应该与证书签名请求及其 status.certificate
字段分开进行。例如,您可以使用集群信任捆绑。
PKCS#10 签名请求格式没有标准机制来指定证书到期时间或有效期。因此,到期时间或有效期必须通过 CSR 对象的 spec.expirationSeconds
字段设置。内置签名者使用 ClusterSigningDuration
配置选项,该选项默认为 1 年(kube-controller-manager
的 --cluster-signing-duration
命令行标志),作为未指定 spec.expirationSeconds
时的默认值。当指定 spec.expirationSeconds
时,使用 spec.expirationSeconds
和 ClusterSigningDuration
中的较小值。
注意
spec.expirationSeconds
字段是在 Kubernetes v1.22 中添加的。早期的 Kubernetes 版本不尊重此字段。在 v1.22 之前的 Kubernetes API 服务器将在创建对象时静默丢弃此字段。Kubernetes 签名者
Kubernetes 提供内置签名者,每个签名者都有一个众所周知的 signerName
kubernetes.io/kube-apiserver-client
:签署将被 API 服务器视为客户端证书的证书。从不自动被 kube-controller-manager 批准。- 信任分发:签署的证书必须被 API 服务器视为客户端证书。CA 捆绑包不会通过任何其他方式分发。
- 允许的主题 - 没有主题限制,但审批者和签名者可以选择不批准或签署。某些主题(如集群管理员级用户或组)在不同发行版和安装之间有所不同,但在批准和签署之前需要额外的审查。
CertificateSubjectRestriction
准入插件默认启用以限制system:masters
,但它通常不是集群中唯一的集群管理员主题。 - 允许的 x509 扩展 - 尊重 subjectAltName 和密钥使用扩展,并丢弃其他扩展。
- 允许的密钥使用 - 必须包含
["client auth"]
。不得包含超出["digital signature", "key encipherment", "client auth"]
的密钥使用。 - 到期/证书有效期 - 对于 kube-controller-manager 对此签名者的实现,设置为
--cluster-signing-duration
选项的最小值,或者如果指定,则为 CSR 对象的spec.expirationSeconds
字段。 - 允许/不允许的 CA 位 - 不允许。
kubernetes.io/kube-apiserver-client-kubelet
:签署将被 API 服务器视为客户端证书的客户端证书。可能会被 kube-controller-manager 自动批准。- 信任分发:签署的证书必须被 API 服务器视为客户端证书。CA 捆绑包不会通过任何其他方式分发。
- 允许的主题 - 组织完全是
["system:nodes"]
,通用名称以“system:node:
”开头。 - 允许的 x509 扩展 - 尊重密钥使用扩展,禁止 subjectAltName 扩展,并丢弃其他扩展。
- 允许的密钥使用 -
["key encipherment", "digital signature", "client auth"]
或["digital signature", "client auth"]
。 - 到期/证书有效期 - 对于 kube-controller-manager 对此签名者的实现,设置为
--cluster-signing-duration
选项的最小值,或者如果指定,则为 CSR 对象的spec.expirationSeconds
字段。 - 允许/不允许的 CA 位 - 不允许。
kubernetes.io/kubelet-serving
:签署服务证书,这些证书被 API 服务器视为有效的 kubelet 服务证书,但没有其他保证。从不自动被 kube-controller-manager 批准。- 信任分发:签署的证书必须被 API 服务器视为有效证书,以终止与 kubelet 的连接。CA 捆绑包不会通过任何其他方式分发。
- 允许的主题 - 组织完全是
["system:nodes"]
,通用名称以“system:node:
”开头。 - 允许的 x509 扩展 - 遵守密钥使用和 DNSName/IPAddress subjectAltName 扩展,禁止 EmailAddress 和 URI subjectAltName 扩展,丢弃其他扩展。必须至少存在一个 DNS 或 IP subjectAltName。
- 允许的密钥使用 -
["key encipherment", "digital signature", "server auth"]
或["digital signature", "server auth"]
。 - 到期/证书有效期 - 对于 kube-controller-manager 对此签名者的实现,设置为
--cluster-signing-duration
选项的最小值,或者如果指定,则为 CSR 对象的spec.expirationSeconds
字段。 - 允许/不允许的 CA 位 - 不允许。
kubernetes.io/legacy-unknown
:完全没有信任保证。Kubernetes 的一些第三方发行版可能会认可由它签署的客户端证书。稳定的 CertificateSigningRequest API(版本certificates.k8s.io/v1
及更高版本)不允许将signerName
设置为kubernetes.io/legacy-unknown
。绝不会被 kube-controller-manager 自动批准。- 信任分发:无。此签名者在 Kubernetes 集群中没有标准的信任或分发。
- 允许的主题 - 任何
- 允许的 x509 扩展 - 尊重 subjectAltName 和密钥使用扩展,并丢弃其他扩展。
- 允许的密钥使用 - 任何
- 到期/证书有效期 - 对于 kube-controller-manager 对此签名者的实现,设置为
--cluster-signing-duration
选项的最小值,或者如果指定,则为 CSR 对象的spec.expirationSeconds
字段。 - 允许/不允许的 CA 位 - 不允许。
kube-controller-manager 为每个内置签名者实现了 控制平面签名。所有这些签名者的失败只会记录在 kube-controller-manager 日志中。
注意
spec.expirationSeconds
字段是在 Kubernetes v1.22 中添加的。早期的 Kubernetes 版本不尊重此字段。在 v1.22 之前的 Kubernetes API 服务器将在创建对象时静默丢弃此字段。这些签名者的信任分发是在带外进行的。除了上面描述的信任之外,任何其他信任都是严格的巧合。例如,一些发行版可能会将 kubernetes.io/legacy-unknown
视为 kube-apiserver 的客户端证书,但这并非标准。这些用法均与 ServiceAccount 令牌密钥 .data[ca.crt]
无关。该 CA 捆绑包仅保证使用默认服务(kubernetes.default.svc
)验证与 API 服务器的连接。
自定义签名者
您还可以引入自己的自定义签名者,它应该具有类似的带前缀的名称,但使用您自己的域名。例如,如果您代表一个使用域名 open-fictional.example
的开源项目,那么您可以使用 issuer.open-fictional.example/service-mesh
作为签名者名称。
自定义签名者使用 Kubernetes API 来颁发证书。请参阅 基于 API 的签名者。
签名
控制平面签名者
Kubernetes 控制平面实现了每个 Kubernetes 签名者,作为 kube-controller-manager 的一部分。
注意
在 Kubernetes v1.18 之前,kube-controller-manager 会签署所有标记为已批准的 CSR。注意
spec.expirationSeconds
字段是在 Kubernetes v1.22 中添加的。早期的 Kubernetes 版本不尊重此字段。在 v1.22 之前的 Kubernetes API 服务器将在创建对象时静默丢弃此字段。基于 API 的签名者
REST API 的用户可以通过向要签署的 CSR 的 status
子资源提交 UPDATE 请求来签署 CSR。
作为此请求的一部分,status.certificate
字段应设置为包含已签署的证书。此字段包含一个或多个 PEM 编码的证书。
所有 PEM 块必须具有“CERTIFICATE”标签,不包含任何标头,并且编码数据必须是 BER 编码的 ASN.1 证书结构,如 RFC5280 第 4 节 中所述。
示例证书内容
-----BEGIN CERTIFICATE-----
MIIDgjCCAmqgAwIBAgIUC1N1EJ4Qnsd322BhDPRwmg3b/oAwDQYJKoZIhvcNAQEL
BQAwXDELMAkGA1UEBhMCeHgxCjAIBgNVBAgMAXgxCjAIBgNVBAcMAXgxCjAIBgNV
BAoMAXgxCjAIBgNVBAsMAXgxCzAJBgNVBAMMAmNhMRAwDgYJKoZIhvcNAQkBFgF4
MB4XDTIwMDcwNjIyMDcwMFoXDTI1MDcwNTIyMDcwMFowNzEVMBMGA1UEChMMc3lz
dGVtOm5vZGVzMR4wHAYDVQQDExVzeXN0ZW06bm9kZToxMjcuMC4wLjEwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDne5X2eQ1JcLZkKvhzCR4Hxl9+ZmU3
+e1zfOywLdoQxrPi+o4hVsUH3q0y52BMa7u1yehHDRSaq9u62cmi5ekgXhXHzGmm
kmW5n0itRECv3SFsSm2DSghRKf0mm6iTYHWDHzUXKdm9lPPWoSOxoR5oqOsm3JEh
Q7Et13wrvTJqBMJo1GTwQuF+HYOku0NF/DLqbZIcpI08yQKyrBgYz2uO51/oNp8a
sTCsV4OUfyHhx2BBLUo4g4SptHFySTBwlpRWBnSjZPOhmN74JcpTLB4J5f4iEeA7
2QytZfADckG4wVkhH3C2EJUmRtFIBVirwDn39GXkSGlnvnMgF3uLZ6zNAgMBAAGj
YTBfMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNVHRMB
Af8EAjAAMB0GA1UdDgQWBBTREl2hW54lkQBDeVCcd2f2VSlB1DALBgNVHREEBDAC
ggAwDQYJKoZIhvcNAQELBQADggEBABpZjuIKTq8pCaX8dMEGPWtAykgLsTcD2jYr
L0/TCrqmuaaliUa42jQTt2OVsVP/L8ofFunj/KjpQU0bvKJPLMRKtmxbhXuQCQi1
qCRkp8o93mHvEz3mTUN+D1cfQ2fpsBENLnpS0F4G/JyY2Vrh19/X8+mImMEK5eOy
o0BMby7byUj98WmcUvNCiXbC6F45QTmkwEhMqWns0JZQY+/XeDhEcg+lJvz9Eyo2
aGgPsye1o3DpyXnyfJWAWMhOz7cikS5X2adesbgI86PhEHBXPIJ1v13ZdfCExmdd
M1fLPhLyR54fGaY+7/X8P9AZzPefAkwizeXwe9ii6/a08vWoiE4=
-----END CERTIFICATE-----
非 PEM 内容可能出现在 CERTIFICATE PEM 块之前或之后,并且未经验证,以允许解释性文本,如 RFC7468 第 5.2 节 中所述。
当以 JSON 或 YAML 编码时,此字段是 base-64 编码的。包含上述示例证书的 CertificateSigningRequest 将如下所示
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
...
status:
certificate: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JS..."
批准或拒绝
在 签名者 根据 CertificateSigningRequest 颁发证书之前,签名者通常会检查该 CSR 的颁发是否已批准。
控制平面自动批准
kube-controller-manager 附带一个内置批准者,用于签名者名称为 kubernetes.io/kube-apiserver-client-kubelet
的证书,该批准者将节点凭据的 CSR 上的各种权限委托给授权。kube-controller-manager 向 API 服务器发布 SubjectAccessReview 资源以检查证书批准的授权。
使用 kubectl
批准或拒绝
Kubernetes 管理员(具有适当权限)可以通过使用 kubectl certificate approve
和 kubectl certificate deny
命令手动批准(或拒绝)CertificateSigningRequest。
要使用 kubectl 批准 CSR
kubectl certificate approve <certificate-signing-request-name>
同样,要拒绝 CSR
kubectl certificate deny <certificate-signing-request-name>
使用 Kubernetes API 批准或拒绝
REST API 的用户可以通过向要批准的 CSR 的 approval
子资源提交 UPDATE 请求来批准 CSR。例如,您可以编写一个 operator,它监视特定类型的 CSR,然后发送 UPDATE 来批准它们。
当您发出批准或拒绝请求时,请根据您确定的状态设置 Approved
或 Denied
状态条件
对于 Approved
CSR
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
...
status:
conditions:
- lastUpdateTime: "2020-02-08T11:37:35Z"
lastTransitionTime: "2020-02-08T11:37:35Z"
message: Approved by my custom approver controller
reason: ApprovedByMyPolicy # You can set this to any string
type: Approved
对于 Denied
CSR
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
...
status:
conditions:
- lastUpdateTime: "2020-02-08T11:37:35Z"
lastTransitionTime: "2020-02-08T11:37:35Z"
message: Denied by my custom approver controller
reason: DeniedByMyPolicy # You can set this to any string
type: Denied
通常将 status.conditions.reason
设置为使用 TitleCase 的机器友好的原因代码;这是一个约定,但您可以将其设置为任何您喜欢的值。如果您想添加供人类阅读的说明,请使用 status.conditions.message
字段。
集群信任捆绑包
Kubernetes v1.27 [alpha]
ClusterTrustBundles 是一个集群范围的对象,用于将 X.509 信任锚(根证书)分发到集群中的工作负载。它们旨在与 CertificateSigningRequests 中的 签名者 概念配合使用。
ClusterTrustBundles 可以使用两种模式:签名者链接 和 签名者未链接。
通用属性和验证
所有 ClusterTrustBundle 对象对其 trustBundle
字段的内容都有严格的验证。该字段必须包含一个或多个 X.509 证书,DER 序列化,每个证书都包装在 PEM CERTIFICATE
块中。证书必须解析为有效的 X.509 证书。
在对象验证期间,会拒绝诸如块间数据和块内标头之类的深奥 PEM 功能,或者可以被对象的使用者忽略。此外,使用者被允许以他们自己的任意但稳定的顺序重新排序捆绑包中的证书。
ClusterTrustBundle 对象应被视为集群内可供所有人读取。如果您的集群使用 RBAC 授权,所有 ServiceAccount 都具有一个默认授权,允许它们获取、列出和监视所有 ClusterTrustBundle 对象。如果您使用自己的授权机制并且已在您的集群中启用 ClusterTrustBundles,您应该设置一个等效规则以使这些对象在集群内公开,以便它们按预期工作。
如果您在集群中默认没有权限列出集群信任捆绑包,您可以模拟您有权访问的服务帐户以查看可用的 ClusterTrustBundles
kubectl get clustertrustbundles --as='system:serviceaccount:mynamespace:default'
签名者链接的 ClusterTrustBundles
签名者链接的 ClusterTrustBundles 与签名者名称相关联,如下所示
apiVersion: certificates.k8s.io/v1alpha1
kind: ClusterTrustBundle
metadata:
name: example.com:mysigner:foo
spec:
signerName: example.com/mysigner
trustBundle: "<... PEM data ...>"
这些 ClusterTrustBundles 旨在由集群中的特定于签名者的控制器维护,因此它们具有几个安全功能
- 要创建或更新签名者链接的 ClusterTrustBundle,您必须被允许对签名者进行证明(自定义授权动词
attest
,API 组certificates.k8s.io
;资源路径signers
)。您可以为特定资源名称<signerNameDomain>/<signerNamePath>
配置授权,或匹配诸如<signerNameDomain>/*
之类的模式。 - 签名者链接的 ClusterTrustBundles 必须使用从其
spec.signerName
字段派生的前缀命名。斜杠 (/
) 将替换为冒号 (:
),并在末尾追加一个冒号。其后是一个任意名称。例如,签名者example.com/mysigner
可以链接到 ClusterTrustBundleexample.com:mysigner:<arbitrary-name>
。
签名者链接的 ClusterTrustBundles 通常会在工作负载中通过对签名者名称使用 字段选择器 和一个单独的 标签选择器 的组合来使用。
签名者未链接的 ClusterTrustBundles
签名者未链接的 ClusterTrustBundles 具有一个空的 spec.signerName
字段,如下所示
apiVersion: certificates.k8s.io/v1alpha1
kind: ClusterTrustBundle
metadata:
name: foo
spec:
# no signerName specified, so the field is blank
trustBundle: "<... PEM data ...>"
它们主要用于集群配置用例。每个签名者未链接的 ClusterTrustBundle 都是一个独立的对象,与签名者链接的 ClusterTrustBundles 的习惯性分组行为形成对比。
签名者未链接的 ClusterTrustBundles 没有 attest
动词要求。相反,您可以使用通常的机制(例如基于角色的访问控制)直接控制对它们的访问。
为了将它们与签名者链接的 ClusterTrustBundles 区分开来,签名者未链接的 ClusterTrustBundles 的名称不能包含冒号 (:
)。
从 Pod 访问 ClusterTrustBundles
Kubernetes v1.29 [alpha]
ClusterTrustBundles 的内容可以注入到容器文件系统中,类似于 ConfigMaps 和 Secrets。有关更多详细信息,请参阅 clusterTrustBundle 投影卷源。
如何为用户颁发证书
为了让普通用户能够进行身份验证并调用 API,需要执行以下几个步骤。首先,此用户必须拥有由 Kubernetes 集群颁发的证书,然后将该证书提供给 Kubernetes API。
创建私钥
以下脚本展示了如何生成 PKI 私钥和 CSR。设置 CSR 的 CN 和 O 属性非常重要。CN 是用户的名称,O 是该用户将所属的组。您可以参考 RBAC 以了解标准组。
openssl genrsa -out myuser.key 2048
openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"
创建 CertificateSigningRequest
创建 CertificateSigningRequest 并通过 kubectl 将其提交到 Kubernetes 集群。以下是一个生成 CertificateSigningRequest 的脚本。
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: myuser
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400 # one day
usages:
- client auth
EOF
需要注意的一些要点
usages
必须是 'client auth
'expirationSeconds
可以延长(例如,864000
表示十天)或缩短(例如,3600
表示一小时)request
是 CSR 文件内容的 base64 编码值。您可以使用以下命令获取内容cat myuser.csr | base64 | tr -d "\n"
批准 CertificateSigningRequest
使用 kubectl 创建 CSR 并批准它。
获取 CSR 列表
kubectl get csr
批准 CSR
kubectl certificate approve myuser
获取证书
从 CSR 中检索证书
kubectl get csr/myuser -o yaml
证书值以 Base64 编码格式存储在 status.certificate
下。
从 CertificateSigningRequest 中导出已颁发的证书。
kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt
创建角色和角色绑定
创建证书后,需要为该用户定义角色和角色绑定,以便其访问 Kubernetes 集群资源。
以下是一个为新用户创建角色的示例命令
kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods
以下是一个为新用户创建角色绑定的示例命令
kubectl create rolebinding developer-binding-myuser --role=developer --user=myuser
添加到 kubeconfig
最后一步是将该用户添加到 kubeconfig 文件中。
首先,您需要添加新的凭据
kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true
然后,您需要添加上下文
kubectl config set-context myuser --cluster=kubernetes --user=myuser
要进行测试,请将上下文更改为 myuser
kubectl config use-context myuser
下一步
- 阅读 在集群中管理 TLS 证书
- 查看在 signer 中构建的 kube-controller-manager 的源代码
- 查看在 approver 中构建的 kube-controller-manager 的源代码
- 有关 X.509 本身的详细信息,请参阅 RFC 5280 第 3.1 节
- 有关 PKCS#10 证书签名请求语法的详细信息,请参阅 RFC 2986
- 阅读有关 ClusterTrustBundle API 的信息