1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Azure App ServiceでホストされているASP.NET Coreアプリケーションのデータ保護の構成

Posted at

デプロイスロットをスワップするとすべてのユーザーがログアウトされてしまう問題

Azure App ServiceでホストされているASP.NET Coreアプリケーションでデプロイスロットを切り替えると、ログインしていたすべてのユーザーがログアウトされてしまうという問題に遭遇しました。

調べてみると、Microsoftのドキュメントに下記のような記載がありました。

アプリが Azure Apps でホストされている場合、キーは %HOME%ASP.NET_DataProtection-Keys フォルダーに保持されます。 このフォルダーはネットワーク ストレージにバックアップされ、アプリをホストしているすべてのマシンで同期されています。

  • 保存中のキーは保護されていません。
  • DataProtection-Keys フォルダーから、単一のデプロイ スロットのアプリのすべてのインスタンスにキー リングが提供されます。
  • ステージングや運用などの別のデプロイ スロットでは、キー リングが共有されません。 ステージングから運用へのスワップや A/B テストの使用など、デプロイ スロットをスワップすると、データ保護を使っているアプリからは、前のスロット内のキー リングを使って格納されたデータを復号化できなくなります。 その結果、標準の ASP.NET Core cookie 認証を使うアプリでは、データ保護を使って cookie が保護されているため、ユーザーがログアウトされます。 スロットに依存しないキー リングが必要な場合は、Azure Blob Storage、Azure Key Vault、SQL ストア、Redis キャッシュなどの外部キー リング プロバイダーを使います。

データ保護キーは、認証cookieの保護やCSRFトークン生成時のキーとして利用されるものですが、Asp.NETCoreアプリの既定の設定ではデプロイスロット間で共有されない場所に保管されるためにスロットの切り替え後に認証cookieが復号できずにログアウトされてしまうようです。

Azure Blob Storage と Azure Key Vaultを利用したデータ保護キーの構成

上記の問題は、異なるデプロイスロット間で共有できる場所にデータ保護キーを保管することで解決できるようです。

保護キーの保管先はデータベースやRedisキャッシュなども選択できますが、今回はAzure Blob Storageを利用することとします。
また、保護キー自体を保護するための暗号化キーをAzure Key Vaultで管理するようにします。

コードの修正

まずは、ソースコード側でデータ保護の構成を行います。

下記ライブラリをNuGetでインストール後、DataProtectionのミドルウェアを下記の様に構成します。

  • Azure.Extensions.AspNetCore.DataProtection.Blobs
  • Azure.Extensions.AspNetCore.DataProtection.Keys
  • Azure.Identity
using Microsoft.AspNetCore.DataProtection;
using Azure.Identity;
using Azure.Storage.Blobs;

public class Startup
{
    //....

    public void ConfigureServices(IServiceCollection services)
    {
        //....
        //アプリケーション設定からBlobコンテナのURLとKey Vaultのキー識別子を取得
        var blobContainerUri = configuration["DataProtectionBlobContainerUri"];
        var keyIdentifier = configuration["DataProtectionKeyIdentifier"];
        //Blobコンテナクライアントを作成
        var blobContainer = new BlobContainerClient(
                new Uri(blobContainerUri), new DefaultAzureCredential());
        blobContainer.CreateIfNotExists();
        var blobClient = blobContainer.GetBlobClient("keys.xml");
        //サービスに登録
        services
            .AddDataProtection()
            .PersistKeysToAzureBlobStorage(blobClient)
            .ProtectKeysWithAzureKeyVault(new Uri(keyIdentifier), new DefaultAzureCredential());
     }
}

Azure StrageのBlobコンテナの作成

下記の手順でデータ保護キーを格納するためのBlobコンテナを作成します。

Strageアカウントの作成

まずはAzureポータルにログインし、 Azure Strageアカウントを作成します。

create strage account
  • Standard(汎用v2アカウント)
  • geo冗長ストレージ(GRS)

Blobコンテナの作成

作成したストレージアカウントにコンテナを追加します。

create blob container
  • パブリックアクセスレベルは「プライベート」とします。

BlobコンテナのURLを取得

作成したコンテナのプロパティを開き、URLをコピーしておきます。(後ほどこのURLをAppSerciceのアプリケーション設定に登録します。)

Key VaultでKeyを作成する

次に、データ保護キー自体を保護ずるためのキーをAzure Key Vaultで作成します。

Key Vaultコンテナの作成

キーの作成

キーの種類、サイズを指定してキーを作成します。

キー識別子の取得

作成したキーを選択後、バージョンを選択
image.png

ここで表示されるキー識別子をコーピーしておきます。(後ほどこのURLをAppSerciceのアプリケーション設定に登録します。)
image.png

また、許可された操作は下記のみにチェックが入っている状態に変更して「保存」します。

  • キーを折り返す
  • キーの折り返しを解除

これで、データの保管先の設定ができました。次に、AppSerciceがこれらのリソースにアクセスできるように設定する必要があります。

App Sercice からデータ保護のリソースにアクセスする

※ ここでは、既にApp Serciceが作成されていて、Asp.NETCoreアプリがデプロイされていることを前提としています。

App Serviceのシステム割り当てマネージドIDを有効にする

Azure ポータルで対象のApp Serciceを開きます。左のメニューでIDを選択し、「システム割り当て済み」タブで「状態」をオンに設定します。

Blobコンテナのアクセス制御でApp ServiceのマネージドIDに対しロールを割り当てる

Azureポータルで、作成したStrage Blobコンテナを開き、左のメニューで「アクセス制御(IAM)」を選択し、「ロールの割り当て」タブをクリックします。

ロールの割り当て追加で「ストレージBLOBデータ共同作成者」のロールを選択します。

アクセスの割当先を「マネージドID」にして、メンバーを選択するをクリック。マネージドIDのプルダウンで対象のAppServiceを選択して割り当てを追加します。

Keyコンテナのアクセス制御でApp ServiceのマネージドIDに対しロールを割り当てる

KeyVaultのKeyコンテナに対しても同様にロールを割り当てます。

作成したKeyVaultのコンテナで「アクセス構成」を選択し、アクセス許可モデルを「Azureロールベースのアクセス制御」に設定後、「アクセス制御(IAM)」
image.png

ロールは「キーコンテナー暗号化ユーザー」を選択
image.png

アクセスの割当先を「マネージドID」にして、メンバーを選択するをクリック。マネージドIDのプルダウンで対象のAppServiceを選択して割り当てを追加します。
image.png

App Serviceのアプリケーション設定にBlobコンテナのURLとKeyコンテナのキー識別子を設定する

ソースコードを修正した際、アプリケーション設定(Configuration)から下記情報を取得するようにしていました。

名前
DataProtectionBlobContainerUri {BlobコンテナのURL}
DataProtectionKeyIdentifier {Key VaultのKey識別子}

この値をApp Serviceのアプリケーション設定に登録します。

確認

これで一通りの設定が完了しました。
設定したApp ServiceのWebページにアクセス後、Keyコンテナにキーファイルが保存されていればOKです。

image.png

参照

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?