しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET Core 5.0 に向けて Azure 関連パッケージのアップグレードを行っておく

.NET Conf 2020 の日程も発表されて、既に Daily Build では RC や 6.0 が出ている .NET Core 周りですが、そろそろ 5.0 へのアップグレードに向けた作業を行っておくかーという気分になっています。

ちなみに .NET Conf 2020 は 11 月 10-12 日での開催です。.NET 5 Launch イベントです。

Azure Functions がどうなるのかちょっと怪しいですが、最悪 netstandard2.1 でライブラリを書いておけば共有できるようになっています。

.NET 5 は LTS ではありませんが、毎年 .NET Core のバージョンアップが予定されているのと、例によってパフォーマンス改善や API 追加などが非常に広範囲に行われているのでアップグレードは行っておきましょう。

ASP.NET Core はかなり成熟してきたので 5.0 になっても大きな変更はなく、すんなりと TFM を変えてパッケージの更新を行えば 5.0 へ移行できるはずです。ただし Azure 関連のパッケージが廃止予定になっているため、この点に関しては修正の必要があります。

Issue にも書いてあるように、既存のパッケージは 5.0 ではサポートされません。しかし新しいパッケージは 2.1 から 5.0 までサポートされるので、先に移行しておくことが可能です。

Data Protection の Key Storage として Blob を使っていることが多いと思うので、この辺りの移行を先にしておくと ASP.NET Core 5.0 への移行が楽になります。

Configuration Provider

使っている人が多いと思うのが Key Vault Secrets を Configuration として読み込むパッケージでしょう。接続文字列や API キーなどは Key Vault に格納しつつ、App Service から Managed Identity でアクセスするのが割と鉄板感あります。

App Service には Key Vault Reference という機能がありますが、Service Endpoint / Private Endpoint 経由では使えないので、この Configuration Provider を使って解決しているケースが多そうです。

新しいパッケージは全て Azure.* という Prefix が付いているので分かりやすいです。最近の Azure SDK の命名規約に沿ったパッケージ名になっています。

まだドキュメントは更新されていないので、サンプルコードを載せておきます。メソッド名は変わっていないですが、パラメータが変わっているので渡し方には注意が必要です。

サンプルコードでは本番のみ Key Vault と Managed Identity を使うようにしています。

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =>
            {
                if (context.HostingEnvironment.IsProduction())
                {
                    var builtConfig = config.Build();

                    config.AddAzureKeyVault(new Uri(builtConfig["KeyVaultEndpoint"]), new DefaultAzureCredential());
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

開発環境でも Visual Studio の Azure サービス認証や Azure CLI 経由で使えますが、一般的には User Secrets を使えば良いので本番だけに限定します。デバッグ開始までに時間もかかるのでストレスが溜まります。

上の例では DefaultAzureCredential を使っていますが、これは Azure.Identity パッケージをインストールする必要があるので忘れないようにしてください。

Key Storage Provider

App Service の場合はデフォルトで特別対応してくれていますが、Deployment Slot を使っている場合には Data Protection のキーを Blob に保存する設定を追加していると思います。

Docker で運用している場合にもキーの永続化が必要なので、同じような設定を行っているはずです。

キーを Blob に保存するパッケージと Key Vault をキーの保護に使うパッケージが新しくなっているので、使っている場合にはそれぞれをインストールしなおします。

Key Vault の方を使っている人はあまり多くない気がしますが、この二つはセットで使います。

これもドキュメントがまだ更新されていないので、サンプルコードを載せておきます。メソッド名は Configuration Provider と同様に変わっていませんが、パラメータは異なります。

新しいパッケージの方が分かりやすいパラメータになっているので良い感じです。

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        services.AddDataProtection()
                .PersistKeysToAzureBlobStorage(Configuration.GetConnectionString("DefaultStorageConnection"), "secrets", "keys.xml")
                .ProtectKeysWithAzureKeyVault(new Uri(Configuration["KeyIdentifier"]), new DefaultAzureCredential());
    }
}

Blob へのアクセスには SAS や Managed Identity が使えますが、ここはこれまで通り接続文字列を使うことにしました。以前は CloudBlobClient を作って渡す必要がありましたが、手間が省ける形になっています。Key Vault へのアクセスは Managed Identity を使うようにしています。

これで適当にデバッグ実行すると、指定した Blob にキーが保存されます。ファイルフォーマットに依存しないパッケージなので、アップグレードしても問題なく読めます。

f:id:shiba-yan:20200903181054p:plain

難しくはないですが、ドキュメントがまだ更新されていないというのだけがネックでした。使用されている Azure Storage / Key Vault SDK も新しいバージョンなので安心です。