Azure Key Vault を使用した MSIX と CI/CD パイプラインの署名

署名は、MSIX パッケージを使用する際に行う重要なタスクの 1 つです。 MSIX パッケージが信頼された証明書で署名されていない場合、ユーザーはアプリケーションをインストールできません。 同時に、署名は、セキュリティに関しても最も重要なタスクの 1 つです。 証明書は、悪意のあるアクターによる ID を使用したアプリケーションへの署名に利用されないよう、安全に保存する必要があります。 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。 詳しくは、キー コンテナーの作成に関するページをご覧ください。
  • Azure Key Vault にインポートされた、有効なパッケージの署名証明書。 Azure Key Vault で生成される既定の証明書は、コード署名には使用できません。 パッケージの署名証明書を作成する方法の詳細については、「パッケージ署名用の証明書を作成する」を参照してください。
  • Azure Pipelines または GitHub Actions でホストされている、MSIX パッケージを生成する CI/CD パイプライン。 詳細については、「YAML ファイルを使用した CI/CD パイプラインの構成」を参照してください。

Azure にアプリケーションを登録する

CI/CD パイプラインの一部としてパッケージに署名するには、Azure SignTool というツールを使用します。 これは、Windows 10 SDK に含まれている標準の SignTool ユーティリティと同様に機能しますが、ローカルの証明書を使用する代わりに、Azure Key Vault に接続し、使用可能な証明書のいずれかを使用します。 ただし、接続を確立するには、まず Azure にアプリケーションを登録する必要があります。それにより、Azure SignTool が Azure Key Vault サービスに対して認証するのに必要な資格情報を得られます。

Azure portal を開き、使用可能なサービスの中から Azure Active Directory を選択します。 [アプリの登録] をクリックし、[新規登録] を選択してプロセスを開始します。 アプリケーションに名前 (たとえば、下の画像の SignToolForContoso) を付け、既定の設定はそのまま使用します。

Register an application on Azure

このシナリオではリダイレクト URI が必要ないため、次にアプリケーションをパブリック クライアントとして扱うよう指定します。 [認証] セクションに移動し、[詳細設定][Treat application as a public client]\(アプリケーションをパブリック クライアントとして扱う\)[はい] に変更します。

Set advanced settings

最後の手順では、クライアント シークレットを作成します。これは、Azure SignTool からの認証に必要なパスワードです。 [証明書とシークレット] セクションに移動し、[新しいクライアント シークレット] をクリックします。 名前を付け、有効期限を選択し、[追加] ボタンを押します。 メイン ページにリダイレクトされ、そこにシークレットが値と共に一覧表示されます。 必ずコピーして安全な場所に保管してください。 これは、再度取得することはできません。 ページを更新するとすぐに、シークレットはマスクされ、再度表示する方法はありません。 新しいシークレットの生成が唯一の方法となります。

最後にクライアント シークレットと一緒に保存する必要がある情報が 1 つあります。アプリケーション ID です。 アプリケーションのホームに戻り ([概要] をクリック)、上のセクションで [アプリケーション (クライアント) ID] の値を確認して下さい。

Application Id

Azure Key Vault へのアクセスを有効にする

次の手順では、先ほど作成した Azure アプリケーションを Azure Key Vault サービスにアクセスするように構成します。 Azure portal から、MSIX パッケージの署名に使用する証明書を保持する Azure Key Vault インスタンスに移動します。 [アクセス ポリシー] セクションに移動し、[アクセス ポリシーの追加] をクリックします。 このツールでは、付与するアクセス許可を定義するために使用できるテンプレートの 1 つを選択できますが、このシナリオでは、どれも適したものではありません。 そのため、ドロップダウンを使用して、以下のオプションを手動で設定する必要があります。

  • [キーのアクセス許可] で、[署名] オプションを有効にします。
  • [証明書のアクセス許可] で、[取得] オプションを有効にします。

最後の重要な手順として、このポリシーにアクセスするアプリケーションを指定します。 [プリンシパルの選択] をクリックし、前の手順で作成した 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 Key Vault の URL です。 これは、Azure portal のサービスのメイン ページで、[DNS 名] の下で確認できます。
  • kvi は、登録した Azure アプリのアプリケーション ID で、以前メモしたものです。
  • 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

Note

AzureSignTool の詳細を確認するには、AzureSignTool sign --help を実行します

Azure Pipelines での Azure SignTool の使用

このセクションでは、こちらで説明されているように、Azure Pipelines で YAML ファイルを使用して構成された Windows アプリケーション用の CI/CD パイプラインが既に存在することを前提としています。

まず初めに、Azure Key Vault に接続するために Azure SignTool で必要な情報を格納するいくつかの変数を作成する必要があります。 Azure DevOps で、パイプラインを選択し、上部にある [編集] ボタンをクリックします。 YAML エディターが表示されたら、上部にある [変数] ボタンをクリックしてパネルを開きます。 [+] ボタンをクリックして、次の変数を追加します。

  • AzureKeyVaultUrl には、コンテナーのフレンドリ名を使用します。
  • AzureKeyVaultUrl には、コンテナーの URL を使用します。
  • AzureKeyVaultClientId には、Azure アプリケーションのアプリケーション ID を使用します。
  • AzureKeyVaultClientSecret には、Azure アプリケーションのクライアント シークレットを使用します。

各変数を作成するときは、必ず [この値を誰にも教えないようにします] オプションを有効にしてください。 これにより、パイプラインにアクセスする他のユーザーには、これらの値は表示されません。

Add variable

Azure SignTool をエージェントにインストールする .NET Core タスクを追加し、既存の 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'

コマンドは、パッケージにローカルで署名するために使用したものと似ています。 唯一の違いは次のとおりです。

  • さまざまなパラメーターに固定値を使用する代わりに、構文 $(変数名) で作成した変数を使用しています
  • MSIX パッケージのパスは、MSIX パッケージがビルドの最後に作成されるエージェント上のフォルダーを指します。

GitHub Actions での Azure SignTool の使用

このセクションでは、こちらで説明されているように、GitHub Actions で YAML ファイルを使用して構成された Windows アプリケーション用の CI/CD パイプラインが既に存在することを前提としています。

最初の手順として、Azure Pipelines で行ったのと同様に、認証情報を安全に保存する必要があります。 GitHub ではシークレットが使用され、これらをリポジトリの設定で追加することができます。 Windows アプリケーションをホストする GitHub リポジトリで、[設定] をクリックし、[シークレット] に移動します。

Azure Pipelines で行ったのと同様に、[新規シークレット] をクリックして 4 つのシークレットを作成します。

  • AzureKeyVaultUrl には、コンテナーのフレンドリ名を使用します。
  • AzureKeyVaultUrl には、コンテナーの URL を使用します。
  • AzureKeyVaultClientId には、Azure アプリケーションのアプリケーション ID を使用します。
  • AzureKeyVaultClientSecret には、Azure アプリケーションのクライアント シークレットを使用します。

Azure Pipelines との違いは、シークレットは暗黙的に非表示になっているため、保護するオプションを有効にする必要がないことです。

これで、リポジトリの [アクション] タブから、既存のワークフローを開いて、署名を実行するために必要なタスクを追加することができます。 最初のものは、AzureSign ツールをエージェントにインストールします。

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

2 番目のものは、パッケージに署名します。そのため、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 が、${{ secrets.SECRET_NAME }} という異なる構文を使用して、シークレットにアクセスすることです。 そのため、さまざまなパラメーターに、先ほど [シークレット] セクションで作成した値が格納されます。 もう一つは、署名する MSIX パッケージを見つけるのに別の方法を使用する必要があることです。 このタスクでは、特定の MSIX パッケージを指す代わりに、ビルド出力に格納されているすべてのファイルを反復処理する PowerShell スクリプトが使用されます。 ファイルに MSIX の拡張子が付いている場合、AzureSignTool コマンドを使用して署名されます。

パッケージの配置

どちらの CI/CD プラットフォームを選択した場合でも、フローの最後に、Azure Key Vault に格納されている証明書で署名された MSIX パッケージが作成されます。 これで、他の利用可能なタスクを使用して、Microsoft Store、Web サイト、Microsoft Intune など、任意の配布方法でパッケージを展開することができます。