Let's Encrypt 运营 CT 日志的实践方式
[本文为客座文章,最初于2019年11月20日发布于 Let’s Encrypt 官方博客。] Let’s Encrypt 推出了一款证书透明度(CT)日志于今年春季推出了该日志。我们希望分享搭建该日志的经验,供其他相关方参考借鉴。。。Sectigo和Amazon Web Services为我们提供了大力支持,承担了 CT 日志运营的大部分成本。
[注:本文最初于2019年11月20日发布在Let's Encrypt 博客上。经 Let's Encrypt 许可,Sectigo 现将这篇实用内容分享给读者。]
Let’s Encrypt 推出了一款证书透明度(CT)日志于今年春季推出了该日志。我们希望分享搭建该日志的经验,供其他相关方参考借鉴。证书透明度(CT)已快速成为互联网安全基础设施的重要组成部分,但运营一套高质量的日志服务并非易事。CT 社区越充分分享已有的实践经验,整个生态系统就会越完善。
Sectigo以及Amazon Web Services为我们提供了大力支持,承担了 CT 日志运营的大部分成本。Sectigo 首席信息官 Ed Giaquinto 表示:“Sectigo 很荣幸能够赞助 Let’s Encrypt CT 日志。我们相信这项举措将为 CT 生态系统提供亟需的支撑。”
如需了解 CT 及其工作原理的更多背景信息,建议阅读《证书透明度工作原理.”
如果您对本文所述内容有任何疑问,欢迎在我们的社区论坛.
目标
- 扩展能力:Let’s Encrypt 的证书签发量超过 每日100万张证书,且该数字每月都在增长。我们希望日志既能收录我们的证书,也能收录其他证书颁发机构(CA)的证书,因此我们需要具备每日处理200万张甚至更多证书的能力。为了支撑这一持续增长的证书规模,证书透明度(CT)软件与基础设施需要按照可扩展要求进行架构设计。
- 稳定性与合规性: 我们的目标是达到99%的正常运行时间,单次中断时长不超过24小时,符合Chromium与AppleCT政策要求。
- 分片: CT日志的最佳实践是将其拆分为多个时间分片。有关时间分片的更多信息,请查看这些博客 文章.
- 低维护成本: 人力成本较高,我们希望尽可能减少基础设施维护所耗费的时间。
系统架构
预发布环境日志与生产环境日志
我们运营两套对等的日志,分别用于预发布环境和生产环境。所有计划应用到生产日志的变更,都会先部署到预发布日志。这是确保更新和升级在部署到生产环境前不会引发问题的关键环节。你可以在我们的文档.
中找到这些日志的访问详情。我们会让预发布日志持续承受生产级别的负载,确保所有与规模相关的问题首先在预发布环境中暴露。我们还使用预发布CT日志提交来自我们预发布CA环境的证书,并向其他CA的预发布环境开放该日志供其使用。
需要说明的是,我们认为一套日志由多个时间分片组成。尽管每个分片在技术层面是独立的日志,但从概念上将这些分片归属到同一条日志下更便于理解。
Amazon Web Services (AWS)
我们选择在AWS上运行CT日志主要出于两点原因。
其一的考量是云服务提供商多样性。由于证书生态系统中受信任的日志数量相对较少,我们不希望因单一云服务提供商故障导致多条日志同时下线。在我们做出该决策时,已有运行在Google、Digital Ocean基础设施上的日志,以及自托管日志,我们当时没有发现运行在AWS上的日志(事后看来我们可能遗漏了Digicert已开始使用AWS部署日志的情况)。如果你计划搭建供CA使用的受信任日志,请将云服务提供商多样性纳入考量。
此外,AWS提供了成熟完善的功能集,我们的团队也有在其他场景下使用AWS的经验。我们完全相信AWS能够胜任这一任务。
Terraform
Let’s Encrypt在多个云项目中使用HashicorpTerraform。我们通过复用已有的Terraform代码快速完成了CT日志基础设施的搭建。我们的CT部署包含约50个组件,涵盖EC2、RDS、EKS、IAM、安全组以及路由组件。集中管理这些代码让我们的小型团队能够在全球任意亚马逊区域复现CT基础设施,避免配置漂移,并且可以便捷地测试基础设施变更。
数据库
我们选择使用MariaDB作为CT日志数据库,因为我们在运营证书颁发机构(CA)方面拥有丰富的MariaDB使用经验。在我们成长为最大的公开受信任证书颁发机构(CA)的过程中,MariaDB展现出了良好的扩展能力。
我们选择由Amazon RDS托管MariaDB实例,因为RDS支持向备用集群成员进行同步写入。这一特性可实现数据库自动故障切换,保障数据库一致性。对于CT日志而言,向数据库副本执行同步写入至关重要。若故障切换期间漏写一条记录,就可能导致某张证书未按承诺写入日志,进而可能导致日志被取消资格。由RDS负责管理该机制可降低运维复杂度、节省人员时间。数据库性能管理、调优与监控仍由我们自行负责。
必须仔细测算CT日志数据库所需的存储容量,这一点十分重要。存储容量不足会导致需要开展耗时且存在潜在风险的存储迁移;存储容量过高则会产生不必要的高额成本。
粗略估算的存储基准为每1亿条记录占用1TB空间。我们预计每个年度时间分片需存储10亿张证书和预证书,对应需要10TB存储空间。我们曾考虑为每个年度时间分片配置独立的数据库存储,为每个分片分配约10TB空间,但该方案成本过高。最终我们决定为每个日志创建12TB的存储块(10TB基础容量加上一定预留空间),该存储块由RDS实现冗余副本。我们计划每年冻结上一年度的分片,将其迁移到成本更低的服务基础设施上,从而回收其占用的存储资源供在线分片使用。
每个CT日志的RDS我们使用2台db.r5.4xlarge实例,每台实例配置8个CPU核心、128GB内存。
Kubernetes
在尝试了多种应用实例管理方案后,我们选择使用Kubernetes。Kubernetes的学习曲线较为陡峭,我们是经过慎重考量才做出该决定的。这是我们首个使用Kubernetes的项目,选择该方案的部分原因是积累相关经验,未来可能将相关技术应用到我们基础设施的其他部分。
Kubernetes为运维人员提供了部署, 扩缩容、服务发现等抽象能力,无需我们自行构建相关功能。我们参考了Trillian代码仓库中的Kubernetes部署示例清单来辅助部署工作。
Kubernetes集群由两大核心组件构成:负责处理Kubernetes API的控制平面,以及运行容器化应用的工作节点。我们选择由Amazon EKS托管我们的Kubernetes控制平面。
每个CT日志的工作节点池我们使用4台c5.2xlarge EC2实例,每台实例配置8个CPU核心、16GB内存。
应用软件
我们在Kubernetes集群中运行三类核心CT组件。
证书透明度前端(即CTFE)提供RFC 6962端点,并将请求转换为发送给Trillian后端的gRPC API请求。
Trillian将自身描述为“透明、高可扩展且可加密验证的数据存储”。本质上,Trillian通过默克尔树实现了通用的可验证数据存储,可通过CTFE作为CT日志的后端。Trillian包含两个组件:日志签名器(log signer)和日志服务器(log server)。日志签名器的作用负责定期处理传入的叶子数据(在CT场景下即证书),并将这些数据整合到默克尔树中。日志服务器则从默克尔树中检索对象,以响应CT API的监控请求。
负载均衡
流量通过映射到Kubernetes Nginx Ingress服务的Amazon ELB进入CT日志。Ingress服务在多个Nginx Pod之间进行流量负载均衡,Nginx Pod再将流量代理到CTFE服务,由CTFE服务将流量均衡分发至各CTFE Pod。
我们在此 Nginx 层部署了基于 IP 和用户代理的速率限制机制。
日志记录与监控
Trillian 和 CTFE 会暴露Prometheus 指标,我们将这些指标转换为监控看板和告警。必须为 CT 日志端点设置高于 CT 策略规定的 99% 正常运行时间要求的服务等级目标,才能确保您的日志受信任。以 DaemonSet 方式运行的 FluentD Pod 会将日志传输至集中式存储,供进一步分析。
我们开发了一款名为ct-woodpecker的免费开源工具,用于监控日志稳定性与正确性的各个维度。该工具是我们保障服务等级目标达成的重要组成部分。每个 ct-woodpecker 实例均在承载 CT 日志的 Amazon VPC 外部运行。
未来效率优化方向
以下是我们未来可能用于提升系统效率的部分方向:
- Trillian 会存储每条证书链的副本,其中包含大量相同中间证书的重复副本。若能在 Trillian 中实现此类重复数据的去重,将可大幅降低存储成本。我们计划研究该方案的可行性与合理性。
- 验证是否可采用成本低于 IO1 块存储与预置 IOPS 的存储形式。
- 验证是否可缩小 Kubernetes 工作节点所使用的 EC2 实例规格,或减少 EC2 实例的使用数量。
