使用 Azure Key Vault 的 MSIX 和 CI/CD 管線簽署

簽署是使用 MSIX 套件時要執行的其中一項重要工作。 如果 MSIX 套件未以受信任的憑證簽署,使用者將無法安裝該應用程式。 同時,簽署也是最重要的一項工作,也就是安全性。 您必須安全地儲存憑證,以避免惡意執行者使用我們的身分識別來簽署應用程式。 Azure Key Vault 是支援這項需求的最佳選項。

在本文中,我們將瞭解如何運用 CI/CD 管線中的 Azure Key Vault,讓我們可以在程式中自動簽署 MSIX 套件。

重要

本文所述的程式是以稱為 Azure SignTool的開放原始碼工具為基礎,其可搭配 Azure Pipelines 和 GitHub Actions 運作。 如果您使用 Azure Pipelines,也可以結合使用 MSIX 延伸 模組與 Azure Key Vault工作。

必要條件

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

在 Azure 上註冊應用程式

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

開啟 Azure 入口網站,然後選擇可用服務之間的 Azure Active Directory 。 按一下 [ 應用程式註冊 ],然後選擇 [ 新增註冊 ] 以開始處理。 提供應用程式的名稱 (例如,在下圖中 SignToolForContoso 它) 然後保留預設設定。

在 Azure 上註冊應用程式

下一步是將應用程式視為公用用戶端,因為我們是在不需要重新導向 URI 的案例中。 移至 [ 驗證] 區段 ,然後在 [ Advanced settings] 下,將 [將 應用程式視為公用用戶端 ] 切換為 [是]

設定 advanced settings

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

您需要與用戶端密碼一起儲存的最後一項資訊:應用程式識別碼。 按一下 [ 總覽 ]) ,返回至應用程式 (的首頁,然後在上方區段中尋找值 應用程式 (用戶端) 識別碼

應用程式識別碼

啟用 Azure Key Vault 的存取

下一步是設定我們剛才建立的 Azure 應用程式,以存取我們的 Azure Key Vault 服務。 在 Azure 入口網站中,移至保存您要用來簽署 MSIX 套件之憑證的 Azure Key Vault 實例。 移至 [ 存取原則 ] 區段,然後按一下 [ 新增存取原則]。 此工具可讓您選擇其中一個可用的範本來定義我們想要授與的許可權,但在我們的案例中,其中沒有任何一個是正確的大小。 因此,我們需要手動設定,方法是使用下拉式清單,如下所示:

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

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

選取主體

找到之後,請按 [ 選取]。 這就是原則看起來的樣子。

新增存取原則

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

使用 Azure SignTool 在本機簽署套件

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

此工具是以 .NET 通用工具的形式提供。 請務必 安裝最新的 .NET SDK,然後開啟命令提示字元並啟動下列命令:

dotnet tool install --global AzureSignTool 

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

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

這是範例命令:

AzureSignTool sign -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

搭配 Azure Pipelines 使用 Azure SignTool

本節假設您已針對 Azure Pipelines 上以 YAML 檔案設定的 Windows 應用程式已有 CI/CD 管線,如 這裡所述。

一開始,您必須建立幾個變數來儲存 Azure SignTool 所需的資訊,以連接到 Azure Key Vault。 在 Azure DevOps 選取您的管線,然後按頂端的 [ 編輯 ] 按鈕。 在 [YAML 編輯器] 中,按一下頂端的 [ 變數 ] 按鈕以開啟面板。 您將按一下 [+] 按鈕以新增下列變數:

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

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

新增變數

現在您可以藉由新增 .NET Core 工作來自訂現有的 YAML 管線,以在代理程式上安裝 Azure SignTool。 這是要加入的 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'

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

  • 我們不使用固定值來處理各種參數,而是使用我們使用語法 $ (變數名稱 所建立的變數)
  • MSIX 套件的路徑會指向代理程式上的資料夾,在該資料夾中,MSIX 封裝是在組建結束時建立。

搭配 GitHub Actions 使用 Azure SignTool

本節假設您已針對 GitHub Actions 上以 YAML 檔案設定的 Windows 應用程式已有 CI/CD 管線,如 這裡所述。

如同我們在 Azure 管線上所做的第一個步驟,我們需要安全地儲存認證。 GitHub 會使用 秘密 ,並可將其新增至存放庫的設定。 當您在裝載 Windows 應用程式的 GitHub 存放庫之後,請按一下 [ 設定 ],然後移至 [ 秘密]。

同樣地,您在 Azure Pipelines 的情況下,您會按一下 [ 新增密碼 ] 來建立四個秘密:

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

與 Azure 管線的差異在於,秘密是隱含隱藏的,因此您不需要啟用任何選項來保護它們。

現在,透過您存放庫的 [ 動作 ] 索引標籤,您可以開啟現有的工作流程,並新增執行簽署所需的工作。 第一個會在代理程式上安裝 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 平臺為何,在流程結束時,都會有 MSIX 套件,並使用儲存在 Azure Key Vault 上的憑證進行簽署。 現在您可以使用任何其他可用的工作,使用您慣用的發佈選項來部署套件: Microsoft Store、網站、Microsoft Intune 等等。