Azure Council Experts 定例会で、Azure Bicep の入門編のセッションに登壇しました。
これまでの ACE は会員企業向けのクローズドなイベントを開催していましたが、今後は誰でも参加できるオープンな形式にリニューアルしました。このイベント後には、会員企業のみのクローズドな会も用意していて、2部構成となっています。
Bicep は従来の ARM テンプレートの課題を解決する良いプロジェクトで積極的に使っていきたいので、その思いを話してきました。
Azure Council Experts 定例会で、Azure Bicep の入門編のセッションに登壇しました。
これまでの ACE は会員企業向けのクローズドなイベントを開催していましたが、今後は誰でも参加できるオープンな形式にリニューアルしました。このイベント後には、会員企業のみのクローズドな会も用意していて、2部構成となっています。
Bicep は従来の ARM テンプレートの課題を解決する良いプロジェクトで積極的に使っていきたいので、その思いを話してきました。
11 月に .NET 6 がリリースされることもあり、現時点での ASP.NET Core アプリケーションにおける Azure Key Vault の使い方を改めて考えてみました。
データベースの接続文字列や API Key などのセンシティブな情報は、アプリケーションのリポジトリ内では管理したくありません。
アプリケーションとセンシティブな情報を分離させる構成を実現する方法にはいつくかありますが、現時点では次の方針がシンプルでいいのではと考えています。
上記の方針に従って、実際に構成を作って試してみます。
ASP.NET Core アプリケーションからアクセスする SQL Database の接続文字列を登録するシナリオを例に説明していきます。
Key Vault の Secret に WebApp20--SqlConnection
という名前で、SQL Connection for Key Vault.
という Value を登録します。
名前に WebApp20
のプレフィックスを付けた理由は、1つの Key Vault でフロントエンドやバックエンドなど複数のアプリケーションの構成を管理する想定だからです。
JSON の階層構造で管理したいので --
で区切っています。Key Vault の名前には :
を使うことができないで注意してください。
.NET 5 の Web API アプリケーションを作成し、必要な NuGet パッケージをインストールします。
Install-Package Azure.Identity -Version 1.4.1 Install-Package Azure.Extensions.AspNetCore.Configuration.Secrets -Version 1.2.1
開発環境以外では MSI を使って Key Vault に接続するように構成します。
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureAppConfiguration((hostingContext, config) => { var settings = config.Build(); if (!hostingContext.HostingEnvironment.IsDevelopment()) { var keyVaultUrl = settings["KeyVaultUrl"]; config.AddAzureKeyVault(new Uri(keyVaultUrl), new DefaultAzureCredential()); } }); webBuilder.UseStartup<Startup>(); });
接続する Key Vault の URL は、appsettings.json で定義しておきます。
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "KeyVaultUrl": "https://xxx.vault.azure.net/" }
アプリケーションで SQL Database の接続文字列を扱いやすくするため、POCO クラスにマッピングします。
public class MySettings { public string SqlConnection { get; set; } }
Key Vault の Secret から自分のアプリケーション情報だけを取得したいので、WebApp20
のプレフィックスを指定しています。
public void ConfigureServices(IServiceCollection services) { services.Configure<MySettings>(Configuration.GetSection("WebApp20")); services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication20", Version = "v1" }); }); }
動作確認のため、SQL Database の接続文字列を返す API を作ります。
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private readonly MySettings _settings; public ValuesController(IOptions<MySettings> optionsAccessor) { _settings = optionsAccessor.Value; } [HttpGet] public ActionResult<string> Get() { return Ok(_settings.SqlConnection); } }
ASP.NET Core アプリケーションをデプロイする Azure Web Apps の MSI を有効化し、Key Vault の Access policies を設定します。
$ az webapp identity assign --name "<Web Apps Name>" --resource-group "<Resource Group Name>" { "principalId": "xxx", "tenantId": "yyy", "type": "SystemAssigned", "userAssignedIdentities": null } $ az keyvault set-policy --name "<Key Vault Name>" --object-id "xxx" --secret-permissions get list
これで Web Apps 上の ASP.NET Core アプリケーションは、MSI で Key Vault に認証して SQL Database の接続文字列を取得できます。
Azure ポータルから設定する場合は、こちらの記事を参照してください。
gooner.hateblo.jp
Visual Studio の機能でローカル開発環境から Key Vault に接続することはできますが、環境によって上手く認証できなかったり、デバッグ実行が遅くなったりするので、今回は使いません。
ASP.NET Core の Secret Manger を使って、プログラマーが開発用の構成情報を管理してコードを書いていくようにします。
docs.microsoft.com
secrets.json ファイルには、このように SQL Database の接続文字列を定義します。
{ "WebApp20": { "SqlConnection": "SQL Connection for Secret Manager." } }
Visual Studio のプロジェクトを右クリックしたユーザーシークレットの管理から定義してもいいですが、アプリケーションのリポジトリとは別で管理する JSON ファイルを dotnet user-secrets コマンドで読み込ませるほうが便利です。
$ type .\webapp20-secrets.json | dotnet user-secrets set --project "C:\Users\thara\source\repos\WebApplication20\WebApplication20"
これでローカル環境では、secrets.json から取得した SQL Database の接続文字列を使って開発できます。
単体テストを実行する際には、テストプロジェクト内で MySettings クラスの モックを作り、SQL Database の接続文字列を渡すようにします。
public class ValuesControllerTest { [Fact] public void Get_ReturnsOkResult() { var settings = new MySettings() { SqlConnection = "SQL Connection for Unit Test." }; IOptions<MySettings> options = Options.Create(settings); var controller = new ValuesController(options); // Act var actionResult = controller.Get(); // Assert var result = Assert.IsType<OkObjectResult>(actionResult.Result); Assert.Equal(settings.SqlConnection, (result.Value as string[])[0]); } }
これでローカル開発でも CI/CD のパイプラインでも、実行環境の影響を受けずに単体テストを実行することができます。
現時点での ASP.NET Core アプリケーションにおける Azure Key Vault の使い方を改めて考えてみました。
アプリケーションの要件やチームの文化などにもよりますが、ベースはこの方針がいいかなと思っています。
セキュリティという観点では、Key Vault 自体を閉域網構成で管理したい話もあるので、そちらは追加で検討が必要です。
2021年7月1日付けで、Microsoft Most Valuable Professional (MVP) アワードを再受賞しました。受賞カテゴリは、Microsoft Azure です。
5 年目の受賞となり、青い 5 Years のリングが貰えたのでちょっと嬉しい。
新型コロナウイルスの影響により今までのようなオフラインの活動は難しくなり、JAZUG を中心としたコミュニティの運営や登壇はほとんどできませんでした。
初めてのオンライン開催となった de:code 2020 には MVP パーソナルスポンサーとして参加し、Azure Pipelines でデプロイする .NET Core 向けの YAML ファイルのサンプルを公開しました。
クラウドデベロッパーちゃんねるで、ちょまどさんと Azure Kubernetes Service のセッション動画を公開したりしました。
ブログでは、例年に比べると記事を多めに書きました。とくに Azure Synapse Analytics については、新たにノウハウを学んだ領域なのでアウトプットも多めです。
例年であれば、1年間の活動内容に対する審査が行われ、再受賞が決まります。
今年は世界中の MVP たちがコロナ禍におけるコミュニティ活動に苦労したことが配慮され、すべての MVP が再受賞ということになりました。
さっそく今月末に JAUGの 11 周年イベントがあるので、Azure Synapse Analytics のネタで LT する予定です。
jazug.connpass.com
コミュニティ運営としては、Azureもくもく会@新宿を 4 月からオンラインで再開しているので継続していきたいです。
参加した人が来てよかったなと思えるように、何かを1つでも持ち帰って貰えるような場にできるといいなと。
azure-mokumoku.connpass.com
あと、お仕事が関係しているところもありますが、企業コミュニティの Azure Council Experts(ACE)です。
会員企業の参加メリットを出しつつ、もっとオープンに活動していけるような運営を検討しているので、こちらもうまく軌道に乗せたいところです。
www.a-c-e.biz
正直なところ、コロナ禍でコミュニティ活動へのモチベーションが下がっていたので、今年は New Normal な活動スタイルを模索しつつ楽しんでいけたらと思います。