一文详解 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。
找到以 serviceaccount 名称开头的 secret,拿到其中 token 字段的值
我们带上 token 再次访问 apiserver,看看效果
返回了 403 状态码,显示 Forbidden;说明我们过了认证,只是没有权限而已
证书认证
使用 openssl 生成客户端私钥和 csr 文件;其中/CN 字段就是你的用户名;csr 文件需要公钥,但命令行却指定的是私钥,是因为 oenssl 会自动用私钥生产公钥
创建 CertificateSigningRequest 资源,回忆下上文提到的证书申请过程,我们需要提供什么?
手动批准证书请求,证书会被保存到 csr 资源的 status.certificate 字段,将证书 base64 解码并写入文件
可以用 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 赋权
创建集群角色和集群角色绑定
再次使用 token 或者证书访问 apiserver
使用证书访问
使用 token 访问
版权声明: 本文为 InfoQ 作者【华为云开发者联盟】的原创文章。
原文链接:【http://xie.infoq.cn/article/32a904ecda3e7a2829dac29b0】。文章转载请联系作者。
评论