Может ли MSI работать с EF CodeFirst?

Я застрял на этом довольно долго, и мне не повезло, что я продвинулся сам.

Я пытаюсь подключиться из службы приложений Azure к управляемой базе данных EF CodeFirst с помощью токена MSI.

При развертывании службы приложений с использованием ARM я создал вывод, который обеспечил создание субъекта службы:

 {
  "principalId":"98f2c1f2-0a86-4ff1-92db-d43ec0edxxxx","
  tenantId":"e6d2d4cc-b762-486e-8894-4f5f440dxxxx",
  "type":"SystemAssigned"
 }

В Куду переменные среды показывают, что он устанавливается:

MSI_ENDPOINT = http://127.0.0.1:41239/MSI/token/
MSI_SECRET = 7C1B16Fxxxxxxxxxxxxx

Я предоставил на портале Azure строку подключения следующим образом:

Data Source=nzmoebase0000bt.database.windows.net;Initial Catalog=nzmoebase0001bt;Connect Timeout=300;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=300;

Я добавил принципала в базу данных в качестве владельца.

Note: I cannot do the same for the master db.

Токен добавляется в DbContext следующим образом:

Токен добавляется с помощью:

    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;
        }

        // To get around:
        // "Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string."
        var terms = new[] {"UserID","Password","PWD=","UID=" };
        string connectionString = dbConnection.ConnectionString;

        foreach (var term in terms)
        {
            if (connectionString.Contains(term, StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }
        }

        string accessToken = await AppCoreDbContextMSITokenFactory.GetAzureSqlResourceTokenAsync();
        sqlConnection.AccessToken = accessToken;
    }

При трассировке токен:

 .eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI....

Который декодировал с использованием jwt.io дал:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "FSimuFrFNoC0sJXGmv13nNZceDc",
  "kid": "FSimuFrFNoC0sJXGmv13nNZceDc"
}.{
  "aud": "https://database.windows.net/",
  "iss": "https://sts.windows.net/e6d2d4cc-b762-486e-8894-4f5f440dxxxx/",
  "iat": 1522783025,
  "nbf": 1522783025,
  "exp": 1522786925,
  "aio": "Y2NgYPjNdyJd9zrzpLavJSEzNIuPAAA=",
  "appid": "d1057cea-461b-4946-89a9-d76439c2xxxx",
  "appidacr": "2",
  "e_exp": 262800,
  "idp": "https://sts.windows.net/e6d2d4cc-b762-486e-8894-4f5f440dxxxx/",
  "oid": "98f2c1f2-0a86-4ff1-92db-d43ec0edxxxx",
  "sub": "98f2c1f2-0a86-4ff1-92db-d43ec0edxxxx",
  "tid": "e6d2d4cc-b762-486e-8894-4f5f440dxxxx",
  "uti": "59bqKWiSL0Gf0bTCI0AAAA",
  "ver": "1.0"
}.[Signature]

Я добавил Persist Security Info = True согласно нескольким рекомендациям в сети, но это не сделало ничего обнаружимого.

Data Source=nzmoebase0000bt.database.windows.net;Initial Catalog=nzmoebase0001bt;MultipleActiveResultSets=False;Persist Security Info = True;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

Я получаю ошибку:

[InvalidOperationException: This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection.]

Кто-нибудь получил соединение с базой данных, используя CodeFirst, с миграциями и MSI? В этот момент, после нескольких недель, когда я действительно застрял, я начинаю задумываться, возможно ли это.

Спасибо за любую помощь - даже если только доказательство того, что она может работать, для начала.

0 ответов

К сожалению, насколько мне известно, нет. Основной камень преткновения для проекта, который должен был использовать небезопасные строки подключения, загруженные с помощью имени / пароля.

Вы можете установить токен доступа для соединения SQL следующим образом:

  1. Установите Microsoft.Azure.Services.AppAuthentication пакет Nuget
  2. настройте свой контекстный класс следующим образом:

    public class MyDatabaseContext : DbContext
    {
        public MyDatabaseContext(DbContextOptions<MyDatabaseContext> options)
            : base(options)
        {
            // Get the db connection
            var connection = (SqlConnection)Database.GetDbConnection();
    
            // Add the access token
            connection.AccessToken = new AzureServiceTokenProvider()
                .GetAccessTokenAsync("https://database.windows.net/")
                .ConfigureAwait(false).GetAwaiter().GetResult();
        }
    
        public DbSet<MyTable> MyTable { get; set; }
    }
    
Другие вопросы по тегам