使用 Azure 金鑰保存庫 簽署 MSIX 和 CI/CD 管線

簽署是使用 MSIX 套件時要執行的重要工作之一。 如果未使用受信任的憑證簽署 MSIX 套件,使用者將無法安裝應用程式。 同時,簽署是安全性方面最重要的工作之一。 憑證必須安全地儲存,以避免惡意執行者可以重複使用這些憑證,以使用我們的身分識別簽署其應用程式。 Azure 金鑰保存庫 是支援這項需求的最佳選項。

在本文中,我們將瞭解如何在 CI/CD 管線中運用 Azure 金鑰保存庫,以便我們可以在程式中自動簽署 MSIX 套件。

重要

本文所述的程式是以名為 Azure SignTool 的 開放原始碼 工具為基礎,此工具可與 Azure Pipelines 和 GitHub Actions 搭配運作。 如果您使用 Azure Pipelines,您也可以結合 Azure 金鑰保存庫 工作來運用 MSIX 擴充功能。

必要條件

  • Azure 帳戶。 如果您沒有 Azure 帳戶,請從這裡開始。
  • Azure Key Vault。 如需詳細資訊,請參閱建立 Key Vault
  • 已匯入 Azure Key Vault 的有效套件簽署憑證。 Azure Key Vault 產生的預設憑證不適用於程式碼簽署。 如需詳細了解如何建立套件簽署憑證,請參閱建立套件簽署的憑證
  • CI/CD 管線,其會產生裝載於 Azure Pipelines 或 GitHub Actions 上的 MSIX 套件。 如需詳細資訊,請參閱 使用 YAML 檔案設定 CI/CD 管線。

在 Azure 上註冊應用程式

若要將套件簽署為 CI/CD 管線的一部分,我們將使用名為 Azure SignTool 的工具。 其運作方式與 Windows 10 SDK 中包含的標準 SignTool 公用程序類似,但與其使用本機憑證,而是連線到 Azure 金鑰保存庫,以使用其中一個可用的憑證。 不過,若要建立連線,我們必須先在 Azure 上註冊應用程式,這會提供我們需要的認證,讓 Azure SignTool 能夠對我們的 Azure 金鑰保存庫 服務進行驗證。

開啟 Azure 入口網站,並在 可用的服務中選擇 [Azure Active Directory ]。 按兩下 [ 應用程式註冊 ],然後選擇 [ 新增註冊 ] 以啟動程式。 為應用程式命名(例如,下圖 中的 SignToolForContoso ),然後保留預設設定。

Register an application on Azure

下一個步驟是將應用程式視為公用客戶端,因為我們位於不需要重新導向 URI 的案例中。 移至 [驗證] 區段,然後在 [進階設定] 底下,將 [將應用程式視為公用用戶端] 變更[是]。

Set advanced settings

最後一個步驟是建立客戶端密碼,也就是我們需要從 Azure SignTool 進行驗證的密碼。 移至 [ 憑證與秘密] 區段,然後按兩下 [ 新增客戶端密碼]。 為它命名,選擇到期日,然後按 [ 新增 ] 按鈕。 系統會將您重新導向回主頁面,其中秘密會連同其值一起列出。 請務必複製它,並將它儲存在安全的地方。 您將無法再次擷取它。 一旦您重新整理頁面,秘密就會被遮罩,而且不會有任何方式顯示它。 您唯一的選項是產生新的秘密。

您需要與客戶端密碼一起儲存的最後一個資訊:應用程式識別碼。 返回應用程式的首頁(按兩下[概觀],並在上方區段中尋找 [應用程式][用戶端] 識別碼的值

Application Id

啟用 Azure 金鑰保存庫 的存取權

下一個步驟是設定我們剛建立的 Azure 應用程式,以存取 Azure 金鑰保存庫 服務。 從 Azure 入口網站 移至 Azure 金鑰保存庫 實例,此實例會保存您想要用來簽署 MSIX 套件的憑證。 移至 [ 存取原則] 區段,然後按兩下 [ 新增存取原則]。 此工具支持選擇其中一個可用的範本來定義我們想要授與的許可權,但在我們的案例中,沒有任何一個範本適合。 因此,我們需要使用下拉式清單手動設定下列選項:

  • 在 [ 金鑰限] 底下,啟用 [ 簽署 ] 選項。
  • 在 [ 憑證許可權] 底下,啟用 [ 取得 ] 選項。

最後一個重要步驟是指定要存取此原則的應用程式。 按兩下 [ 選取主體 ],並使用其名稱搜尋您在上一個步驟中建立的 Azure 應用程式。 在此範例中,它稱為 SignToolForContoso

Select principal

找到它之後,請按 [選取]。 這就是原則的外觀。

Add access policy

當您完成此程式時,按兩下 [ 新增 ] 以建立原則。

使用 Azure SignTool 在本機簽署套件

現在 Azure 組態已完成,我們可以使用 Azure SignTool 來簽署套件。 在本節中,我們將使用工具在本機熟悉此工具。 在下一節中,我們將使用它作為 CI/CD 管線的一部分。

此工具可作為 .NET 全域工具使用。 請務必 安裝最新的 .NET SDK,然後開啟命令提示字元並啟動下列命令:

dotnet tool install --global AzureSignTool 

現在您可以使用 AzureSignTool 命令簽署套件,這需要下列參數:

  • kvu是 Azure 金鑰保存庫 的 URL。 您可以在 Azure 入口網站 的 [DNS 名稱] 底下,在服務的主頁面中找到它。
  • kvi 是您已註冊之 Azure 應用程式的應用程式識別碼,且先前已記下。
  • kvs 是您先前產生的客戶端密碼,且先前已注意到。
  • kvc 是您想要使用的憑證易記名稱。
  • tr 是時間戳伺服器的 URL。 藉由使用此選項,我們可以讓套件在憑證到期時也能運作。
  • v 是我們想要簽署之 MSIX 套件的路徑。

這是範例命令:

AzureSignTool sign -kvt "<tenantID>" -kvu "https://contosoexpenses-blog.vault.azure.net/" -kvi "64fae35e-cb84-4b9f-86eb-5170d169316d" -kvs "this-is-the-secret" -kvc "MyCertificate" -tr http://timestamp.digicert.com -v .\MyContosoApp.msix

注意

若要深入瞭解 AzureSignTool,請執行 AzureSignTool sign --help

搭配 Azure Pipelines 使用 Azure SignTool

本節假設您已經有一個 CI/CD 管線,適用於在 Azure Pipelines 上使用 YAML 檔案設定的 Windows 應用程式,如下所述

首先,您必須建立一些變數來儲存 Azure SignTool 連線至 Azure 金鑰保存庫 所需的資訊。 在 Azure DevOps 中,選取您的管線,然後按頂端的 [編輯] 按鈕。 當您在 YAML 編輯器中之後,按下頂端的 [變數 ] 按鈕以開啟面板。 您將按下 [+] 按鈕以新增下列變數:

  • AzureKeyVaultName,具有保存庫的易記名稱。
  • AzureKeyVaultUrl,具有保存庫的 URL。
  • AzureKeyVaultClientId,具有 Azure 應用程式的應用程式識別碼。
  • AzureKeyVaultClientSecret,具有 Azure 應用程式的客戶端密碼。

當您建立每個變數時,請務必啟用 [保留此值 秘密] 選項。 它會確保有管線存取權的其他人員將無法看到其值。

Add variable

現在您可以新增 .NET Core 工作,在代理程式上安裝 Azure SignTool,以自定義現有的 YAML 管線。 這是要新增的 YAML:

- task: DotNetCoreCLI@2
  displayName: 'Install Azure SignTool'
  inputs:
    command: custom
    custom: tool
    arguments: 'install --global AzureSignTool'

下一個步驟是新增PowerShell工作,以執行將簽署封裝的命令。 建立 MSIX 套件之後,您只能在建置程式結束時執行這項工作。

- powershell: '& AzureSignTool sign -kvu $(AzureKeyVaultUrl) -kvi $(AzureKeyVaultClientId) -kvs $(AzureKeyVaultClientSecret) -kvc $(AzureKeyVaultName) -tr http://timestamp.digicert.com -v "$(System.DefaultWorkingDirectory)\MyPipeline\MyContosoApp\MyContosoApp.msix"'
  displayName: 'Sign the package'

命令類似於我們用來在本機簽署套件的命令。 唯一的差異如下:

  • 我們不是使用各種參數的固定值,而是使用語法 $(Variable-Name) 所建立的 變數
  • MSIX 套件的路徑會指向在組建結尾建立 MSIX 套件之代理程式上的資料夾。

搭配 GitHub Actions 使用 Azure SignTool

本節假設您已經有使用 GitHub Actions 上 YAML 檔案設定之 Windows 應用程式的 CI/CD 管線,如下所述

如同我們在 Azure Pipeline 上所做的第一個步驟,我們需要安全地儲存認證。 GitHub 會使用 秘密 ,而且可以在存放庫的設定中新增秘密。 一旦您在裝載 Windows 應用程式的 GitHub 存放庫上,請按兩下 [設定 然後移至 [秘密]。

與使用 Azure Pipelines 所做的類似,您會按兩下 [新增秘密] 來建立四個秘密

  • AzureKeyVaultName,具有保存庫的易記名稱。
  • AzureKeyVaultUrl,具有保存庫的 URL。
  • AzureKeyVaultClientId,具有 Azure 應用程式的應用程式識別碼。
  • AzureKeyVaultClientSecret,具有 Azure 應用程式的客戶端密碼。

Azure Pipeline 的差異在於秘密會隱含隱藏,因此您不需要啟用任何保護秘密的選項。

現在,透過 存放庫的 [動作] 索引標籤,您可以開啟現有的工作流程,並新增執行簽署所需的工作。 第一個工具會在代理程式上安裝 AzureSign 工具:

- name: Install AzureSignTool
  run: dotnet tool install --global AzureSignTool

第二個套件將會簽署套件,因此,必須在Visual Studio組建完成且產生 MSIX 套件之後執行。

 - name: Sign package
   run: |
        Get-ChildItem -recurse -Include **.msix | ForEach-Object {
        $msixPath = $_.FullName
        & AzureSignTool sign -kvu "${{ secrets.AzureKeyVaultUrl }}" -kvi "${{ secrets.AzureKeyVaultClientId }}" -kvs "${{ secrets.AzureKeyVaultClientSecret }}" -kvc ${{ secrets.AzureKeyVaultName }} -tr http://timestamp.digicert.com -v $msixPath
        }

相較於我們在 Azure Pipelines 中使用的工作,此工作有幾個差異。 第一個是 GitHub 使用不同的語法來存取秘密,也就是 ${{ 秘密。SECRET_NAME }}。 因此,各種參數會填入我們先前在 [秘密] 區段中建立的值。 另一個是,您需要使用不同的方法來尋找要簽署的 MSIX 套件。 工作不是指向特定的 MSIX 套件,而是使用 PowerShell 腳本,逐一查看儲存在組建輸出中的所有檔案。 如果檔案具有 MSIX 擴展名,則會使用 AzureSignTool 命令來簽署它。

部署套件

不論您選擇的 CI/CD 平台為何,在流程結束時,您都會使用 Azure 金鑰保存庫 上儲存的憑證簽署 MSIX 套件。 現在您可以使用任何其他可用的工作,使用您慣用的散發選擇來部署套件:Microsoft Store、網站、Microsoft Intune 等。