Аутентификация ManagedIdentityCredential недоступна при запуске из Visual Studio

Недавно я настроил нашу службу приложений Azure и Azure SQL Server для использования управляемого доступа к удостоверениям. Службе приложений назначено управляемое удостоверение, назначенное системой, и назначена правильная роль владельца базы данных SQL. Когда я публикую свой код в службе приложений, он отлично работает и может получить доступ к базе данных.

Моя проблема в том, что я не могу подключиться к базе данных через свое приложение при локальном запуске через Visual Studio. Моя учетная запись Azure настроена как администратор Azure Active Directory на SQL Server, и я могу открывать подключение и выполнять запросы через Azure Data Studio после входа в систему.

Я использую ту же учетную запись через Visual Studio, даже отсоединил и снова связал ее в меню «Инструменты» -> «Параметры» -> «Аутентификация службы Azure/выбор учетной записи». Но когда я пытаюсь запустить приложение локально, я получаю сообщение об ошибке ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint. Ошибка не дает мне много работы, потому что я не уверен, как увидеть полное представление о том, что пытается пройти аутентификацию. Я не использую какой-либо код на своей стороне для получения токена доступа, поскольку я просто позволяю Microsoft SQLClient получить его для меня через строку подключения.

Вот полная трассировка стека ошибки, все, что может указать мне правильное направление, будет оценено. Я предполагаю, что это как-то связано с тем, что Visual Studios, вероятно, нужно разрешить получить токен доступа от моего имени, но я подумал, что, поскольку я вошел в свою учетную запись Azure, это может не иметь значения.

   at Microsoft.Data.ProviderBase.DbConnectionPool.CheckPoolBlockingPeriod(Exception e)
   at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)

Azure.RequestFailedException: A socket operation was attempted to an unreachable network. (169.254.169.254:80)
 ---> System.Net.Http.HttpRequestException: A socket operation was attempted to an unreachable network. (169.254.169.254:80)
 ---> System.Net.Sockets.SocketException (10051): A socket operation was attempted to an unreachable network.
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
   at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|277_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Azure.Core.Pipeline.HttpClientTransport.ProcessAsync(HttpMessage message, Boolean async)
   --- End of inner exception stack trace ---
   at Azure.Core.Pipeline.HttpClientTransport.ProcessAsync(HttpMessage message, Boolean async)
   at Azure.Core.Pipeline.HttpPipelineTransportPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.RequestActivityPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)

   at Azure.Identity.ImdsManagedIdentitySource.<AuthenticateAsync>d__15.MoveNext()
   at Azure.Identity.ManagedIdentityClient.<AuthenticateCoreAsync>d__17.MoveNext()
   at Azure.Identity.ManagedIdentityClient.<AppTokenProviderImpl>d__18.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<SendTokenRequestToProviderAsync>d__4.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<FetchNewAccessTokenAsync>d__3.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<ExecuteAsync>d__2.MoveNext()
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__12.MoveNext()
   at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.<ExecuteAsync>d__3.MoveNext()
   at Azure.Identity.AbstractAcquireTokenParameterBuilderExtensions.<ExecuteAsync>d__0`1.MoveNext()
   at Azure.Identity.MsalConfidentialClient.<AcquireTokenForClientCoreAsync>d__21.MoveNext()
   at Azure.Identity.MsalConfidentialClient.<AcquireTokenForClientAsync>d__20.MoveNext()
   at Azure.Identity.ManagedIdentityClient.<AuthenticateAsync>d__16.MoveNext()
   at Azure.Identity.ManagedIdentityCredential.<GetTokenImplAsync>d__16.MoveNext()
   at 


Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex, String additionalMessage)
   at Azure.Identity.ManagedIdentityCredential.<GetTokenImplAsync>d__16.MoveNext()
   at Azure.Identity.ManagedIdentityCredential.<GetTokenAsync>d__14.MoveNext()
   at Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProvider.<AcquireTokenAsync>d__17.MoveNext()
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.<>c__DisplayClass147_1.<<GetFedAuthToken>b__1>d.MoveNext()
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.GetFedAuthToken(SqlFedAuthInfo fedAuthInfo)

Соответствующая информация о соединении DbContext. В настоящее время используется версия 7.0.3 Microsoft.EntityFrameworkCore для класса DbContext.

    public class DbEntities: DbContext
    {
        public DbEntities() : base() { }
        //All DbSet<...> classes here
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("DB_CONNECTION_STRING"));
        }
    }

Соответствующий JSON-файл AppSettings

{
  "ConnectionStrings": {
    "DB_CONNECTION_STRING": "Server=tcp:MY-SERVER.database.windows.net;Initial Catalog=development;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication=\"Active Directory Managed Identity\";"
  },
}

Итак, чего вы хотите достичь? Хотите подключить azure sql к своему приложению локально или хотите аутентифицировать свое приложение? Кроме того, ему также необходимо знать, что вы пытаетесь реализовать, и вашу конфигурацию помимо трассировки стека.

Md Farid Uddin Kiron 16.02.2023 03:58

@MdFaridUddinKiron Полагаю, я хочу, чтобы поведение было таким же, как если бы приложение было развернуто. Так что прямо сейчас мне просто нужно подключиться к базе данных через локальное приложение. Это существующее приложение, которое я обновляю для работы с управляемой идентификацией. В настоящее время используется DbContext, предоставляемый в версии 7.0.3 пакета Microsoft.EntityFrameworkCore. Я добавил соответствующую информацию о подключении в свой исходный пост.

Dillon Drobena 16.02.2023 16:24

Попробуйте войти в нужную учетную запись с помощью Azure CLI (az login). Хотя я не уверен, что это сработает именно для этой строки подключения. Вам может понадобиться Active Directory Default для аутентификации.

Alex AIT 16.02.2023 16:31

@MdFaridUddinKiron По сути, я пытаюсь ответить на вопрос, почему я могу открыть соединение с базой данных через Azure Data Studio, но не через свое локальное приложение в Visual Studios, когда моя учетная запись Microsoft подключена к обоим.

Dillon Drobena 16.02.2023 16:31

Вход @AlexAIT с помощью azure cli не имел значения. Все еще получаю те же ошибки. Попробую Active Directory Default и посмотрим, изменит ли это что-нибудь

Dillon Drobena 16.02.2023 16:49

@AlexAIT Хорошо, изменение строки подключения для использования Active Directory Default вместо Active Directory Managed Identity, похоже, позволяет ему работать как в localhost, так и в моей службе приложений Azure. Не знаю, почему... но я возьму это.

Dillon Drobena 16.02.2023 16:58

Круто, я разместил это как ответ, включая некоторую дополнительную информацию.

Alex AIT 16.02.2023 17:08
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
7
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

https://learn.microsoft.com/en-us/sql/connect/ado-net/sql/azure-active-directory-authentication?view=sql-server-ver16

Используя Authentication=\"Active Directory Managed Identity\", вы укажете своему приложению использовать только управляемую аутентификацию. Это можно использовать только в том случае, если вы действительно работаете в качестве ресурса Azure. Вы не можете использовать аутентификацию Managed Identity с вашей личной учетной записью.

Используя Active Directory Default в качестве значения, система попробует несколько вариантов:

Выполняйте аутентификацию с помощью удостоверения Azure AD, используя неинтерактивные механизмы без пароля, включая управляемые удостоверения, Visual Studio Code, Visual Studio, Azure CLI и т. д.

Другие вопросы по теме