MSI を既存のアプリに後付けしようとしています。
元のアプリの DbContext は、web.config で同じ名前の ConnectionString を見つけたコンストラクターのみを使用していました。
DbConnectionFactory を使用して AccessToken を注入するように変更しました。
public class AppCoreDbContext : DbContext {
public AppCoreDbContext() : this("AppCoreDbContext")
{
}
public AppCoreDbContext(string connectionStringOrName) : base( OpenDbConnectionBuilder.Create(connectionStringOrName).Result, true)
{
}
...etc...
}
呼び出しているクラスは次のようになります。
public static class OpenDbConnectionBuilder
{
public static async Task<DbConnection> CreateAsync(string connectionStringName)
{
var connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
var dbConnection = DbProviderFactories
.GetFactory(connectionStringSettings.ProviderName)
.CreateConnection();
dbConnection.ConnectionString = connectionStringSettings.ConnectionString;
await AttachAccessTokenToDbConnection(dbConnection);
// Think DbContext will open it when first used.
//await dbConnection.OpenAsync();
return dbConnection;
}
static async Task AttachAccessTokenToDbConnection(IDbConnection dbConnection)
{
SqlConnection sqlConnection = dbConnection as SqlConnection;
if (sqlConnection == null)
{
return;
}
string msiEndpoint = Environment.GetEnvironmentVariable("MSI_ENDPOINT");
if (string.IsNullOrEmpty(msiEndpoint))
{
return;
}
var msiSecret = Environment.GetEnvironmentVariable("MSI_SECRET");
if (string.IsNullOrEmpty(msiSecret))
{
return;
}
string accessToken = await AppCoreDbContextMSITokenFactory.GetAzureSqlResourceTokenAsync();
sqlConnection.AccessToken = accessToken;
}
}
呼び出すもの
// Refer to: https://winterdom.com/2017/10/19/azure-sql-auth-with-msi
public static class AppCoreDbContextMSITokenFactory
{
private const String azureSqlResource = "https://database.windows.net/";
public static async Task<String> GetAzureSqlResourceTokenAsync()
{
var provider = new AzureServiceTokenProvider();
var result = await provider.GetAccessTokenAsync(azureSqlResource);
return result;
}
}
上記の結果は、デバッガーで追跡すると、
var result = await provider.GetAccessTokenAsync(azureSqlResource);
その後、永久にハングアップします。
注: 私は組織のドメインに参加していない個人のマシンで作業していますが、私の個人の MSAは組織のドメインに招待されています。
確かに、私は数年間開発を中断しており、ハングはおそらく await の周りで間違いを犯したことが原因です (暗黙のうちにそれを理解するのは常に大雑把でした)...しかし、それを理解しようとしている間、そしてドキュメントはかなりまばらです。上記が MSI を使用するための意図されたアプローチであったかどうかについてのフィードバックをいただければ幸いです。
不思議なんだけど:
- Azure にデプロイするときに、ARM に ID を作成するように指示できます。開発時に、ローカル マシンに MSI を使用するように指示するにはどうすればよいでしょうか?
- 開発マシンで接続文字列がローカル データベースに接続されている場合、とにかくトークンを作成して追加すると、トークンは無視されるか、例外が発生します。
- これは MSI について説明する範囲を少し超えていますが、DbContext 内で使用する dbConnection を作成したことはありません。接続を「所有」する DbContext の長所/短所を知っている人はいますか? dbcontextが閉じているときに接続を所有して閉じる方が賢明だと思います。
基本的に...これはすべて新しいので、これを機能させるためのアドバイスをいただければ幸いです。シークレットなしでデプロイできるというコンセプトは素晴らしく、このデモを機能させたいと思っています。
どうもありがとう!