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:

  1. kubernetes.io/kube-apiserver-client:签名的证书将被 API 服务器视为客户证书。 kube-controller-manager 不会自动批准它。
    1. 信任分发:签名的证书将被 API 服务器视为客户端证书。CA 证书包不通过任何其他方式分发。
    2. 许可的主体:没有主体限制,但审核人和签名者可以选择不批准或不签署。 某些主体,比如集群管理员级别的用户或组因部署和安装方式不同而不同, 所以批准和签署之前需要进行额外仔细审查。 用来限制 system:masters 的 CertificateSubjectRestriction 准入插件默认处于启用状态, 但它通常不是集群中唯一的集群管理员主体。
    3. 许可的 x509 扩展:允许 subjectAltName 和 key usage 扩展,弃用其他扩展。
    4. 许可的密钥用途:必须包含 ["client auth"],但不能包含 ["digital signature", "key encipherment", "client auth"] 之外的键。
    5. 过期时间/证书有效期:对于 kube-controller-manager 实现的签名者, 设置为 --cluster-signing-duration 选项和 CSR 对象的 spec.expirationSeconds 字段(如有设置该字段)中的最小值。
    6. 允许/不允许 CA 位:不允许。
  1. kubernetes.io/kube-apiserver-client-kubelet: 签名的证书将被 kube-apiserver 视为客户证书。 kube-controller-manager 可以自动批准它。

    1. 信任分发:签名的证书将被 API 服务器视为客户端证书。CA 证书包不通过任何其他方式分发。
    2. 许可的主体:组织名必须是 ["system:nodes"],用户名以 "system:node:" 开头
    3. 许可的 x509 扩展:允许 key usage 扩展,禁用 subjectAltName 扩展,并删除其他扩展。
    4. 许可的密钥用途:["key encipherment", "digital signature", "client auth"] 或 ["digital signature", "client auth"]
    5. 过期时间/证书有效期:对于 kube-controller-manager 实现的签名者, 设置为 --cluster-signing-duration 选项和 CSR 对象的 spec.expirationSeconds 字段(如有设置该字段)中的最小值。
    6. 允许/不允许 CA 位:不允许。
  1. kubernetes.io/kubelet-serving: 签名服务证书,该服务证书被 API 服务器视为有效的 kubelet 服务证书, 但没有其他保证。kube-controller-manager 不会自动批准它。
    1. 信任分发:签名的证书必须被 kube-apiserver 认可,可有效的中止 kubelet 连接。CA 证书包不通过任何其他方式分发。
    2. 许可的主体:组织名必须是 ["system:nodes"],用户名以 "system:node:" 开头
    3. 许可的 x509 扩展:允许 key usage、DNSName/IPAddress subjectAltName 等扩展, 禁止 EmailAddress、URI subjectAltName 等扩展,并丢弃其他扩展。 至少有一个 DNS 或 IP 的 SubjectAltName 存在。
    4. 许可的密钥用途:["key encipherment", "digital signature", "server auth"] 或 ["digital signature", "server auth"]
    5. 过期时间/证书有效期:对于 kube-controller-manager 实现的签名者, 设置为 --cluster-signing-duration 选项和 CSR 对象的 spec.expirationSeconds 字段(如有设置该字段)中的最小值。
    6. 允许/不允许 CA 位:不允许。
  1. kubernetes.io/legacy-unknown: 不保证信任。Kubernetes 的一些第三方发行版可能会使用它签署的客户端证书。 稳定版的 CertificateSigningRequest API(certificates.k8s.io/v1 以及之后的版本)不允许将 signerName 设置为 kubernetes.io/legacy-unknown。 kube-controller-manager 不会自动批准这类请求。
    1. 信任分发:没有。这个签名者在 Kubernetes 集群中没有标准的信任或分发。
    2. 许可的主体:全部。
    3. 许可的 x509 扩展:允许 subjectAltName 和 key usage 等扩展,并弃用其他扩展。
    4. 许可的密钥用途:全部。
    5. 过期时间/证书有效期:对于 kube-controller-manager 实现的签名者, 设置为 --cluster-signing-duration 选项和 CSR 对象的 spec.expirationSeconds 字段(如有设置该字段)中的最小值。
    6. 允许/不允许 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方式签发客户端证书的更多相关文章

  1. Kubernetes客户端认证——基于CA证书的双向认证方式

    1.Kubernetes 认证方式 Kubernetes集群的访问权限控制由API Server负责,API Server的访问权限控制由身份验证(Authentication).授权(Authori ...

  2. 在 ASP.NET 网页中不经过回发而以编程方式实现客户端回调

    在 ASP.NET 网页的默认模型中,用户会与页交互,单击按钮或执行导致回发的一些其他操作.此时将重新创建页及其控件,并在服务器上运行页代码,且新版本的页被呈现到浏览器.但是,在有些情况下,需要从客户 ...

  3. Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证

    1.概述 在 Kubernetes 官方手册中给出了 "用户" 的概念,Kubernetes 集群中存在的用户包括 "普通用户" 与 "Service ...

  4. Kubernetes的三种外部访问方式:NodePort、LoadBalancer和Ingress(转发)

    原文 http://cloud.51cto.com/art/201804/570386.htm Kubernetes的三种外部访问方式:NodePort.LoadBalancer和Ingress 最近 ...

  5. 不吹不黑,今天我们来聊一聊 Kubernetes 落地的三种方式

    作者 | 王国梁  Kubernetes 社区成员与项目维护者原文标题<Kubernetes 应用之道:让 Kubernetes落地的"三板斧">,首发于知乎专栏:进击 ...

  6. kubernetes学习笔记之十一:kubernetes dashboard认证及分级授权

    第一章.部署dashboard 作为Kubernetes的Web用户界面,用户可以通过Dashboard在Kubernetes集群中部署容器化的应用,对应用进行问题处理和管理,并对集群本身进行管理.通 ...

  7. 【爬坑系列】之解读kubernetes的认证原理&实践

    对于访问kube-apiserver模块的请求来说,如果是使用http协议,则会顺利进入模块内部得到自己想要的:但是如果是用的是https,则能否进入模块内部获得想要的资源,他会首先要进行https自 ...

  8. 附005.Kubernetes身份认证

    一 Kubernetes访问 1.1 Kubernetes交互 与Kubernetes交互通常有kubectl.客户端(Dashboard).REST API请求. 1.2 API访问流程 用户使用k ...

  9. Kubernetes TLS认证

    转自: https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/ 前段时间撸了一会 Kubernetes 官方文档,在查看 TLS ...

  10. (三)Kubernetes 快速入门

    Kubernetes的核心对象 API Server提供了RESTful风格的编程接口,其管理的资源是Kubernetes API中的端点,用于存储某种API对象的集合,例如,内置Pod资源是包含了所 ...

随机推荐

  1. 【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I

    [LGR-148-Div.3]洛谷基础赛 #1 & MGOI Round I T1 luoguP9502 『MGOI』Simple Round I | A. 魔法数字 \(100pts\) 水 ...

  2. NC14402 求最大值

    题目链接 题目 题目描述 给出一个序列,你的任务是求每次操作之后序列中 (a[j]-a[i])/(j-i)[1<=i<j<=n]的最大值. 操作次数有Q次,每次操作需要将位子p处的数 ...

  3. MYSQL TIMESTAMP自动更新问题

    某张表格里有2个TIMESTAMP类型,time1.time2;建表时time1默认NOT NULL ,time2默认NULL; 之后出现了问题:当只修改time2字段,不操作time1时:time1 ...

  4. 苹果AppleMacOs最新Sonoma系统本地训练和推理GPT-SoVITS模型实践

    GPT-SoVITS是少有的可以在MacOs系统下训练和推理的TTS项目,虽然在效率上没有办法和N卡设备相提并论,但终归是开发者在MacOs系统构建基于M系列芯片AI生态的第一步. 环境搭建 首先要确 ...

  5. SpringBoot事务注解@Transactional 事物回滚、手动回滚事物

    处理springboot 下提交事务异常,数据库没有回滚的问题. spring的文档中说道,spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作. 什么 ...

  6. 进度条模块之tqdm

    导入模块 from tqdm import tqdm import time ''' desc 描述 ncols 进度条总长度 可修改 range(1000) 封装迭代器 ''' for i in t ...

  7. 死锁,互斥锁,递归锁,线程事件Event,线程队列Queue,进程池和线程池,回调函数,协程的使用,协程的例子---day33

    1.死锁,互斥锁,递归锁 # ### 死锁 互斥锁 递归锁 from threading import Lock,Thread,RLock #递归锁 import time noddle_lock = ...

  8. 机器学习策略篇:详解单一数字评估指标(Single number evaluation metric)

    单一数字评估指标 无论是调整超参数,或者是尝试不同的学习算法,或者在搭建机器学习系统时尝试不同手段,会发现,如果有一个单实数评估指标,进展会快得多,它可以快速告诉,新尝试的手段比之前的手段好还是差.所 ...

  9. 基于java的学生信息管理系统

    开发说明:使用数组集合存储临时数据,实现学生信息管理系统,实现的功能有管理员的注册.登陆.增加学生信息.删除学生信息.查询学生信息.修改学生信息.学生信息列表 登陆注册界面 系统首页界面 增加 删除 ...

  10. macOS搭建SonarQube

    目录 前言 准备环境 下载安装包 解压路径:/usr/local 创建数据库 修改配置文件 配置环境变量 启动SonarQube 扫描项目 项目报告介绍 总结 前言 初到新公司,接手8-10个java ...