簽署是使用 MSIX 套件時要執行的重要工作之一。 如果未使用受信任的憑證簽署 MSIX 套件,使用者將無法安裝應用程式。 同時,簽署是安全性方面最重要的工作之一。 憑證必須安全地儲存,以避免惡意執行者可以重複使用這些憑證,以使用我們的身分識別簽署其應用程式。 Azure Key Vault 是支援這項需求的最佳選項。
在本文中,我們將瞭解如何在 CI/CD 管線中運用 Azure Key Vault,以便我們可以在程式中自動簽署 MSIX 套件。
這很重要
本文所述的程式是以名為 Azure SignTool 的開放原始碼工具為基礎,此工具可與 Azure Pipelines 和 GitHub Actions 搭配運作。 如果您使用 Azure Pipelines,您也可以結合 Azure Key Vault 工作來運用 MSIX 擴充功能。
先決條件
- Azure 帳戶。 如果您還沒有 Azure 帳戶,請 從這裡開始。
- Azure 金鑰保管庫。 如需詳細資訊,請參閱 建立 Key Vault。
- 匯入至 Azure Key Vault 的有效套件簽署憑證。 Azure Key Vault 所產生的預設憑證不適用於程式代碼簽署。 如需如何建立套件簽署憑證的詳細資訊,請參閱 建立套件簽署的憑證。
- 產生 MSIX 套件的 CI/CD 管線,並將套件裝載於 Azure Pipelines 或 GitHub Actions。 如需詳細資訊,請參閱 使用 YAML 檔案設定 CI/CD 管線。
在 Azure 上註冊應用程式
若要將套件簽署為 CI/CD 管線的一部分,我們將使用名為 Azure SignTool 的工具。 它的運作方式與 Microsoft Windows 10 SDK 中包含的標準 SignTool 工具類似,但不使用本機憑證,而是透過連線至 Azure 密鑰保管庫以使用其中一個可用的憑證。 不過,若要建立連線,我們必須先在 Azure 上註冊應用程式,這會提供我們需要的認證,讓 Azure SignTool 能夠對我們的 Azure Key Vault 服務進行驗證。
開啟 Azure 入口網站,並在可用的服務中選擇 [Azure Active Directory ]。 按兩下 [應用程式註冊 ],然後選擇 [ 新增註冊 ] 以啟動程式。 為應用程式命名(例如,下圖中的 SignToolForContoso ),然後保留預設設定。
下一個步驟是將應用程式視為公用客戶端,因為我們位於不需要重新導向 URI 的案例中。 移至 [ 驗證] 區段 ,然後在 [ 進階設定] 底下,將 [ 將應用程式視為公用用戶端 ] 變更為 [是]。
最後一個步驟是建立客戶端密碼,也就是我們需要從 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 -kvt "<tenantID>" -kvu "https://contosoexpenses-blog.vault.azure.net/" -kvi "aaaabbbb-0000-cccc-1111-dddd2222eeee" -kvs "this-is-the-secret" -kvc "MyCertificate" -tr http://timestamp.digicert.com -v .\MyContosoApp.msix
備註
若要深入瞭解 AzureSignTool,請執行 AzureSignTool sign --help
搭配 Azure Pipelines 使用 Azure SignTool
本節假設您已經有一個適用於 Windows 應用程式的 CI/CD 管線,已在 Azure Pipelines 上通過 YAML 檔案設定,如 此處 所述。
首先,您必須建立一些變數來儲存 Azure SignTool 連線至 Azure Key Vault 所需的資訊。 在 Azure DevOps 中,選取您的管線,然後按頂端的 [ 編輯] 按鈕。 當您在 YAML 編輯器中之後,按下頂端的 [ 變數 ] 按鈕以開啟面板。 您將按下 [+] 按鈕以新增下列變數:
- AzureKeyVaultName,以及保存庫對應的易記名稱。
- AzureKeyVaultUrl,將您的保存庫的 URL 填入其中。
- AzureKeyVaultClientId,即您 Azure 應用程式的應用程式識別碼。
- AzureKeyVaultClientSecret,具有 Azure 應用程式的客戶端密碼。
當您建立每個變數時,請務必啟用 [ 保留此值 秘密] 選項。 它會確保能存取管線的其他人無法查看他們的數值。
現在您可以新增 .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 Key Vault 上的憑證簽署 MSIX 套件。 現在您可以使用任何其他可用的工作,使用您慣用的發行版來部署套件:Microsoft市集、網站、Microsoft Intune 等。