安全地签署软件

Travis CI 使软件开发人员能够在 构建作业 的一部分中使用 cosign 工具和密钥安全地签署软件工件。

CosignSigstore 项目 的一部分,有助于确保安全软件供应链所需的工具。

您将能够签署容器镜像或作为软件发布的一部分的任何其他工件(blob)。安全地签署您的软件确认其来源,并且是安全软件供应链中的推荐做法。

先决条件 #

在开始之前,请确保您拥有

  • 在 Travis CI 构建作业中可用的密钥。
  • 在 Linux 构建环境中预安装 Cosign(由 Travis CI 维护)。

选项 1:直接将密钥上传到 Travis CI #

帐户持有者或组织管理员可以生成无密码的私有 PEM 密钥并将其上传到 Travis CI。将密钥上传到 个人帐户 或组织帐户(例如:https://app.travis-ci.com/organizations/[org_name]/preferences)。密钥名称只能包含字母数字字符和下划线字符(_)。请务必记下密钥的名称。密钥名称在个人帐户或组织的范围内必须唯一。

提供的密钥将可用于在此帐户(个人或组织)下运行的所有构建。请注意各个存储库设置,尤其是 安全设置 -> 与分支共享 SSH 密钥 设置。如果启用,当派生存储库向原始(基础存储库)提交拉取请求时,签名密钥也可能可用。

选项 2:来自密钥管理系统的密钥 #

您还可以通过配置 Travis CI 中的 Hashicorp Vault 访问 并从中获取签名密钥来获取签名密钥。

用法 #

您将使用名为 cosign 的开源工具来安全地签署软件。CosignSigstore 项目的一部分,该工具有一个很好的 文档站点。在使用该工具之前,请熟悉其工作原理。

请注意:为了保护私有存储库免受意外泄露(例如,通过 Rekor 注册表或任何其他公共注册表),我们不允许在为私有存储库运行的构建作业中使用 cosign 进行 无密钥(使用临时密钥)签名。如果您尝试这样做,错误消息会指出实验性功能不允许用于私有存储库。

使用存储在 Travis CI 中的密钥 #

配置密钥后,您可以修改您的 .travis.yml 以在构建作业之一中包含一个安全签名代码步骤。以下示例说明了一个签名示例容器镜像,它可以是您的发布镜像。

keys:
  - SSH_KEY_FOR_SIGNING # must match the key identifier set in the UI

env:
  secret: “...” # encrypted COSIGN_PASSWORD=...  string; see cosign doc

before_script:
  - travis_key SSH_KEY_FOR_SIGNING cosign.key  # cosign requires the key to be in a file

script:
  - cosign sign --key cosign.key [whatever_the_image_identifier_is]

请注意,如果您想在构建作业(或整个构建,具体取决于您在 .travis.yml 中如何构建构建定义)中使用密钥,则需要新的 keys 标签和至少一个上传的密钥标识符。如果未提供密钥标识符或与任何上传的密钥不匹配,则在构建作业或构建运行时将不会提供任何密钥。

使用存储在 Hashicorp Vault 中并获取到 Travis CI 构建作业的密钥 #

Cosign 依赖于以下标准 Hashicorp Vault 环境变量在构建作业环境中设置

  • VAULT_ADDR
  • VAULT_TOKEN
  • TRANSIT_SECRET_ENGINE_PATH(可选)

默认假设是您的 Hashicorp Vault 已启用传输引擎。这是 Vault 的配置,用户负责。

要使用存储在外部 Hashicorp Vault 密钥管理服务 (KMS) 中的密钥执行安全签名,请从以下示例开始,填写所需的连接详细信息

vault:
  api_url: [single value endpoint address:port] #mandatory
  token:
    secure: “...” #mandatory
    # This will make the default VAULT_ADDR and VAULT_TOKEN available for cosign.

script:
  - cosign sign --key hashivault://some-key-identifier [whatever_the_image_identifier_is]

如有疑问,请查阅 Cosign KMS 支持文档页面

安全注意事项 #

尽管该功能旨在帮助您通过签名证明文件或镜像的来源,但在 CI/CD 过程中始终考虑以下确保用于签署文件或镜像的密钥安全性的方面。

用于签名的密钥上传到个人帐户或组织帐户下的 Travis CI 可以用于此实体拥有的每个存储库(假设相应的存储库 .travis.yml 中存在正确的标签和密钥标识符)。从 Hashicorp Vault 下载到特定构建作业或构建的密钥可以在特定构建作业或构建的每个构建作业中使用,分别。

因此,请仔细查看 Travis CI 中属于该帐户的存储库的存储库设置,并评估用于签名的密钥被泄露的风险,例如,通过来自派生存储库的恶意拉取请求或意外的调试消息。我们建议您注意存储库是否为公共存储库(默认情况下使作业日志公开),是否允许来自派生存储库的拉取请求,是否共享存储库 SSH 密钥以及谁可以访问作业日志。请注意,作业日志,尤其是公共日志,可用于通过拉取请求或在 Travis CI 中触发构建的提交中的恶意或意外调试消息泄露秘密。

我们建议您考虑以下安全措施

  • 仅为文件/镜像签名目的使用单独的密钥
  • 如果可能,使用私有存储库触发构建,在此期间签署文件
  • 查看谁有权访问此类存储库的推送/写入权限
  • 查看存储库设置,尤其是 安全设置 -> 与分支共享 SSH 密钥 设置
  • 将签署发布的构建排除到具有有限协作者列表的单独帐户/组织(如果可能且可行)
  • 在各个存储库设置中 限制对存储库作业日志的访问
  • 如果使用 Hashicorp Vault KMS 作为用于签名的密钥的来源:始终加密在相应的存储库设置或 .travis.yml 文件中连接到 Vault 所需的秘密

Travis CI 将尝试在作业日志中模糊处理秘密,但由于有很多方法可以在输出中打印它们,因此无法保证所有易受攻击的数据都会被发现和屏蔽。由于 Travis 是一个云 CI/CD 系统,请注意相关的风险以及最大程度地减少这些风险的方法。另请阅读 保护数据安全最佳实践