Kubernetes客户端认证(三)—— Kubernetes使用CertificateSigningRequest方式签发客户端证书
1、概述
在《Kubernetes客户端认证(一)—— 基于CA证书的双向认证方式》和《Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证》两篇博文中详细介绍了Kubernetes客户端认证方式,包括以证书方式访问的普通用户或进程(运维人员及 kubectl、 kubelet 等进程);以 ServiceAccount 方式(JWTToken)访问的 Kubernetes 的内部服务进程,它是给运行在 Pod 里的进程用的,它为 Pod 里的进程提供了必要的身份证明,但它并不是给 Kubernetes 集群的用户(系统管理员、 运维人员、租户用户等)用的,对于Kubernetes集群的用户可以通过证书或者接入外部用户系统来提供身份证明。而其中最简单的方式便是为用户签发客户端证书,签发客户端证书有两种方式,一种是基于CA根证书签发证书,另一个种是发起 CSR(Certificate Signing Requests)请求。
在《Kubernetes客户端认证(一)—— 基于CA证书的双向认证方式》这篇博文的3.2章节详细介绍了基于CA根证书签发证书,这种方式因为需要基于根CA证书、根CA私钥进行证书签发,一般需要在集群的master节点上进行配置,但是生产环境下一般情况下我们都没办法进入到集群的master节点机器,所以这种方式用的不多。但是一般情况我们都能拿到对应的一个kubeconfig文件用来访问k8s集群,基于kubeconfig 文件我们也可以进行证书的批准和授权,这就是k8s CSR机制,通过使用CSR方式签发客户端证书,这也是k8s推荐方式,本文主要讲解如果通过k8s CSR机制来为用户签发客户端证书。
2、CertificateSigningRequest(CSR)机制
CertificateSigningRequest(CSR)资源用来向指定的签名者申请证书签名, 在最终签名之前,申请可能被批准,也可能被拒绝。(特性状态: Kubernetes v1.19 [stable])
2.1 请求签名流程
CertificateSigningRequest 资源类型允许客户端基于签名请求申请发放 X.509 证书。 CertificateSigningRequest 对象在 spec.request 字段中包含一个 PEM 编码的 PKCS#10 签名请求。 CertificateSigningRequest 使用 spec.signerName 字段标示签名者(请求的接收方)。 注意,spec.signerName 在 certificates.k8s.io/v1 之后的 API 版本是必填项。 在 Kubernetes v1.22 和以后的版本,客户可以可选地设置 spec.expirationSeconds 字段来为颁发的证书设定一个特定的有效期。该字段的最小有效值是 600,也就是 10 分钟。
创建完成的 CertificateSigningRequest,要先通过批准,然后才能签名。 根据所选的签名者,CertificateSigningRequest 可能会被控制器自动批准。 否则,就必须人工批准, 人工批准可以使用 REST API(或 go 客户端),也可以执行 kubectl certificate approve 命令。 同样,CertificateSigningRequest 也可能被驳回, 这就相当于通知了指定的签名者,这个证书不能签名。
对于已批准的证书,下一步是签名。 对应的签名控制器首先验证签名条件是否满足,然后才创建证书。 签名控制器然后更新 CertificateSigningRequest, 将新证书保存到现有 CertificateSigningRequest 对象的 status.certificate 字段中。 此时,字段 status.certificate 要么为空,要么包含一个用 PEM 编码的 X.509 证书。 直到签名完成前,CertificateSigningRequest 的字段 status.certificate 都为空。
一旦 status.certificate 字段完成填充,请求既算完成, 客户端现在可以从 CertificateSigningRequest 资源中获取已签名的证书的 PEM 数据。 当然如果不满足签名条件,签名者可以拒签。
为了减少集群中遗留的过时的 CertificateSigningRequest 资源的数量, 一个垃圾收集控制器将会周期性地运行。 此垃圾收集器会清除在一段时间内没有改变过状态的 CertificateSigningRequests:
- 已批准的请求:1 小时后自动删除
- 已拒绝的请求:1 小时后自动删除
- 已失败的请求:1 小时后自动删除
- 挂起的请求:24 小时后自动删除
- 所有请求:在颁发的证书过期后自动删除
2.2 Kubernetes 签名者
Kubernetes 提供了内置的签名者,每个签名者都有一个众所周知的 signerName:
kubernetes.io/kube-apiserver-client:签名的证书将被 API 服务器视为客户证书。 kube-controller-manager 不会自动批准它。- 信任分发:签名的证书将被 API 服务器视为客户端证书。CA 证书包不通过任何其他方式分发。
- 许可的主体:没有主体限制,但审核人和签名者可以选择不批准或不签署。 某些主体,比如集群管理员级别的用户或组因部署和安装方式不同而不同, 所以批准和签署之前需要进行额外仔细审查。 用来限制
system:masters的 CertificateSubjectRestriction 准入插件默认处于启用状态, 但它通常不是集群中唯一的集群管理员主体。 - 许可的 x509 扩展:允许 subjectAltName 和 key usage 扩展,弃用其他扩展。
- 许可的密钥用途:必须包含
["client auth"],但不能包含["digital signature", "key encipherment", "client auth"]之外的键。 - 过期时间/证书有效期:对于 kube-controller-manager 实现的签名者, 设置为
--cluster-signing-duration选项和 CSR 对象的spec.expirationSeconds字段(如有设置该字段)中的最小值。 - 允许/不允许 CA 位:不允许。
kubernetes.io/kube-apiserver-client-kubelet: 签名的证书将被 kube-apiserver 视为客户证书。 kube-controller-manager 可以自动批准它。- 信任分发:签名的证书将被 API 服务器视为客户端证书。CA 证书包不通过任何其他方式分发。
- 许可的主体:组织名必须是
["system:nodes"],用户名以 "system:node:" 开头 - 许可的 x509 扩展:允许 key usage 扩展,禁用 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 不会自动批准它。- 信任分发:签名的证书必须被 kube-apiserver 认可,可有效的中止 kubelet 连接。CA 证书包不通过任何其他方式分发。
- 许可的主体:组织名必须是
["system:nodes"],用户名以 "system:node:" 开头 - 许可的 x509 扩展:允许 key usage、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 和 key usage 等扩展,并弃用其他扩展。
- 许可的密钥用途:全部。
- 过期时间/证书有效期:对于 kube-controller-manager 实现的签名者, 设置为
--cluster-signing-duration选项和 CSR 对象的spec.expirationSeconds字段(如有设置该字段)中的最小值。 - 允许/不允许 CA 位 - 不允许。
kube-controller-manager 为每个内置签名者实现了控制平面签名。 注意:所有这些故障仅在 kube-controller-manager 日志中报告。
3、通过 CSR 签发客户端证书实例
1)生成用户私钥
openssl genrsa -out zmc.key 2048
2)生成证书请求文件
// 基于用户私钥生成用户证书签名请求文件zmc.csr,其中CN代表k8s用户
openssl req -new -key zmc.key -subj "/CN=zmc" -out zmc.csr
3) 通过 kubectl 创建一个 CertificateSigningRequest 并将其提交到 Kubernetes 集群
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: zmc
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1V6Q0NBVHNDQVFBd0RqRU1NQW9HQTFVRUF3d0RlbTFqTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQwpBUThBTUlJQkNnS0NBUUVBbWFLRWY5ODBIRkhneG9WdXVBL29oNHlvU1JPNG8vbEU1N1J4UmduT1ZlR0tDbXZoCjRSOWZ3bk9IRzZaUjFVdkd4RzdKY0duaFJFMlFlUFVvcXpVYkVxWnFtc0V4NmpmTHgycTRqd3RNRm9GMDFnaHMKY2RwU0p1WTNEeFlKdFhtbUhKM2h3Q1N1MEZPT1NNMHU2V3JWZ0FFVkRCUno2a0RRcE1lcjlscmQwenBIRTdkUgpJSFNYbWVuVTVFTHVuTGh3a0E5TUhuczAweHhkcEhiR2QrTUFTVEU4LzcrNzR5T3hkQmJZQVhRK04rV2pZQ1NWCm5JT1dVUktWSFpCVDJIKzZxMjFvNkVxK2JlczB2MkhBWmZPTjZhOVVoU2FpZjRQRm9vTXlyS21xSFRkMFdrZlkKY1FZZFVzR0tBUFI3YVZrbmx4cWFxVCtEbXNqM0pBVFdZVjZBV3dJREFRQUJvQUF3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFIOFhoZjJEeVlMRldkQmJtazMwY3FHMkI1Qlh5dEFZWU0vOHQ1Z2UvZjhlMUtEeWQ4aXNQbitXCll1ak5mMzFrNGllRGpZb2NPaDFKZFlTRUkrTmgwdkFiVXVWaU94OU1RY3RUZjBXb0hHTklwRlZ3SFVsNTE2R3MKazRMMEgyVXM5WnlNMUJXSGxVaG13MDJncGs5VjV2RDc3QjN6dnh3aUs4UnJyZlA2YWVScGtnbzdOcFg0bEVMWApRSVY0VzBUWExsTjF2Si9UaGVncHhRZVhPZHZMbjJxd084aEgyVmRSRnQzODNWS0RTNFR0UFdWNGw5WTJGSkxVCk01NlhsdEFhcFd2aDBnV3U4RWVjbzhJd0tSY2xvYzU2RUlob05OVzBHN2lUeDgxVW1LUWlPRXl3RVZVNllPaHAKa25wbXhreWFGUXo4QTdIeG1ON2ZIaTdwdUNCcGZDUT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==
signerName: kubernetes.io/kube-apiserver-client
#expirationSeconds: 86400 # one day
usages:
- client auth
EOF
- request 字段是 CSR 文件内容的 base64 编码值。 要得到该值,可以执行命令
cat zmc.csr | base64 | tr -d "\n"
- expirationSeconds 证书过期时间(k8s 1.22版本之前没有这个字段,默认的过期时间是十年左右)
- usage 字段必须是 ‘client auth’,代表密钥的用途
注意:下面的 csr 代表的是 certificatesigningrequests(是k8s里面的一种资源),注意与上面的 certificate 区分开来。
查看CertificateSigningRequest资源状态

4)批准 CertificateSigningRequest
kubectl certificate approve zmc
查看CertificateSigningRequest资源状态

5)从 CertificateSigningRequest 导出颁发的证书
kubectl get csr zmc -o jsonpath='{.status.certificate}'| base64 -d > zmc.crt

当前k8s集群版本是1.21,可以看到默认的过期时间是十年左右。

验证新签发用户证书也是由kuberntests集群ca证书签发的。

6)使用签发的用户证书访问k8s集群资源
配置用户信息到到对应的 kubeconfig 上下文中。
将客户端证书文件 zmc.crt 和客户端密钥文件 zmc.key 设置为名为 zmc 的用户凭证,并将这些证书和密钥嵌入到 kubeconfig 文件中
kubectl config set-credentials zmc --client-certificate=zmc.crt --client-key=zmc.key --embed-certs=true
查看kubeconfig最新配置。
kubectl config view

为当前集群和用户zmc配置kubeconfi上下文。
kubectl config set-context zmc@cluster.local --cluster=cluster.local --user=zmc
切换上下文为当前新创建的用户。
kubectl config use-context zmc@cluster.local
再次查看kubeconfig最新配置。

使用签发的用户证书访问k8s集群资源。

注意: 如果访问资源没有权限就为用户当前k8s集群维护对应资源的RBAC权限,这块详细步骤可以参见《Kubernetes客户端认证(一)—— 基于CA证书的双向认证方式》和《Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证》这两篇博文,本文不再赘余。
4、总结
本文详细讲解了Kubernetes使用CertificateSigningRequest方式签发客户端证书详细步骤,基于kubectl和k8s集群交互为示例,当然也可以通过client-go与kube-apiserver交互管理CertificateSigningRequest资源签发客户端证书,并且对于可信客户端证书颁发请求还可以通过开发自定义控制器自动进行证书审批工作。
参考:K8S集群安全机制
参考:证书和证书签名请求 (详细步骤参加k8s官方文档)
Kubernetes客户端认证(三)—— Kubernetes使用CertificateSigningRequest方式签发客户端证书的更多相关文章
- Kubernetes客户端认证——基于CA证书的双向认证方式
1.Kubernetes 认证方式 Kubernetes集群的访问权限控制由API Server负责,API Server的访问权限控制由身份验证(Authentication).授权(Authori ...
- 在 ASP.NET 网页中不经过回发而以编程方式实现客户端回调
在 ASP.NET 网页的默认模型中,用户会与页交互,单击按钮或执行导致回发的一些其他操作.此时将重新创建页及其控件,并在服务器上运行页代码,且新版本的页被呈现到浏览器.但是,在有些情况下,需要从客户 ...
- Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证
1.概述 在 Kubernetes 官方手册中给出了 "用户" 的概念,Kubernetes 集群中存在的用户包括 "普通用户" 与 "Service ...
- Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress(转发)
原文 http://cloud.51cto.com/art/201804/570386.htm Kubernetes的三种外部访问方式:NodePort.LoadBalancer和Ingress 最近 ...
- 不吹不黑,今天我们来聊一聊 Kubernetes 落地的三种方式
作者 | 王国梁 Kubernetes 社区成员与项目维护者原文标题<Kubernetes 应用之道:让 Kubernetes落地的"三板斧">,首发于知乎专栏:进击 ...
- kubernetes学习笔记之十一:kubernetes dashboard认证及分级授权
第一章.部署dashboard 作为Kubernetes的Web用户界面,用户可以通过Dashboard在Kubernetes集群中部署容器化的应用,对应用进行问题处理和管理,并对集群本身进行管理.通 ...
- 【爬坑系列】之解读kubernetes的认证原理&实践
对于访问kube-apiserver模块的请求来说,如果是使用http协议,则会顺利进入模块内部得到自己想要的:但是如果是用的是https,则能否进入模块内部获得想要的资源,他会首先要进行https自 ...
- 附005.Kubernetes身份认证
一 Kubernetes访问 1.1 Kubernetes交互 与Kubernetes交互通常有kubectl.客户端(Dashboard).REST API请求. 1.2 API访问流程 用户使用k ...
- Kubernetes TLS认证
转自: https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/ 前段时间撸了一会 Kubernetes 官方文档,在查看 TLS ...
- (三)Kubernetes 快速入门
Kubernetes的核心对象 API Server提供了RESTful风格的编程接口,其管理的资源是Kubernetes API中的端点,用于存储某种API对象的集合,例如,内置Pod资源是包含了所 ...
随机推荐
- Python 装饰器解析(一)
装饰器用于在源码中"标记"函数,以增强函数的行为. 我们先来看下面的例子,现有一个求和函数add,现在要求统计函数执行的时长 def add(a, b): print(a+b) 最 ...
- 【OpenGL ES】绘制三角形
1 前言 1.1 设置顶点属性 顶点有位置.颜色等属性,可以通过 glVertexAttribPointer 设置顶点的属性. void glVertexAttribPointer( int in ...
- Js中fetch方法
Js中fetch方法 fetch()方法定义在Window对象以及WorkerGlobalScope对象上,用于发起获取资源的请求,其返回一个Promise对象,这个Promise对象会在请求响应后被 ...
- MySQL数据库备份与恢复方法
MySQL数据库备份与恢复方法 mysql -uroot -p show databases; 1.导出数据库 1).MySQL命令行导出整个数据库(包含数据) 导出文件默认是存在mysql\bin目 ...
- centos7 搭建snmpv3靶场
安装文件 yum install net-snmp net-snmp-utils -y 关闭服务创建用户 systemctl stop snmpd # 添加一个用户 如 root net-snmp-c ...
- win32 - EnumDisplayDevices和EnumDisplayMonitors的使用
EnumDisplayDevices枚举适配器 EnumDisplayMonitors枚举监视器 #pragma comment(lib, "dxva2.lib") #includ ...
- 使用二进制重排 & Clang插桩技术点来进行iOS冷启动进行优化
1.冷启动 1.1 什么是冷启动? 冷启动是指内存中不包含该应用程序相关的数据,必须要从磁盘载入到内存中的启动过程. 注意:重新打开 APP, 不一定就是冷启动. 当内存不足,APP被系统自动杀死后, ...
- 第一百一十一篇:基本引用类型Date
好家伙,本篇为<JS高级程序设计>第五章的学习笔记 1.基本引用类型 引用值(或者对象)是某个特定引用类型的实例,在ECMAScript中,引用类型是把数据和功能组织到一起的结构,(像 ...
- 【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析
问题描述 Azure Redis Cluster 在增加分片数时失败,错误消息为: ResponseBody: { "error": { "details": ...
- 百度爱番番基于图技术、流式计算的实时CDP建设实践
导读:随着营销3.0时代的到来,企业愈发需要依托强大CDP能力解决其严重的数据孤岛问题,帮助企业加温线索.促活客户.但什么是CDP.好的CDP应该具备哪些关键特征?本文在回答此问题的同时,详细讲述了爱 ...