认证的密码学原理
认证
什么是认证呢?
譬如说你的学位证,就是一种认证。网站上用的https,也是一种认证。
网络安全
网络安全主要就是在某些假设成立的条件下,我们如何进行防范的问题。
比如,有一个非常重要的假设:
两个服务 A, B 通讯,中间的网络是不安全的。既然中间网络是不安全的,那我们肯定不能直接把信息在 A 和 B 之间传输。
业内是如何应对这个问题的呢?
对称加密
对称加密,就是数据发送发和接手方使用一个相同的加密秘钥,对数据进行加密和解密。
由于使用同一个秘钥,那么数据接收方如何知道发送方的加密秘钥呢?在中间传输网络不安全的前提下,我们是无法安全地将秘钥发送给接收方的。
非对称加密
数据发送方使用的加密秘钥和接收方使用的解密秘钥,不是同一个秘钥。
Service B 先公开声明一个公钥,所有的服务都可以获取公钥,Service A 使用公钥加密数据,发送给 Service B,然后 B 通过自己的私钥解密数据。这就是非对称加密的实现方式。
当完全使用非对称加密也会有问题,我们考虑如下的加密方案:
- 方案 1
仅使用非对称加密,ServiceB公开声明公钥,ServiceA使用公钥加密数据,发送给 ServiceB,然后ServiceB通过自己的私钥解密数据。
但这里有个问题,非对称加密使用的算法非常消耗计算资源,如果每次通讯都使用非对称加密,性能损耗是无法接受的。
- 方案 2
第一次通讯,Service A 使用公钥加密一个秘钥数据,发送给ServiceB, ServiceB 使用自己的私钥,解密出秘钥数据。
然后这个解密出来的秘钥,用来进行对称加密通讯。
然后ServiceA 和 ServiceB 使用这个秘钥,通过对称加密进行通讯。
上面的方案2,就是大名鼎鼎的 SSL/TLS 协议
但这个方案也有一个潜在的风险:
黑客一开始截获 ServiceB 发往 ServiceA的公钥,然后使用一个篡改的公钥发给 ServiceA,这样ServiceA 使用该公钥加密秘钥,这个秘钥就被黑客截获并解密。
那么针对这个问题风险,是如何解决的呢?
- 方案 3
使用 CA ,证书认证机构,所有合法的网站的证书,都保存在 CA。 当 Service A 拿到公钥之后,先去问 CA,这个公钥是否是合法的。在确认公钥合法之后,再用来加密秘钥发送。
这个就是 https 的实现机制,所有的 https 网站相当于ServiceB, 公开声明一个公钥,而且这个公钥要注册到证书认证机构。我们的浏览器,相当于 ServiceA,在访问网站时,先拿到这个公钥,去查询证书认证机构 CA,如果是合法的公钥,那么就会进行正常的加密数据传输,如果不是合法的公钥,浏览器就会报一个网站不安全的提示。
K8s 的认证和授权
认证
k8s 有下面几种认证方式
- 客户端证书认证 (TLS 双向认证)
k8s 有自己的 CA,kubectl 和 apiServer 互相验证
- BearerToken
相对简单,可以理解为一个非常复杂的密码,预先定义在 ApiServer 中
- ServiceAccount
k8s 内部,运行的pod,要和 apiServer 通讯,使用 这种方式。(namespance, token, ca)通过挂载的方式,挂载到pod中。
授权
- k8s 使用的授权方式:
RBAC (Role Based Access Control)基于角色的访问控制,当前 k8s 采用的方式。
- 用户和角色
角色Role 是定义在 namespace(命名空间) 中的,如果一个用户有了一个角色,那就有了这个命名空间中对应的权限。
用户 User 在 Test 命名空间中拥有一个角色,拥有这个角色对应的命名空间中就权限 Authority。
使用 RoleBinding 资源描述用户所对应的角色
- 跨命名空间的权限
集群的权限,ClusterRole, 通过 ClusterRoleBinding。
k8s 中的用户有两种,一中是普通用户User,另一种叫ServiceAccount。 User 和 ServiceAccount 是平等的关系,都可以有Role 和 ClusterRole。
准入控制
k8s中具体的权限空时,是通过准入控制来实现的,可以理解为独立的过滤插件,也可以理解为Java中的filter.
这里简单介绍其中的几个
- AlwaysAdmit 总是允许
- AlwaysDeny 总是拒绝
- ServiceAccount 不是用户的中的那个ServieAccount, 辅助 sa做自动化
- DenyEscolatingExec 用来限制登录到容器中执行命令