以下是 CA 安全性的概述,分为两个部分:
控制面:实现了一个 CA 负责为网格中的各个服务签发证书,并将证书颁发给各个服务,具体的做法有两个:
- 通过(webhook)动态准入控制器的方式,将 CA 的证书挂载到 Pod 里面去,同时添加了环境变量,只需要读取环境变量就可以获取路径了。
- Dubbo 应用通过与 CA 建立双向 TLS 连接(CA 证书已经被挂载到了 Pod 中,所以可以验证 CA 证书),发送 CSR 请求申请这个 dubbo 应用的证书,dubbo-cp 会验证客户端的 CSR 请求并签发证书返回给客户端。
数据面:在网格中服务相互之前发起通信的时候,dubbo sdk 会拦截服务请求,采用证书进行双向 TLS 认证并建立一个 TLS 连接,使用该 TLS 连接来在网格中传输数据。
在 dubbo-cp 中,要实现一个 CA 要做两方面的事情:
- 维护 CA:维护 CA 的证书状态,存储 CA 证书。
- 签发证书:接受 CSR 请求,为 Dubbo 应用签发证书。
维护 CA
dubbo-cp 中的 CA 中心结构包含两个关键字段:
- authorityCert:相当于 CA 认证证书,CA 服务器证书、客户端的证书都是这个证书签发的。
- serverCerts:CA 服务器的证书,在客户端与控制面的连接中,dubbo-cp 使用的证书就是这个证书,用于响应 CSR 请求(以及其他如 snp,dds 等接口),客户端可能使用ip地址、localhost、域名等方式访问控制面,不同名称的访问返回不同的服务器证书。
以下是 dubbo-cp 初始化 gRPC 服务器的函数:
1 | func NewGrpcServer(s *provider.CertStorage, config *dubbo_cp.Config) GrpcServer { |
刷新 CA 服务器证书
dubbo-cp 会定期的检查 CA 服务器证书是否失效,并刷新 CA 服务器证书:
1 | func (s *CertStorage) RefreshServerCert(stop <-chan struct{}) { |
刷新 CA 认证证书
在 CA 启动时,除了刷新 CA 服务器证书,还需要刷新 CA 认证证书。
因为 dubbo-cp 可能启动多个实例,所以对于 CA 认证证书的刷新只能有一个实例进行(通过 Kubernetes 的选举功能实现只在一个实例上进行)。主要需要做的是:
- 更新 CA 认证证书。
- 更新 Webhook 动态准入控制器的证书。
- 更新 CA 证书在 ConfigMap 上的公钥信息。
1 | func (s *CertStorage) Start(stop <-chan struct{}) error { |
签发证书
客户端发起 CSR 请求,CA 为客户端签发证书的接口定义如下:
1 | message IdentityRequest { |
接口实现
接口实现如下,在验证之后,会返回为客户端签发的证书。
1 | func (s *AuthorityService) CreateIdentity( |