EntityFramework 使用 MSI 的应用服务
App Service to EntityFramework using MSI
我正在尝试将 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...
}
它正在调用的 class 看起来像:
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 已 受邀加入组织域。
不可否认,我已经中断了几年的开发,挂起可能是由于在等待方面犯了一个错误(在隐含地理解这一点时总是很粗略)......但是在尝试弄清楚这一点,并且文档非常稀疏,希望得到关于以上是否是使用 MSI 的预期方法的反馈。
我在想:
- 部署到Azure时,我们可以告诉ARM创建Identity——开发时,我们如何告诉本地机器使用MSI?
- 如果在开发机器上连接字符串是到本地数据库的,而我创建并添加了令牌,它会忽略它,还是引发异常。
- 这有点超出了讨论 MSI 的范围,但我以前从未创建过要在 DbContext 中使用的 dbConnection。有谁知道 pros/cons 的 DbContext 'owning' 连接?我假设在 dbcontext 关闭时拥有并关闭连接会更明智。
基本上...这是全新的,因此非常感谢有关使它正常工作的任何建议——能够在没有秘密的情况下部署的概念将是 很棒的 并且真的会想让这个演示工作。
非常感谢!
你好 user9314395:托管服务标识仅适用于 Azure 上的资源 运行。虽然我们不支持本地开发方案,但您可以考虑使用以下(预览)库:https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication
我正在尝试将 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...
}
它正在调用的 class 看起来像:
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 已 受邀加入组织域。
不可否认,我已经中断了几年的开发,挂起可能是由于在等待方面犯了一个错误(在隐含地理解这一点时总是很粗略)......但是在尝试弄清楚这一点,并且文档非常稀疏,希望得到关于以上是否是使用 MSI 的预期方法的反馈。
我在想:
- 部署到Azure时,我们可以告诉ARM创建Identity——开发时,我们如何告诉本地机器使用MSI?
- 如果在开发机器上连接字符串是到本地数据库的,而我创建并添加了令牌,它会忽略它,还是引发异常。
- 这有点超出了讨论 MSI 的范围,但我以前从未创建过要在 DbContext 中使用的 dbConnection。有谁知道 pros/cons 的 DbContext 'owning' 连接?我假设在 dbcontext 关闭时拥有并关闭连接会更明智。
基本上...这是全新的,因此非常感谢有关使它正常工作的任何建议——能够在没有秘密的情况下部署的概念将是 很棒的 并且真的会想让这个演示工作。
非常感谢!
你好 user9314395:托管服务标识仅适用于 Azure 上的资源 运行。虽然我们不支持本地开发方案,但您可以考虑使用以下(预览)库:https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication