通常有必要在你的构建或部署过程中注入秘密,以便部署的服务能够与其他服务进行交互。如果你只部署到一个环境,这可能是直接的。但是,当部署到多个环境时,你可能需要动态地注入不同的秘密,这取决于你所部署的环境。
假设你有一个虚拟机(VM),是你应用程序的一部分。该虚拟机需要一个嵌入到配置文件中的秘密API令牌来与第三方服务进行通信。为了保持你的生产和非生产环境的隔离,你为你的生产服务器创建了一个 "prod "API令牌,为你的非生产服务器创建了一个 "dev "API令牌。现在,你不想把这些令牌硬编码到一个配置文件中,并把它检查到你的版本控制系统(VCS)中,原因有二。首先,因为将秘密检查到源代码控制中是很差的安全做法,其次,因为你不想维护这个配置文件的独立 "prod "和 "dev "版本。一个更好的解决方案是用正确的令牌即时生成配置文件,并将其注入CI/CD管道工作中。但这又带来了几个新的挑战。
- 如何安全地存储和访问密文
- 如何动态地呈现配置模板
- 渲染后如何注入模板
我们将在本篇文章的下一节中讨论这些挑战的一些解决方案。
安全地存储和访问秘密
这里的挑战是双重的。首先,你如何安全地存储你的秘密?第二,你如何让你的CI/CD管道中的流程能够访问它们,从而呈现模板?
用CircleCI上下文管理秘密
CircleCI有一个内置的秘密存储,可以通过我们的上下文功能访问。在上下文中记录的秘密有以下属性。
- 它们存储在Hashicorp Vault,使用AES256-GCM96加密,并且不能被CircleCI员工访问(链接)。
- 它们可以使用CircleCI CLI自动旋转。
- 它们的密钥和值在创建后不能被修改。
- 它们的值不能在CircleCI管道工作之外透露。
**提示:**如果你的秘密将只在CircleCI内使用,使用CircleCI的上下文。
在CircleCI流水线作业的配置中,你可以指定一个或多个上下文来加载。然后,这些上下文中的秘密将作为环境变量在该作业期间可用。然后,你可以让你的模板渲染引擎将这些环境变量的数据插入你的配置文件模板,以渲染适合目标部署环境的配置文件。
使用第三方秘密存储
另一个选择是使用第三方秘密存储,如SecretHub、AWS Secrets Manager或Hashicorp Vault。这些是更灵活的,因为他们的秘密可以用于CircleCI以外的服务。然而,为了在CircleCI中使用他们的秘密,你将需要编写你自己的方法来提取这些秘密,并使它们对你的模板渲染引擎可用。你可能会利用CircleCI的合作伙伴和社区球体来帮助整合其中的一些工具。
动态地渲染配置模板
你对模板渲染引擎的选择将取决于几个因素,包括。
- 你正在使用的构建和/或部署的工具
- 你的应用程序中使用的语言
- 你的团队最喜欢使用的模板语言
**提示。**对于需要被多个工具访问的秘密,可以考虑使用第三方的秘密存储。预算时间来编写逻辑,使秘密对你的模板渲染引擎可用。
如果你使用Terraform,你可以使用其字符串模板语法。如果你使用Python或Ansible,你可以使用Mako或Jinja模板。在这两个例子中,你可以通过使用CircleCI预建的图像,并预装Terraform、Ansible或Python来节省一些时间,用于包括模板渲染的工作。你也可以检查任何相关的轨道,如Jinja轨道。
一旦你在VCS中检查了你的配置文件模板,并在你的管道部署工作中添加了步骤,以使用你选择的模板渲染引擎渲染模板,你只需确保你将注入模板的秘密可供模板渲染引擎使用。正如上一节所提到的,CircleCI上下文使这个问题变得简单。如果你使用的是第三方的秘密存储,你需要做一些脚本来安全地检索秘密,并将它们传递给模板渲染引擎。
**提示。**使用方便的图像和球体来减少设置模板渲染环境所需的努力。
将渲染好的模板注入到管道中
所以你已经在你的管道中渲染了你的模板,现在你需要把它们注入你的管道作业中。这一部分可能听起来很简单:只需渲染模板并将其插入到你的构建工件中,或将其推送到部署期间创建的基础设施中即可
然而,在使用渲染后的模板的同一作业中渲染模板并不总是实用的。想象一下,你正在渲染Jinja模板的配置文件,你想注入到Docker镜像构建中。渲染Jinja模板的最方便的CircleCI执行器是一个运行CircleCI的Python便利镜像的Docker容器。构建Docker镜像的最有效的执行器可能是一个机器执行器(换句话说,一个虚拟机)。每个工作都在一个干净的容器或虚拟机中运行,所以在Docker容器中渲染的模板将不能被运行Docker构建的机器执行器使用。你可以把这两个任务合并成一个流水线作业,在两个执行器中的一个上运行,但这将使你的流水线更慢、更复杂。
**提示。**缓存渲染的模板,以便在管道的其他工作中使用。
幸运的是,CircleCI允许你在工作区的作业之间缓存依赖关系。你可以渲染你的模板,把它们缓存在一个工作区,然后把这个工作区附加到任何需要使用这些模板的后续作业中。这使你能够为每个作业使用最有效的执行器(就配置工作和计算时间而言)。
动态渲染配置模板解决了安全存储秘密的问题,同时使CI/CD管道中的进程能够访问这些秘密。在这篇文章中,我已经介绍了如何使用CircleCI上下文或第三方秘密存储来安全地存储和访问秘密。我还介绍了选择一个模板渲染引擎,以及如何使用该引擎将秘密注入配置模板。使用动态渲染模板的秘密管理的最佳实践将有助于保持你的CI/CD管道成功和安全地运行。