写点什么

一文详解 kube-apiserver 认证鉴权能力

  • 2023-12-27
    广东
  • 本文字数:2151 字

    阅读完需:约 7 分钟

一文详解kube-apiserver认证鉴权能力

本文分享自华为云社区《kube-apiserver认证鉴权能力》,作者: 可以交个朋友。

HTTPS 为什么要进行身份验证


首先不管是 kubectl 还是 API 调用都是通过 HTTPS 访问 kube-apiserver,有图有真相



所以要想了解 kube-apiserver 认证鉴权,得先从 HTTPS 说起;接下来我们直接通过 API 接口访问 apiserver



为什么不能访问?准确来说是为什么不能建立 HTTPS 连接


原因就是客户端无法验证服务端证书,导致 HTTPS 连接建立失败。可不可以不验证服务端证书?可以



但在公网环境不建议这么做,如果不验证服务端,你可能访问的并不是你想访问的服务端


证书如何保证服务端不被伪造


如何保证客户端收到的服务端公钥没有被伪造?答案就是第三方权威机构 CA


证书申请流程:服务端需要将自己的信息和公钥发给 CA,CA 根据服务端发送过来的内容进行 HASH,然后用 CA 私钥加密得到签名,将签名和 CSR 文件同时写入一个文件即为证书,而访问端通过 CA 根证书(包含 CA 公钥)解密服务端证书中的签名可以确认服务端身份,身份确认后就可以从服务端证书中 CSR 文件内拿到服务端的公钥


为什么要先 HASH 一下?因为不管 CSR 文件多大,经过 HASH 之后长度固定,加/解密速度更快



防伪关键点就是 CA 的私钥只有 CA 机构有,你无法修改证书里面的签名;你也无法用自己的 CA 私钥伪造签名,因为访问端没有你的 CA 公钥无法解密;


只要签名无法修改,csr 文件的内容修改就毫无意义。


现在我们再访问一次 apiserver,这次我们带上 K8S 集群 CA 证书试试



有 HTTP 状态码返回就说明 HTTPS 连接已建立;完整的 HTTPS 认证过程如下



想想为什么 curl 访问https://www.baidu.com不需要指定 CA 证书?

kubernetes 认证方式


上文我们只是验证了服务端,服务端并没有验证客户端,所以我们收到了 401 的返回码。类似于我虽然接了你的电话,但我首先肯定是想知道你是谁。


apiserver 支持三种认证客户端的方式:


  • HTTPS 证书认证:此方式最严格,基于 CA 根证书签名的双向数字证书认证方式。比如 kube-controller-manager、kubelet 等

  • HTTP Token 认证:通过一个 Token 来识别合法用户。比如 serviceaccount

  • HTTP Base 认证:通过用户名+密码的方式认证。由于不常用本文不做介绍

Token 认证


我们创建一个 serviceaccount;1.24 版本以上创建 serviceaccount 不再自动创建 secret。


kubectl create sa test
复制代码


找到以 serviceaccount 名称开头的 secret,拿到其中 token 字段的值



我们带上 token 再次访问 apiserver,看看效果



返回了 403 状态码,显示 Forbidden;说明我们过了认证,只是没有权限而已

证书认证


使用 openssl 生成客户端私钥和 csr 文件;其中/CN 字段就是你的用户名;csr 文件需要公钥,但命令行却指定的是私钥,是因为 oenssl 会自动用私钥生产公钥


openssl genrsa -out myuser.key 2048  openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"
复制代码


创建 CertificateSigningRequest 资源,回忆下上文提到的证书申请过程,我们需要提供什么?


cat <<EOF | kubectl apply -f - apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata:   name: myuser spec:   request: $(cat myuser.csr | base64 | tr -d "\n")   signerName: kubernetes.io/kube-apiserver-client   expirationSeconds: 86400  # one day   usages:   - client auth EOF
复制代码


手动批准证书请求,证书会被保存到 csr 资源的 status.certificate 字段,将证书 base64 解码并写入文件


kubectl certificate approve myuser kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt
复制代码


可以用 openssl 查看证书内容,查看签名字段需要借助其他工具,比如:asn1editor



使用客户端私钥和证书再次访问 apiserver



和 token 访问结果一致,认证通过但未赋权

鉴权机制


上文我们访问 apiserver 得到了 403 的返回码,说明我们权限不够,无法获取 namespaces 资源;为了集群便于管理,我们必须为不同用户设置不同权限。


在 K8S 集群中完成鉴权机制的是 RBAC,RBAC 授权规则是通过四种资源来进行配置:


  • Role:角色,其实是定义一组对 Kubernetes 资源(命名空间级别)的访问规则

  • ClusterRole:集群角色,其实是定义一组对 Kubernetes 资源(集群级别,包含全部命名空间)的访问规则

  • RoleBinding:角色绑定,定义了用户和角色的关系

  • ClusterRoleBinding:集群角色绑定,定义了用户和集群角色的关系


有了角色和角色绑定,还缺一个对象,你希望将角色绑定到那个对象上?


在 k8s 集群中这个对象称为 subject 主体,主体可以是用户、组或者 serviceaccount;


k8s 集群中不存在用户资源,你也无法通过命令查到;Kubernetes 使用证书中’subject’的通用名称(Common Name)字段 (例如:"/CN=bob")来确定用户名


接下来我们对上文创建的 serviaccount 和用户 myuser 赋权


创建集群角色和集群角色绑定


#创建一个集群角色,仅对namespaces资源有get、list和watch权限kubectl create clusterrole myclusterrole --resource=namespaces --verb=get,list,watch#将serviceaccount和myuser用户与该集群角色绑定,test和myuser便有了该集群角色的权限kubectl create clusterrolebinding testuser --clusterrole=myclusterrole --user=myuser  kubectl create clusterrolebinding testsa --clusterrole=myclusterrole --serviceaccount=default:test
复制代码


再次使用 token 或者证书访问 apiserver


使用证书访问



使用 token 访问



点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
一文详解kube-apiserver认证鉴权能力_云原生_华为云开发者联盟_InfoQ写作社区