ハマった
サーバーアプリ開発でかなりハマりました。
開発環境で実行できていた、データベースとアプリケーションの接続が、Azure上でうまくできずに悪戦苦闘。
Azure SQL Serverには当然ながらファイヤーウォールが敷かれているのですが、開発環境用に設定していたIPではアクセスできるのですが、公共LAN等ではアクセス不可でアプリが止まってしまいます。
しかも依頼者の前でそれをやって、アプリが動いていた家に連れていくというね。
依頼者を家に帰した後、色々調べた結果、Azure上に仮想のMicrosoft Entra認証プロバイダー(マネージドID)を用意して、アプリにログインしてくるユーザーの代わりにApp Service→SQL Databaseへの認証を行う方法が解決につながりました。
要するに今まではアプリにログインするユーザーがSQL Databaseの認証に蹴られていたのを、アプリに設定されたマネージドIDに認証してもらうという形態にするイメージですね。
環境
デプロイ:Azure App Service
アプリ開発:ASP.Net Core Blazor
認証:Azure AD B2C
SQL:Azure SQL Server
やったこと
大体このチュートリアル通りにやればできる。
色々注意点もあるので、下記にまとめていきます。
マネージドIDの前に、Microsoft EntraユーザーをSQL Serverに認証させる
自動生成されたIDの前に、実在するユーザーをSQL ServerにEntraユーザーとして認証させます。
チュートリアルではAzure CLIでのやり方が書かれていますが、Azureポータルで、Entra IDを登録してから、SQL Server Management Studioなどを使ってクエリを投げても大丈夫。
この時はCLIが怖かったので、僕はそうしました。
マネージドIDの作成
- Azure検索窓に「マネージドID」と入力。
- マネージドID を「作成」から、任意のサブスクリプションとリソースグループを選ぶ。
- 「リージョン」と「名前」を入力して「確認と作成」
App Serviceに作成したマネージドIDを登録
- 「App Service」→「作成アプリ」に移動
- 「設定」→「ID」→「ユーザー割り当て済み」を選択
- 「追加」で作成したマネージドIDの名前を入力して検索して登録。
Azure Cloud Shellの登場
ここでいよいよAzure CLIを使います。まあ単なるAzure上で動くBashなんですけど、Azure PortalのUIに慣らされ切っていたので、渋々有効化して使いました。
チュートリアルが用意されていたので、それを見るといいと思うよ。
Azure CLIに色々インストールしてから、下記を実行します。
これによって、データベースに接続するアプリに紐づいたマネージドIDが、SQL Serverに対して、Entra IDと同様に操作が可能になります。
az webapp connection create sql
--resource-group <group-name> #リソースグループ名
--name <server-name> #アプリ名(マネージドIDが登録されている)
--target-resource-group <sql-group-name> #SQLのリソースグループ名(最初のリソースと一緒かもね)
--server <sql-name> #SQL Server名(マネージドIDを登録したい)
--database <database-name> #データベース名
--user-identity client-id=<client-id> subs-id=<subscription-id> #マネージドIDのclient id とサブスクリプション名
--client-type <client-type> #dotnetと入力(optionの先頭だったから。。脳死)
コードの修正
チュートリアルから外れますが、EF Coreを使いたい場合、program.csにこんな感じの記述を追加します。
// Azure SQL Database への接続を構成
string connectionString =
Environment.GetEnvironmentVariable("AZURE_SQL_CONNECTIONSTRING")!;
// DbContext の登録
builder.Services.AddDbContext<TestContext>(options =>
options.UseSqlServer(connectionString));
appsettings.jsonに入力してある文字列は消してもオッケーです。
余談
マネージドIDとかEntra IDとか
パルスのファルシのルシがコクーンでパージ並みに意味不明な単語が出てきますが、一つ一つ意味を抑えれば大丈夫なはず。多分。
余談1:マネージドIDって何?
ChatGPT 4o により生成
AzureにおけるマネージドIDとは、AzureリソースがAzure Active Directory (Azure AD) を利用して他のAzureサービスに安全にアクセスするための自動管理されたIDです。これにより、開発者はコード内に資格情報(ユーザー名やパスワード)を直接埋め込む必要がなくなり、セキュリティが向上します。
マネージドIDには以下の2種類があります:
- システム割り当てマネージドID:特定のAzureリソース(例:仮想マシン)に直接関連付けられ、そのリソースのライフサイクルと共に作成および削除されます。
- ユーザー割り当てマネージドID:スタンドアロンのAzureリソースとして作成され、複数のAzureリソースで共有して使用できます。これらのIDは独立したライフサイクルを持ち、明示的に管理されます。
マネージドIDを使用することで、AzureリソースはAzure AD認証をサポートする他のサービス(例:Azure Key Vault、Azure Storage)に対して、資格情報をコードに含めずに認証およびアクセスが可能となります。
これにより、資格情報の管理負担が軽減され、セキュリティリスクが低減されます。
余談2:Azure Entra 認証ユーザーとの違い
ChatGPT 4o により生成
- 管理: Entra認証ユーザーは人が管理し、マネージドIDはAzureリソースによって自動的に管理されます。
- 利用者: Entra認証ユーザーは人間のユーザーに使用され、マネージドIDはアプリケーションやサービスに使用されます。
- アクセスの方法: Entra認証ユーザーは、ログインと認証を通じてリソースにアクセスしますが、マネージドIDはバックエンドでリソースへのアクセスを許可するために使用され、資格情報の管理が不要です。
まとめ
今回やったことをまとめると、
AzureのEntra認証ユーザーをSQL ServerにCREATEしてALTER権限を付与。
サブスクリプションのリソースグループにマネージドIDを作成し、App Serviceにユーザー割り当てマネージドIDとして登録。
Azure CLIコマンドを使ってマネージドIDをSQL Serverに割り当て、生成された環境変数をアプリが読めるようにすることで、シークレット無しでApp ServiceからSQL Databaseに認証可能になる。
ということです。
パルスのファルシのルシがコクーンでパージ