生成 GPG 密钥
由 IBM Cloud DevSecOps 持续集成工具链构建并记录在清单中的工件必须在部署到生产前进行签名。 持续集成管道使用 Skopeo 作为缺省工具来提供工件签名功能。
创建并存储 DevSecOps 持续集成管道自动或手动使用的 GPG 密钥。
自动生成 GPG 密钥
使用此方法,模板将为您生成 GPG 密钥。 通过完成以下步骤,输入密钥生成的 名称 和 电子邮件:
-
转至 工件签名,然后单击 新建。
人工制品签名 " -
在该窗口中,将使用工具链名称和电子邮件标识来预填充 name 和 email 字段。 更改名称和电子邮件标识以反映您的 GPG 密钥需求。 您还可以通过选择此框将密钥存储在私钥提供程序中。
更改姓名和电子邮件地址 -
生成密钥后,您可以将其复制以供参考。
图 3 工件签名证书
复制的密钥为 base64 格式。 在将钥匙导入 钥匙圈 之前,先 解码 钥匙。echo <encoded_gpg_key> | base64 --decode
手动生成 GPG 密钥
下载并安装 GPG 命令行工具
下载并安装适用于您操作系统的 GPG 命令行工具。 转至 GnuPG 二进制发行版 部分,以下载适用于您的操作系统的工具。
Mac OS X
- 下载并安装 Mac GPG。
- 验证已安装的 GPG 的版本。 从命令行,运行下列命令:
$ gpg --version
gpg (GnuPG) 2.3.1
libgcrypt 1.9.3
Copyright (C) 2021 Free Software Foundation, Inc.
- 对于 2.3.1之前的 GPG 版本,可能无法使用 -- passphrase = '' 选项。 在这种情况下,您可以通过在提示时按 Enter 键来省略以下对话框中的密码。
Windows™
- 下载并安装 GitBash (对于
base64编码是必需的)。 - 验证已安装的 GPG 的版本。 在 Git bash 命令提示符中运行以下命令:
$ gpg --version
gpg (GnuPG) 2.2.27
libgcrypt 1.8.7
Copyright (C) 2021 g10 Code GmbH
生成 GPG 密钥
如果 generate-key 命令打开一个要求口令的对话框,请将口令和字段留空。 这是 skopeo 工具在图像签名方面的一个限制,即该处理流程无法接受使用密码短语保护的私钥。 如果在创建期间提供口令,那么您的管道将无法对证书进行解码,而您的管道将在映像签名步骤中失败。 请注意,这也适用于 GIT 标记签名。
Mac OS X 和 Linux™
从 shell 提示符运行以下命令:
gpg --pinentry-mode loopback --passphrase='' --generate-key
- 请输入您的姓名和电子邮箱地址。
- 输入 O 以启动密钥创建。
- 生成密钥后,选择选项 O。
Windows™
GPG 版本> 1.4
从 Git bash 命令提示符,运行以下命令:
gpg --pinentry-mode loopback --passphrase='' --generate-key
- 请在 “真实姓名”字段中输入您的姓名。
- 在 电子邮件地址中输入您的电子邮件地址。
- 输入 O 以启动密钥创建。
- 生成密钥后,选择选项 O。
GPG 版本 < 1.4 (或前一条命令出现任何故障)
从 Git bash 命令提示符,运行以下命令:
gpg --gen-key
- 类型的密钥: 选择缺省选项 (1) RSA 和 RSA (缺省值)
- keysize: 保留缺省值 (2048)
- 键有效性: 将缺省值保留为 0。 这是因为值键 0 不会到期。
- 确认您的选择: 输入 y。
- 在 实名 字段中输入您的姓名。
- 在 电子邮件地址中输入您的电子邮件地址。
- 输入 O 以启动密钥创建。
- 生成密钥后,选择选项 O。
验证密钥创建
验证是否已创建 GPG 密钥。 在命令提示符下,运行以下命令:
gpg --list-keys
确保列出了您的密钥。 Windows 上的示例输出:
$ gpg --list-keys
/c/Users/FredSmith/.gnupg/pubring.gpg
-------------------------------------
pub 2048R/1BB354B5 2021-06-08
uid Fred Smith <fred@company.com>
sub 2048R/F91C39A6 2021-06-08
导出密钥
此步骤是可选的。 运行此命令以确保可以导出 GPG 密钥。
gpg --export-secret-key <Email Address>
不得直接复制导出的原始密钥。 建议将此步骤生成的密钥安全地存储在您的 Key Protect 实例或 Secrets Manager 实例中。 更多详情请参见下文。
存储密钥
必须通过下列其中一种方式向 CI 管道提供 GPG 密钥:
- 存储在 IBM® Key Protect for IBM Cloud® 中
- 存储在 IBM Cloud® Secrets Manager 中
- 直接存储在 CI 工具链中
请确保以正确的格式复制密钥,以防止由于导入失败而发生 CI 管道签名错误。 在以下命令中使用 pbcopy ( Mac OS X )或 clip (Windows Git bash),将密钥内容复制到剪贴板。
将密钥存储在 Key Protect 中
导出 GPG 密钥并将其复制到剪贴板。
在将 GPG 密钥存储到您的 Key Protect 实例中之前,必须对其进行双重 base64 编码。
OS X
gpg --export-secret-key <Email Address> | base64 | base64 | pbcopy
Windows™
gpg --export-secret-key <Email Address> | base64 -w0 | base64 -w0 | clip
Linux™
gpg --export-secret-key <Email Address> | base64 | base64
-
在 IBM Cloud 控制台中,选择要在其中存储从先前步骤生成的 GPG 密钥的 Key Protect 实例。
-
单击 添加 + 图标以向实例添加新密钥。
-
选择 导入您自己的密钥 选项。
-
选择 选择密钥类型 作为 标准密钥。
-
在 密钥名称 字段中指定相应的名称。 稍后可通过此密钥名称检索存储的 GPG 密钥。
-
复制先前在 密钥材料 字段中导出的密钥。
确保在复制密钥并将其粘贴到 密钥资料 字段中时,密钥末尾没有多余的行。
-
选择 选择密钥环 选项作为缺省值。
-
单击 添加密钥 以将密钥添加到 密钥保护。
将密钥添加到密钥保护中
有关 Key Protect的更多信息,请参阅 Key Protect 文档。
将密钥存储在 Secrets Manager 中
在将 GPG 密钥存储到您的 Secrets Manager 实例中之前,必须对其进行单次 base64 编码。
导出 GPG 密钥并将其复制到剪贴板。
OS X
gpg --export-secret-key <Email Address> | base64 | pbcopy
Windows™
gpg --export-secret-key <Email Address> | base64 -w0 | clip
Linux™
gpg --export-secret-key <Email Address> | base64
-
在 IBM Cloud 控制台中,选择要在其中存储从先前步骤生成的 GPG 密钥的 Secrets Manager 实例。
-
单击 添加 + 图标以向实例添加新密钥。
-
选择 其他密钥类型 选项。
其他秘密类型 " -
选择选项 选择密钥类型的 标准密钥 类型。
-
在 名称 字段中提供相应的名称。 稍后可通过此名称检索存储的 GPG 密钥。
-
选择 私钥值 选项,并在 私钥值 字段中粘贴先前导出的密钥。
确保在复制密钥并将其粘贴到 密钥值 字段中时,密钥末尾没有额外的行。
-
通过单击 添加 图标将密钥添加到 Key Protect 实例。
添加关键字
有关 Secrets Manager 的更多信息,请参阅 Secrets Manager 入门。
导出专用密钥并将其直接存储在 CI 管道中
建议不要使用此方法,应仅用于试验。 使用 Key Protect 或 Secrets Manager 来存储密钥。 有关更多信息,请参阅 配置密钥库
将 GPG 密钥作为安全管道属性存储之前,需要 GPG 密钥的单个 base64 编码。
请将 GPG 密钥安全地存储在 Key Protect 或 Secrets Manager 实例中。
Mac OS X / Linux™
gpg --export-secret-key <Email Address> | base64
Windows™
gpg --export-secret-key <Email Address> | base64 -w0
配置用于签名的注册表凭据
在对容器镜像进行签名时,管道需要凭据来对容器注册表进行身份验证。 DevSecOps 管道支持运行时动态凭据解析,允许您通过多种方式配置凭据,并具备自动回退机制。
凭证解析层次结构
该管道在运行时会根据以下优先级顺序动态解析用户名和 API 密钥凭据。
当使用 gara-destination-registry 和 gara-destination-namespace 配置签名目标覆盖,并且同时提供了 gara-destination-apikey 时,管道会优先使用 gara-destination-apikey 来对目标注册表进行身份验证。 否则,将回退到以下针对目标镜像的凭据解析规则。
API 密钥解析顺序:
- 特定于命名空间的 API 密钥:
signing-token-apikey-{registry}-{namespace}(密钥) - 注册表专用 API 密钥:
signing-token-apikey-{registry}(密钥) - Docker 配置 JSON:
signing-dockerconfigjson(密钥) - ICR 特定的备用方案:
ciso-ibmcloud-api-key(秘密)ibmcloud-api-key(秘密)
用户名解析顺序:
- 命名空间专用用户名:
signing-token-username-{registry}-{namespace}(环境变量) - 注册表专用用户名:
signing-token-username-{registry}(环境变量) - 默认值:
iamapikey(如果未配置用户名)
其中:
{registry}是注册表的主机名(例如:us.icr.io、de.icr.io){namespace}这是完整的命名空间路径,其中斜杠和点已被下划线替换(例如:my_namespace_path)
配置命名空间专用凭据
为了实现精细的访问控制,您可以配置针对特定注册表命名空间的凭据:
API密钥(密钥):signing-token-apikey-{registry}-{namespace}
用户名(环境变量):signing-token-username-{registry}-{namespace}
示例:关于图片 us.icr.io/my-namespace/my-app:latest
- registry:
us.icr.io - 命名空间:
my-namespace - API密钥密钥:
signing-token-apikey-us.icr.io-my_namespace - 用户名环境变量:
signing-token-username-us.icr.io-my_namespace - 如果未提供用户名,则默认为:
iamapikey
配置注册表专用凭据
若要在注册表的所有命名空间中实现更广泛的访问:
API密钥(密钥):signing-token-apikey-{registry}
用户名(环境变量):signing-token-username-{registry}
示例:对于任何位于 us.icr.io
- API密钥密钥:
signing-token-apikey-us.icr.io - 用户名环境变量:
signing-token-username-us.icr.io - 如果未提供用户名,则默认为:
iamapikey
配置 Docker 的JSON配置文件
您可以提供一个包含多个注册表凭据的 base64-encoded Docker 配置 JSON 文件:
秘密名称:signing-dockerconfigjson
格式:Base64-encoded 符合 Docker 网站上 config.json 格式的 JSON:
{
"auths": {
"us.icr.io": {
"username": "iamapikey",
"password": "your-api-key"
},
"us.icr.io/my-namespace": {
"username": "iamapikey",
"password": "namespace-specific-key"
}
}
}
该管道会优先匹配最具体的路径,从而允许在 Docker 配置中进行命名空间级别的覆盖。
示例配置
关于图片 us.icr.io/production/my-app:v1.0.0:
选项 1:命名空间专用(推荐用于生产环境)
- API密钥密钥:
signing-token-apikey-us.icr.io-production=your-namespace-api-key - 用户名环境变量(可选):
signing-token-username-us.icr.io-production=iamapikey - 如果未指定用户名,则默认为
iamapikey
选项 2:全局注册表
- API密钥密钥:
signing-token-apikey-us.icr.io=your-registry-api-key - 用户名环境变量(可选):
signing-token-username-us.icr.io=iamapikey - 如果未指定用户名,则默认为
iamapikey
选项 3:Docker 配置 JSON
- 秘诀:
signing-dockerconfigjson=base64-encoded-docker-config - 用户名是从 Docker 配置JSON文件中提取的
选项 4:IBM Cloud (默认值,ICR 模式下自动处理)
- API密钥密钥:
ibmcloud-api-key=your-ibmcloud-api-key - 用户名默认为
iamapikey