IstioCon2023:Cert-manager帮助增强Istio证书管理的安全性和灵活性
记录在2023年9月26日在上海IstioCon上发表的技术演讲《cert-manager Help Enhance Security and Flexibility of Istio Certificate Management》
议题:
对等身份验证是 Istio 零信任安全模型的基本组成部分。默认情况下,Istio 创建私钥和自签名根证书,使用它们自动签署和颁发 X.509 证书给每个工作负载,并帮助应用程序实现互相 TLS,以实现无需更改代码的安全服务间通信。在生产环境中,强烈建议从 PKI 提供商颁发根 CA,以增强安全性并提供更多的灵活性。在这次演讲中,超盟将分享 cert-manager 的详细实践,它是一个强大且可扩展的 X.509 证书控制器,如何帮助 Istio 构建增强的零信任网络。演讲将说明 cert-manager 如何通过自动从指定的 PKI 提供商获取证书,并在到期前的配置时间内更新证书,以避免任何服务停机,从而简化 Istio 根 CA 的生命周期管理。
Peer authentication is fundamental part of Istio’s zero-trust security model. By default, Istio creates a private key and self-signed root certificate, uses them to automatically sign and issue X.509 certificates to every workload, and help application make mutual TLS to secure service-to-service communication without code changes. In production environment, it is strongly recommended to issue the root CA from a PKI provider to enhance the security and provide more flexibility. In this speech, Chaomeng will share a detailed practice of how cert-manager, a powerful and extensible X.509 certificate controller, help Istio build enhanced zero-trust network. That is how cert-manager simplify Istio root CA lifecycle management by automatically obtaining certificates from a specified PKI provider, and renewing certificates at a configured time before expiry to avoid any service downtime.
正文:
大家好,我是张超盟,来自华为云。今天我分享主题是istio安全的相关内容。 大家使用istio最常见的是非侵入的流量和可观测性能力,如方便的灰度分流策略。实际上,随着使用深入,会感受到istio强大的安全能力。 实际上与其说istio提供了非侵入的认证、授权等安全能力,不如说提供了一个完备的安全模型。我们一般称为零信任安全网络。 在这个安全模型中,证书是非常基础的一块能力。今天的分享中我们将了解istio和一个证书管理服务cert-manager配合提供全面灵活的安全能力。
我是华为云分布式云原生的架构师,从2018年开始也一直在负责华为云应用服务网格的设计开发工作。
演讲的内容包括:
- 必要的背景Istio零信任安全;
- Istio安全中证书碰到的问题
- 和cert-manager给出的解决办法
- 重点是两个实践:cert-manager提供Istio根证书管理和Ingress-gateway证书管理的的实践。
首先如今天的这次演讲的标题,我们的切入点和上下文是零信任安全。零信任安全的内容很多,我们这里仅介绍本次演讲必要的背景内容。
这是零信任安全的一个比较标准的定义。零信任安全模型描述了一种用于 IT 系统策略、设计和实施的方法。
零信任安全模型背后的主要概念是“从不信任,始终验证”。零信任就是不信任,目标在什么都不信任的环境上提供安全,千万别文字上简单理解成没有信任的安全环境。默认情况下,不应信任用户和设备,即使它们连接到许可的网络,即使它们以前已经过验证。通过建立强身份验证、在授予访问权限之前验证设备合规性,以及确保仅对明确授权的资源进行最小特权访问来实现。
可以看到这和传统理解的安全只是使用防火墙IDS这些在入口处防护,零信任模型里,网络内部和外部都不会信任任何人,网络、人、设备、负载都是zero trust。
零信任安全模型的一个典型实现是这样。可以看到涉及四个大框:
- 右上角的Resource表示访问的资源,也是零信任安全保护的对象,所有的数据、计算都认为是Resource,对这些资源的访问都要基于零信任网络的原则进行管理。
- 左上角是资源请求者,或者说客户端。不管这个客户端来自网络外部还是网络内部都是不被信任。
- 中间的策略执行点PEP来决定哪些访问是信任哪些不信任。PEP基于负载的身份标识、认证客户端的身份、并基于请求属性动态判定对目标资源的访问是否信任。注意这里的判定基于一个独立的连接或者会话,对请求进行评估判定,因此可能出现上一次请求是允许的后面的请求不允许,可能来自一个客户端对统一资源的请求,请求中携带的某个属性变化了,请求就不被允许。
- PEP应用的策略都是基于控制面PDP动态生效,就是图下面部分。
以上这个图是不是很容易联想到Istio这张经典的安全的架构图。网格的数据面代理非常适当地扮演了PEP的角色,实现了零信任模型中对PEP的要求。
网格中支持Kubernetes Service account、云平台身份等多种身份标识,并通过证书或编码身份,进行认证;网格数据面代理应用间进行透明的双向认证,同时进行访问通道加密。并且可以自动为网格中的负载签发、续签证书;基于认证的服务身份,结合应用访问内容配置细粒度的授权策略,细粒度地控制资源访问权限,践行零信任安全要求的每会话控制要求和最小访问权限原则;还可以通过访问日志详细记录服务间访问。
并且很重要一点,以上这些能力都是非侵入方式提供,透明地拦截服务间的流量,透明地应用配置的安全策略,应用代码不感知也无需修改,应用部署的下层基础设施无需修改。所以有时我们也说Istio提供了一个零信任的网络基础设施,部署运行在上面的服务负载天然就是满足零信任的要求。
上面图上橘红色圆点标记了Istio安全体现中证书作用的位置。证书是在Istio的零信任安全体系的根基。我们下面展开看下Istio安全体现中证书的几处应用。
前面说过了Istio提供了一套基于负载身份的认证体系。Istio数据面基于负载身份生成负载的证书,并基于负载的证书进行透明的双向认证和通道加密。
主要机制是Istio代理负责维护本Pod内的证书和密钥。Istio代理生成私钥,并基于负载身份,一般是k8s的service account,向Istiod发起证书签名请求CSR(Certificates Signing Request)得到签发的证书和对应的Istio代理上的密钥一起使用。网格代理Envoy上通过SDS获取新的证书,并基于该证书进行身份认证和服务间安全通信。Istio代理负责证书和密钥的定期轮换,当监控到证书过期时重新申请,并向本地Envoy推送新的证书。
虽然负载上证书自动签发和维护,那么签发这些证书的根证书呢?默认情况下Istio提供了一种开箱即用的方式来启用这些安全能力,Istiod会自动创建一个私钥和一个自签名的有效期为10年的证书,存储在cacerts中。Istiod则使用这个根CA为负载签发证书。但在生产环境下这个自签的证书不能满足安全要求,另外每个控制面自签的证书各自负载签发负载证书,也会导致多控制面的场景下,负载间不能互相认证。
另外是网格ingress处的TLS Termination。在Ingress-gateway上配置服务端证书,供源服务,一般是浏览器等客户端认证,并将客户端到网格边界这段TLS的加密流量透明转化为非加密流量向下传递。在Gateway提供客户端认证,避免了入口服务frontend管理证书和与调用方TLS交换的问题。frontend仍然是普通的HTTP协议提供能力,TLS被ingress Gateway卸载或终止掉了。
网格中与Ingress 处的TLS Termination对应的是Egress的TLS Origination。Egress-gateway接收网格内部未加密的流量,根据网格外部服务端的的认证要求进行Simple或双向TLS认证。在Egress-gateway认证网格外部的服务端,避免了出口的微服务自身管理证书和与目标服务TLS交互的问题。backend仍然是普通的HTTP或TCP协议访问外部服务,Egress-gateway代替网格服务发起了TLS请求。
这里列了个表格简单对比了三种模式。
位置看mTLS作用在网格内部,TLS termination和TLS origination分别作用在网格的入口和出口。
mTLS是Istio自动签发证书,自动加载到网格数据面的Sidecar上,Sidecar代替业务透明地完成TLS。TLS termination是客户端程序和Ingress-gateway间进行TLS交换和认证。TLS origination是Egress-gateway和外部目标服务间进行TLS交换和认证。
但有一个共同的特点,都是基于证书的认证,TLS termination和TLS origination是配置的实体证书,需要有证书管理。mTLS虽然负载的证书是由Istio自动签发,但网格的根证书管理还是要解决的问题。包括如何进行证书的管理、续签等。
下面我们总结整理下Istio中证书相关的挑战和需求
首先,避免证书问题引起的服务运行问题,不管是证书过期还是证书配置错误。但是遗憾的是,在实际生产中这却是导致最终业务故障的一类典型问题。另外关于证书最直接的需求是在证书有效期过期前的自动续签。生产中经常是运维人员配置相关告警,在证书快过期前收到告警后,手工去签发和替换证书。如果能有办法在到期前自动续签,可以减少这部分人工负担,并可避免人工操作引入的失误。
可以有一种方式可以灵活方便地配置证书的相关属性,包括有效期、dns域名等。最好是能支持多种证书签发者,包括公有CA和私有CA等。另外一个是最好能和云原生有结合,方便云原生的应用或者平台使用证书。
对于以上问题和需求,当前有一个比较合适的解决方案,那就是cert-manager。
这是摘自cert manager官方的介绍。是一个作用于k8s的强大的可扩展的x509证书控制器。可以从多种包括公有和私有CA的不同的证书签发者获取证书,保证证书满足有效期要求,基于证书配置的时间,在过期前自动续签。
社区描述的能力我们这里就不挨着过了,基于后面的实践会有体会。
这里的cert就是certificate,翻译成中文我们一般指数字证书,简称证书。数字证书的基本概念这里不完全介绍,我们这里一句话补充下:根据非对称密码学的原理,每个证书持有人都有一对公钥和私钥,这两把密钥可以互为加解密。数字证书就是经过CA认证过的公钥,因此数字证书和公钥一样是公开的。
而私钥一般情况都是由证书持有者在自己本地生成或委托受信的第三方生成的,由证书持有者自己负责保管或委托受信的第三方保管。比如前面介绍Istio签发的负载证书,私钥是在stio agent中维护,只是向Istiod请求签发一个证书;而公共或私有的CA机构,创建CA类型的证书时,只有证书本身,不会给你私钥,私钥在机构维护。
这里是cert-manager的架构,体现了架构也体现了机制和流程。cert-manger 关键概念很多,满足基本使用要求,了解两个即可,就是图上下面两层:Issuer表示cert-manager对接的一个证书发行者CA。Issuer接受证书签发请求CSR,向请求方签发证书。Certificate表示一个要签发的x509证书的详细描述,包括哪个颁发者签发,有效期,多长时间自动续签等。。
总体流程是:通过Issuer配置一般对接一个证书机构,通过certificate描述要签发的证书。cert-manager把CSR发给Issuer描述的证书发行者,并将证书发行者签发的证书,存储在Secret中。
cert-manager内置了多个证书发行者,也可以扩展支持其他证书发行者,如各种厂商提供的私有证书PCA,扩展Issuer的定义,并安装Addon来对接PCA。
这里只是概念模型上介绍下其定位和用法,具体用法后面的实践中详细了解。
首先我们介绍cert-manager为Istio服务网格生成根证书,我们会介绍cert-manager通过对接一个CCM的私有CA来签发证书,这个证书作为网格的根CA,为网格的负载签发证书。
这个图是我在前面介绍的Istio根证书机制上添加了基于cert-manager的证书签发机制的完整流程。
1.首先创建 PCA的 CA 层次结构,包括根 CA 和从属 CA,这个步骤我们下页详细介绍
2.第二步,配置将从属 CA 设置为cert-manager的证书发行者
3.cert-manager根据certificate的配置从PCA签发证书,并存储在cacerts这个secret 中。
4.cert-manager管理证书的生命期,根据证书对象的配置在到期前续签证书。
下面就是Istio的固有流程和机制了:
1.Istiod 提供 gRPC 服务来接收证书签名请求 (CSR)
2.Istio 代理创建私钥和 CSR,并将 CSR 发送到 Istiod 进行签名
3.Istiod 根据从cert-manager获取到的根证书签发 CSR 以生成证书
4.Envoy 通过SDS向 Istio 请求证书和密钥
5.Istio 代理监测工作负载证书的到期时间,定期检查证书和密钥轮换
6.工作负载的Sidecar基于负载证书进行透明的双向 TLS (mTLS)
这是PCA和Istio总体的CA层次结构。可以看到分四层,前两层在PCA中定义,后两层在Istio中实现。使用pca的从属ca作为证书发行者,签发证书,作为istio控制面的根证书,再签发负载实体证书。
最下是实体证书,也称为叶子证书或终端证书,安装在终端上。进行实体身份认证,可以是客户端也可以是服务端。如我们前面提到的ingressgw和egressgw上配置的证书。是证书链的最后一层,不能签发其他证书。
最顶层是根证书,是公钥体系的信任根,可以签发下层证书。根ca如果频繁使用,它的密钥泄露风险就增加,一旦泄露,下层所有证书都必须废弃。所以一般不直接用根证书签发最终的实体证书。而是引入中间层,从属ca。
图上中间两层就是从属ca,用于隔离根证书与下层的叶子证书。在证书链验证过程中对下一层证书进行校验。可以向下签发从属ca或叶子证书。当一个从属ca暴露,只用吊销和和替换它这个分支下的证书,不影响根ca和其他从属ca和其他叶子证书。
ca层次从上向下有效期逐层减少。强制要求新签发的证书到期时间不能超过其父证书。根ca使用最少,保护安全等级最高,一般有效期10-30年。从属ca越往下层有效期越短,一般设置2-5年。实体证书使用最频繁,泄露风险最高,一般根据应用场景设置一两年几个月甚至几小时。
这是在华为云CCM上创建的证书。首先创建根CA,然后根据根CA创建一个从属CA。在选择从属CA的有效期时,要求不能超过根CA的有效期。创建时可以填证书的各种属性。
下来,配置cert-manager最重要的两个对象Issuer和Certificate。
其中Issuer是一个扩展实现,包括接连接PCA的插件,和对应的CRD,描述对Issuer的配置。不同类型的Issuer配置会不同。这个CCM的Issuer配置连接上一步CCM的PCA创建的一个从属CA,使用这个从属CA签发证书。
待签发的证书通过certificate对象来描述。几个值得关注的属性:
- isCA,描述这里签发的是一个可以签发证书的证书,即是一个CA。结合前面的架构图,我们理解这里签发的证书要作为网格的root CA,响应数据面的CSR请求,为数据面签发负载的证书。
- Duration,表示证书的有效期,这里是以小时为单位描述,不能超过在PCA上创建的二级从属证书的有效期
- Renewbefoe表示在有效期到期前10天,cert-manager调用自动从PCA续签证书。
- Secret是签发证书的存储位置,存储在cacerts的secret中。
这是Isito中的典型配置,给一个目标服务启用mTLs,通过Peerauthentication配置对目标负载使用严格默认的认证;DestinationRule中定义使用ISTIO_MUTUAL的模式,即Istio提供的透明双向认证。Istio自身配置这里我们不多赘述。
当启用了mTLS后,服务就完全无需关心tls和证书的相关问题,服务端协议HTTP,客户端通过普通HTTP协议访问。通过客户端的访问输出、客户端和服务端代理的访问日志上都可以看到应用本身没有涉及TLS和证书。
代理根据认证策略。自动地为服务提供透明的mTLS,实现服务的双向认证、通道加密。后续配合基于身份的授权策略,管理服务间的访问授权,实现最小访问权限,只有明确的特定身份可以访问某些特征的服务。如具体哪些身份的负载可以访问目标服务的哪些接口,这里的身份就是编码在证书中。
下面是通过cert manager为Istio的Ingress-gateway签发证书,生产中Ingress-gateway的证书过期导致的服务不通的问题时有发生。
总体架构如和流程如下:
1.在cert-manager中创建Issuer
2.在cert-manager中创建证书
3.配置的Issuer签发证书并存在配置的secret中
4.cert-manager会一直检查证书的有效期,在过期前自动续签。
5.Istio gateway的TLS中定义使用上一步生成的secret作为认证的资料
6.Istio的动态把证书推送到Ingress-gateway
7.客户端发起HTTPS请求,携带服务端的CA,Ingress-gateway和客户端TLS握手,并验证服务端证书
8.Ingress-gateway执行TLS终止,并将HTTP流量发送给后端服务
下面重要部分是定义cert-manager的两个重要资源对象。
首先是Issuer:和前一个实践不同,这里的Issuer使用的是cert-manager内置的CA类型的Issuer,即在secret中存储的证书和私钥来签发证书。
其次是证书的定义:最大的不同是,isCA是false,表示签发的不是一个CA而是一个实体证书。只是用于Ingress-gateway直接使用,不可用于签发证书,属于证书链中的最后一层,是Ingress-gateway与调用的客户端进行HTTPS通信的凭证。
另外也配置了证书的有效期、续签时间、生成的证书存储的secret等。
另外配置了dnsName,指定与证书相关联的域名如果客户端的,校验客户端访问的域名与 subjectAltName 扩展中该域名匹配。
这里是配置Ingress-gateway的定义。
协议HTTPS,TLS模式配置为SIMPLE,表示TLS终止时,只需要客户端校验服务端,服务端无需校验客户端,这也是ingress gateway 人机交互的典型配置。
Tls的credentialName配置cert-manager生成的证书的secret。
其他Istio固有的配置这里不过多解析
以下是解析是配置的证书内容,包括cert-manager中certificate资源对象的详细信息,配置的证书有效期是300天;在到期前10天进行证书续签。
可以看到isCA:false,表示这是一个作用于终端的实体证书,不是一个可以再签发其他证书的CA。把envoy congfigdump出来的gateway关联的证书内容解出来,对比可见,与我们在cert-manager中通过certificate资源定义的证书的各项内容一致。包括证书有效期,是否CA、dns名等。
这是一个端到端的测试。在网格外部,通过HTTPS协议访问Ingress-gateway,来访问网格的一个服务。访问链路上的详细流程如下:
1.Gateway 加载cert-manager配置并生成的证书
2.客户端HTTPS访问,并携带服务端CA
3.从访问的输出可以看到:
4.客户端和Ingress-gateway的TLS握手
5.验证服务端证书,包括过期时间,SAN等
6.最终效果是Ingress-gateway卸载了TLS请求,将HTTPS流量转化为HTTP流量发给后端服务。
以上是我们实践的全部内容,实际项目中细节更多,时间关系并没有全部包含在以上分享中。