如何使用 Azure Key Vault 中的证书/密钥对使用 Azure Pipelines 构建的代码进行签名?

Ano*_*yne 30 azure-keyvault azure-devops azure-pipelines

我们正在从本地构建服务器迁移到 Azure Pipelines。我们生产“收缩包装”桌面软件,因此很明显我们需要在发布之前对所有二进制文件进行签名。我们当前的构建基础架构使用 GlobalSign 的 USB 硬件令牌来完成此操作,但显然,当我们进行云构建时,这将不起作用 - 遗憾的是,云没有配备 USB 端口:D

现在,GlobalSign 最近开始宣传Azure Key Vault 作为密钥存储选项,他们非常乐意将其出售给我们,但我不确定我们实际上如何将其与我们的构建管道集成(或者确实是这样)甚至可能)。

有没有人真正做过这项工作?

Pau*_*ood 37

代码签名

我一直在与 Azure Key Vault 和 Azure Pipelines 进行斗争以让我们的代码签名,并取得了成功。所以这就是我发现的。

至关重要的是,用于代码签名的扩展验证 (EV) 证书与“普通”SSL 证书非常不同。标准的可以随心所欲地导出,这意味着您可以将其上传到 Azure Pipelines 并与标准的 Microsoft 签名工具一起使用。

但是,一旦 EV 证书在 Azure Key Vault 中,它就不会以任何通常的方式出现。您必须使用上面 Anodyne发现的优秀Azure 签名工具从管道中调用它

将您的证书放入 Key Vault。您可以使用任何您喜欢的证书颁发机构来生成证书,只要他们知道您需要一个 EV 证书,并且重要的是一个具有硬件安全模块 (HSM) 的证书,而不是带有物理 USB 密钥的证书。任何基于云的系统(如 Key Vault)都需要 HSM 版本。

要获得外部访问此证书的权限,您可以按照此页面操作,要注意它错过了一个步骤。因此,请先阅读该文档,然后再阅读这些汇总步骤,以设置 Key Vault:

  1. 打开 Azure 门户,转到该Azure Active Directory区域,然后创建一个App registration: 输入一个令人难忘的名称,忽略Redirect URI并保存它。
  2. 转到您的具体Key Vault,然后Access control (IAM),然后Add role assignment。在select输入框中输入您刚刚创建的应用程序的名称。也选择一个Role,我建议Reader然后保存。
  3. 缺失的部分:仍在 Key Vault 中,单击Access policies菜单项。单击Add Access Policy并添加您的应用程序。在Certificate Permissions需要有Get打勾。而且Key Permissions,尽管您在这个保管库中可能根本没有任何密钥,但需要拥有GetSign。你会认为这两个会在证书烫发中......
  4. 返回到您刚刚创建的应用程序。选择Certificates & secrets,然后选择上传证书(一个纯粹用于远程访问 Key Vault 的新证书)或创建一个client secret. 如果是后者,请保留密码的副本,您将不会再看到它!
  5. Overview应用程序的部分将是Application (client) ID. 这和密码或证书是稍后将在管道任务中提供给 Azure 签名工具的内容。

处理来自 Azure 的实际代码签名需要多个步骤。以下内容适用于 Microsoft 托管代理,但类似问题会影响您拥有的任何私有代理。

  1. Azure 签名工具需要安装 .NET Core SDK,但版本至少为 2.x,并且由于始终使用最新的.NET Core SDK ,这意味着只要 Windows 的版本足够新,你不需要自己安装它。您可以看到哪个版本的SDK 随哪个 Windows 代理一起提供

    HostedAzure Pipelines 中的当前操作系统版本(也称为Default Hosted)在撰写本文时为 Windows Server 2012 R2。这还不够最新。安装更新的 .NET Core SDK 来解决这个问题会拖延每次构建的时间,尽管安装有效,但调用 Azure 签名工具可能无效。它似乎只找到旧版本的 SDK,并抛出此错误:Unable to find an entry point named 'SignerSignEx3' in DLL 'mssign32'.

    因此,最简单的方法是更改​​您的构建以使用更高版本的操作系统映像。Windows 2019 就像一个魅力。并且无需安装任何版本的 .NET Core。

  2. 然后创建一个命令行任务来安装 Azure 签名工具。您也可以使用 .NET Core CLI 任务,但没有必要。在任务中,键入:

    set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
    dotnet tool install --global AzureSignTool --version 2.0.17
    
    Run Code Online (Sandbox Code Playgroud)

    自然地使用您想要的任何版本。

    DOTNET_SKIP_FIRST_TIME_EXPERIENCE 环境变量并不是绝对必要的,但设置它可以大大加快速度(请参阅此处的解释)。

  3. 最后,创建另一个命令行任务并键入要运行的 Azure 签名工具命令。在 Windows 上,这将类似于下面的内容,注意^不要/作为行继续标记。当然,请参阅此处了解更多参数信息

     AzureSignTool.exe sign -du "MY-URL" ^
       -kvu https://MY-VAULT-NAME.vault.azure.net ^
       -kvi CLIENT-ID-BIG-GUID ^
       -kvs CLIENT-PASSWORD ^
       -kvc MY-CERTIFICATE-NAME ^
       -tr http://timestamp.digicert.com ^
       -v ^
       $(System.DefaultWorkingDirectory)/Path/To/My/Setup/Exe
    
    Run Code Online (Sandbox Code Playgroud)

从理论上讲,您应该会成功!符号工具的输出相当不错,通常可以指出问题所在。

补发证书

如果需要补发证书,情况就大不一样了。

  1. 在 Azure 中,转到证书并单击它,打开一个页面,显示该证书的版本,包括当前版本和旧版本。

  2. 单击“新版本”按钮,可能接受默认设置(取决于您希望做出的选择),然后单击“创建”。

  3. 这将带您返回到版本页面,将出现一个消息框,指出“证书 XXXX 的创建当前正在等待”。单击那里(或“证书操作”按钮)打开“证书操作”侧页。在那里,下载 CSR(证书签名请求)。

  4. 在 GlobalSign 中,按照他们的说明重新颁发现有证书。重新发布后,他们将发送一封电子邮件,说明如何下载。

  5. 再次登录GlobalSign,输入临时密码后,打开CSR,将全文(以 开头-----BEGIN CERTIFICATE REQUEST-----)复制到GlobalSign。提交它。

  6. 使用“安装我的证书”按钮下载。然后在 Azure 的“证书操作”侧页面中 - 使用“合并签名请求”按钮将 .CER 文件上传到 Azure。这将创建证书的新版本。

  7. 禁用旧版本的证书。


Pat*_*SFT 7

是的,它可以在 Azure DevOps Service Build pipeline 中执行此操作。

正常情况下,我们通常使用SignTool.exe命令来对文件进行签名。市场上还有一个扩展Code Signing,它可以对单个文件进行签名,您可以使用脚本对多个文件运行SignTool.exe命令。

因此,您可以将协同设计证书导出到 pfx 文件,然后将其作为安全文件上传到 Azure Devops 安全文件存储,使其可供您的构建使用。

Azure DevOps 可以存储安全文件。检查此链接了解详细信息:安全文件

Azure Key Vault实例有点复杂。我们还有一个 Azure Key Vault 任务。

在生成或发布管道中使用此任务从 Azure Key Vault 实例下载身份验证密钥、存储帐户密钥、数据加密密钥、.PFX 文件和密码等机密。

该任务可用于从保管库中获取全部或部分机密的最新值,并将它们设置为可在管道的后续任务中使用的变量。

不确定 GlobalSign 如何将代码签名与您的环境集成。理论上来说,它是可以做到这一点的。具体的细节和实施,你可能需要和他们的售前讨论。希望这可以帮助。

  • 谢谢你回到我身旁!我认为这里的主要问题是 GlobalSign 不会让我们拥有代码签名证书的私钥(出于安全原因)。他们坚持将密钥保存在 USB 令牌、HSM 或 Azure Key Vault 中。这意味着我们无法将私钥导出到 PFX 文件。不过,我发现 [AzureSignTool](https://github.com/vcsjones/AzureSignTool) 看起来可以完成这项工作。如果这对我们有用,我会将其作为答案发布:) (2认同)