使用MSI的App服务到EntityFramework

时间:2018-03-28 10:11:13

标签: azure-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...
}

它正在调用的类看起来像:

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创建身份 - 在开发时,我们如何告诉本地计算机使用MSI?
  • 如果在开发机器上连接字符串是本地数据库,我仍然创建并添加令牌,它会忽略它,或者引发异常。
  • 这有点超出讨论MSI的范围,但我从未创建过在DbContext中使用的dbConnection。有没有人知道DbContext拥有&#39;的优点/缺点?连接?我 关闭dbcontext时关闭连接。

基本上......这是全新的,所以不胜感激任何有关实现这一点的建议 - 无需秘密即可部署的概念将是 awesome 并且非常希望得到这个演示工作

非常感谢!

1 个答案:

答案 0 :(得分:0)

Hello user9314395:托管服务标识仅适用于在Azure上运行的资源。虽然我们不支持本地开发方案,但您可以考虑使用以下(预览)库:https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication