From 2a161917ec1c58ac5650fed625ff963e4284878e Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 24 Mar 2021 23:28:01 -0700 Subject: [PATCH 1/9] Feature | Azure Identity support - Phase 1 changes --- .../SqlAuthenticationParameters.xml | 7 +- .../src/Microsoft.Data.SqlClient.csproj | 4 +- ...uthenticationProviderManager.NetCoreApp.cs | 5 +- ...thenticationProviderManager.NetStandard.cs | 8 +- .../SqlClient/SqlInternalConnectionTds.cs | 3 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 8 +- .../SqlAuthenticationProviderManager.cs | 5 +- .../SqlClient/SqlInternalConnectionTds.cs | 3 +- .../ActiveDirectoryAuthenticationProvider.cs | 101 ++++--- ...reManagedIdentityAuthenticationProvider.cs | 248 ------------------ .../SqlClient/SqlAuthenticationParameters.cs | 21 +- tools/props/Versions.props | 1 + tools/specs/Microsoft.Data.SqlClient.nuspec | 5 + 13 files changed, 107 insertions(+), 312 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml index 520882eb93..ec6695297d 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml @@ -12,7 +12,8 @@ The user login name/ID. The user password. The connection ID. - Initializes a new instance of the class using the specified authentication method, server name, database name, resource URI, authority URI, user login name/ID, user password and connection ID. + The connection timeout value in milliseconds. + Initializes a new instance of the class using the specified authentication method, server name, database name, resource URI, authority URI, user login name/ID, user password, connection ID and connection timeout value. Gets the authentication method. @@ -46,5 +47,9 @@ Gets the database name. The database name. + + Gets the connection timeout value. + The connection timeout value to be passed to Cancellation Token Source. + diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index dc051a033e..3b929aab71 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -84,9 +84,6 @@ Microsoft\Data\SqlClient\ActiveDirectoryAuthenticationProvider.cs - - Microsoft\Data\SqlClient\AzureManagedIdentityAuthenticationProvider.cs - Microsoft\Data\SqlClient\LocalAppContextSwitches.cs @@ -829,6 +826,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs index bf44f23184..ad76c371ed 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs @@ -15,7 +15,6 @@ internal partial class SqlAuthenticationProviderManager static SqlAuthenticationProviderManager() { - var azureManagedIdentityAuthenticationProvider = new AzureManagedIdentityAuthenticationProvider(); SqlAuthenticationProviderConfigurationSection configurationSection = null; try @@ -41,8 +40,8 @@ static SqlAuthenticationProviderManager() Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, azureManagedIdentityAuthenticationProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, azureManagedIdentityAuthenticationProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs index 71b8b23269..7bb4b28bdb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs @@ -7,9 +7,7 @@ namespace Microsoft.Data.SqlClient internal partial class SqlAuthenticationProviderManager { static SqlAuthenticationProviderManager() - { - var azureManagedIdentityAuthenticationProvider = new AzureManagedIdentityAuthenticationProvider(); - + { Instance = new SqlAuthenticationProviderManager(); var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); @@ -17,8 +15,8 @@ static SqlAuthenticationProviderManager() Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, azureManagedIdentityAuthenticationProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, azureManagedIdentityAuthenticationProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index f94f257e34..100c41290c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -2324,7 +2324,8 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) authority: fedAuthInfo.stsurl, serverName: ConnectionOptions.DataSource, databaseName: ConnectionOptions.InitialCatalog) - .WithConnectionId(_clientConnectionId); + .WithConnectionId(_clientConnectionId) + .WithConnectionTimeout(ConnectionOptions.ConnectTimeout * 1000); switch (ConnectionOptions.Authentication) { case SqlAuthenticationMethod.ActiveDirectoryIntegrated: diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 58e0037059..927d3a693a 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -145,9 +145,6 @@ Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs - - Microsoft\Data\SqlClient\AzureManagedIdentityAuthenticationProvider.cs - Microsoft\Data\SqlClient\EnclaveDelegate.cs @@ -571,6 +568,9 @@ All runtime; build; native; contentfiles; analyzers; buildtransitive + + $(AzureIdentityVersion) + $(MicrosoftIdentityClientVersion) @@ -592,4 +592,4 @@ - + \ No newline at end of file diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index 0280954005..561c0cd101 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -25,7 +25,6 @@ internal class SqlAuthenticationProviderManager static SqlAuthenticationProviderManager() { - var azureManagedIdentityAuthenticationProvider = new AzureManagedIdentityAuthenticationProvider(); SqlAuthenticationProviderConfigurationSection configurationSection = null; try { @@ -50,8 +49,8 @@ static SqlAuthenticationProviderManager() Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, azureManagedIdentityAuthenticationProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, azureManagedIdentityAuthenticationProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); } public static readonly SqlAuthenticationProviderManager Instance; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 381a87036e..4c79b037ba 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -2771,7 +2771,8 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) authority: fedAuthInfo.stsurl, serverName: ConnectionOptions.DataSource, databaseName: ConnectionOptions.InitialCatalog) - .WithConnectionId(_clientConnectionId); + .WithConnectionId(_clientConnectionId) + .WithConnectionTimeout(ConnectionOptions.ConnectTimeout * 1000); switch (ConnectionOptions.Authentication) { case SqlAuthenticationMethod.ActiveDirectoryIntegrated: diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs index 29500ef5b4..342e834697 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -8,6 +8,8 @@ using System.Security; using System.Threading; using System.Threading.Tasks; +using Azure.Core; +using Azure.Identity; using Microsoft.Identity.Client; using Microsoft.Identity.Client.Extensibility; @@ -69,7 +71,9 @@ public override bool IsSupported(SqlAuthenticationMethod authentication) || authentication == SqlAuthenticationMethod.ActiveDirectoryPassword || authentication == SqlAuthenticationMethod.ActiveDirectoryInteractive || authentication == SqlAuthenticationMethod.ActiveDirectoryServicePrincipal - || authentication == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow; + || authentication == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow + || authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity + || authentication == SqlAuthenticationMethod.ActiveDirectoryMSI; } /// @@ -99,24 +103,37 @@ public override void BeforeUnload(SqlAuthenticationMethod authentication) #endif /// - public override Task AcquireTokenAsync(SqlAuthenticationParameters parameters) => Task.Run(async () => + public override async Task AcquireTokenAsync(SqlAuthenticationParameters parameters) { - AuthenticationResult result; + CancellationTokenSource cts = new CancellationTokenSource(); + + // Use Connection timeout value to cancel token acquire request after certain period of time. + cts.CancelAfter(parameters.TimeoutInMilliseconds); + string scope = parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix; string[] scopes = new string[] { scope }; + int seperatorIndex = parameters.Authority.LastIndexOf('/'); + string tenantId = parameters.Authority.Substring(seperatorIndex + 1); + string authority = parameters.Authority.Remove(seperatorIndex + 1); + + TokenCredentialOptions tokenCredentialOptions = new TokenCredentialOptions() { AuthorityHost = new Uri(authority) }; + TokenRequestContext tokenRequestContext = new TokenRequestContext(scopes); + + if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity || parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryMSI) + { + string clientId = string.IsNullOrWhiteSpace(parameters.UserId) ? null : parameters.UserId; + AccessToken accessToken = await new ManagedIdentityCredential(clientId, tokenCredentialOptions).GetTokenAsync(tokenRequestContext, cts.Token); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Managed Identity auth mode. Expiry Time: {0}", accessToken.ExpiresOn); + return new SqlAuthenticationToken(accessToken.Token, accessToken.ExpiresOn); + } + + AuthenticationResult result; if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryServicePrincipal) { - IConfidentialClientApplication ccApp = ConfidentialClientApplicationBuilder.Create(parameters.UserId) - .WithAuthority(parameters.Authority) - .WithClientSecret(parameters.Password) - .WithClientName(Common.DbConnectionStringDefaults.ApplicationName) - .WithClientVersion(Common.ADP.GetAssemblyVersion().ToString()) - .Build(); - - result = ccApp.AcquireTokenForClient(scopes).ExecuteAsync().Result; - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Service Principal auth mode. Expiry Time: {0}", result.ExpiresOn); - return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); + AccessToken accessToken = await new ClientSecretCredential(tenantId, parameters.UserId, parameters.Password, tokenCredentialOptions).GetTokenAsync(tokenRequestContext, cts.Token); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Service Principal auth mode. Expiry Time: {0}", accessToken.ExpiresOn); + return new SqlAuthenticationToken(accessToken.Token, accessToken.ExpiresOn); } /* @@ -149,16 +166,16 @@ public override Task AcquireTokenAsync(SqlAuthentication { if (!string.IsNullOrEmpty(parameters.UserId)) { - result = app.AcquireTokenByIntegratedWindowsAuth(scopes) + result = await app.AcquireTokenByIntegratedWindowsAuth(scopes) .WithCorrelationId(parameters.ConnectionId) .WithUsername(parameters.UserId) - .ExecuteAsync().Result; + .ExecuteAsync(cancellationToken: cts.Token); } else { - result = app.AcquireTokenByIntegratedWindowsAuth(scopes) + result = await app.AcquireTokenByIntegratedWindowsAuth(scopes) .WithCorrelationId(parameters.ConnectionId) - .ExecuteAsync().Result; + .ExecuteAsync(cancellationToken: cts.Token); } SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Integrated auth mode. Expiry Time: {0}", result.ExpiresOn); } @@ -168,9 +185,10 @@ public override Task AcquireTokenAsync(SqlAuthentication foreach (char c in parameters.Password) password.AppendChar(c); password.MakeReadOnly(); - result = app.AcquireTokenByUsernamePassword(scopes, parameters.UserId, password) + + result = await app.AcquireTokenByUsernamePassword(scopes, parameters.UserId, password) .WithCorrelationId(parameters.ConnectionId) - .ExecuteAsync().Result; + .ExecuteAsync(cancellationToken: cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Password auth mode. Expiry Time: {0}", result.ExpiresOn); } else if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryInteractive || @@ -194,7 +212,7 @@ public override Task AcquireTokenAsync(SqlAuthentication { // If 'account' is available in 'app', we use the same to acquire token silently. // Read More on API docs: https://docs.microsoft.com/dotnet/api/microsoft.identity.client.clientapplicationbase.acquiretokensilent - result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(); + result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken: cts.Token); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (silent) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); } catch (MsalUiRequiredException) @@ -202,14 +220,14 @@ public override Task AcquireTokenAsync(SqlAuthentication // An 'MsalUiRequiredException' is thrown in the case where an interaction is required with the end user of the application, // for instance, if no refresh token was in the cache, or the user needs to consent, or re-sign-in (for instance if the password expired), // or the user needs to perform two factor authentication. - result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod); + result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod, cts); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); } } else { // If no existing 'account' is found, we request user to sign in interactively. - result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod); + result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod, cts); SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); } } @@ -220,36 +238,35 @@ public override Task AcquireTokenAsync(SqlAuthentication } return new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn); - }); - + } private async Task AcquireTokenInteractiveDeviceFlowAsync(IPublicClientApplication app, string[] scopes, Guid connectionId, string userId, - SqlAuthenticationMethod authenticationMethod) + SqlAuthenticationMethod authenticationMethod, CancellationTokenSource cts) { - CancellationTokenSource cts = new CancellationTokenSource(); -#if NETCOREAPP - /* - * On .NET Core, MSAL will start the system browser as a separate process. MSAL does not have control over this browser, - * but once the user finishes authentication, the web page is redirected in such a way that MSAL can intercept the Uri. - * MSAL cannot detect if the user navigates away or simply closes the browser. Apps using this technique are encouraged - * to define a timeout (via CancellationToken). We recommend a timeout of at least a few minutes, to take into account - * cases where the user is prompted to change password or perform 2FA. - * - * https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core#system-browser-experience - */ - cts.CancelAfter(180000); -#endif try { if (authenticationMethod == SqlAuthenticationMethod.ActiveDirectoryInteractive) { + CancellationTokenSource ctsInteractive = new CancellationTokenSource(); +#if NETCOREAPP + /* + * On .NET Core, MSAL will start the system browser as a separate process. MSAL does not have control over this browser, + * but once the user finishes authentication, the web page is redirected in such a way that MSAL can intercept the Uri. + * MSAL cannot detect if the user navigates away or simply closes the browser. Apps using this technique are encouraged + * to define a timeout (via CancellationToken). We recommend a timeout of at least a few minutes, to take into account + * cases where the user is prompted to change password or perform 2FA. + * + * https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core#system-browser-experience + */ + ctsInteractive.CancelAfter(180000); +#endif if (_customWebUI != null) { return await app.AcquireTokenInteractive(scopes) .WithCorrelationId(connectionId) .WithCustomWebUi(_customWebUI) .WithLoginHint(userId) - .ExecuteAsync(cts.Token); + .ExecuteAsync(ctsInteractive.Token); } else { @@ -273,13 +290,15 @@ private async Task AcquireTokenInteractiveDeviceFlowAsync( return await app.AcquireTokenInteractive(scopes) .WithCorrelationId(connectionId) .WithLoginHint(userId) - .ExecuteAsync(cts.Token); + .ExecuteAsync(ctsInteractive.Token); } } else { AuthenticationResult result = await app.AcquireTokenWithDeviceCode(scopes, - deviceCodeResult => _deviceCodeFlowCallback(deviceCodeResult)).ExecuteAsync(); + deviceCodeResult => _deviceCodeFlowCallback(deviceCodeResult)) + .WithCorrelationId(connectionId) + .ExecuteAsync(cancellationToken: cts.Token); return result; } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs deleted file mode 100644 index 6f543d909e..0000000000 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AzureManagedIdentityAuthenticationProvider.cs +++ /dev/null @@ -1,248 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Data.SqlClient -{ - internal sealed class AzureManagedIdentityAuthenticationProvider : SqlAuthenticationProvider - { - // HttpClient is intended to be instantiated once and re-used throughout the life of an application. -#if NETFRAMEWORK - private static readonly HttpClient s_httpClient = new HttpClient(); -#else - private static readonly HttpClient s_httpClient = new HttpClient(new HttpClientHandler() { CheckCertificateRevocationList = true }); -#endif - - private const string AzureSystemApiVersion = "&api-version=2019-08-01"; - private const string AzureVmImdsApiVersion = "&api-version=2018-02-01"; - private const string AccessToken = "access_token"; - private const string Expiry = "expires_on"; - private const int FileTimeLength = 10; - - private const int DefaultRetryTimeout = 0; - private const int DefaultMaxRetryCount = 5; - - // Azure Instance Metadata Service (IMDS) endpoint - private const string AzureVmImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token"; - - // Timeout for Azure IMDS probe request - internal const int AzureVmImdsProbeTimeoutInSeconds = 2; - internal readonly TimeSpan _azureVmImdsProbeTimeout = TimeSpan.FromSeconds(AzureVmImdsProbeTimeoutInSeconds); - - // Configurable timeout for MSI retry logic - internal readonly int _retryTimeoutInSeconds = DefaultRetryTimeout; - internal readonly int _maxRetryCount = DefaultMaxRetryCount; - - // Reference: https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http - public override async Task AcquireTokenAsync(SqlAuthenticationParameters parameters) - { - HttpClient httpClient = s_httpClient; - - try - { - // Check if App Services MSI is available. If both these environment variables are set, then it is. - string msiEndpoint = Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT"); - string msiHeader = Environment.GetEnvironmentVariable("IDENTITY_HEADER"); - - var isAppServicesMsiAvailable = !string.IsNullOrWhiteSpace(msiEndpoint) && !string.IsNullOrWhiteSpace(msiHeader); - - // if App Service MSI is not available then Azure VM IMDS may be available, test with a probe request - if (!isAppServicesMsiAvailable) - { - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | This environment is not identified as an Azure App Service environment. Proceeding to validate Azure VM IMDS endpoint availability."); - using (var internalTokenSource = new CancellationTokenSource()) - using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(internalTokenSource.Token, default)) - { - HttpRequestMessage imdsProbeRequest = new HttpRequestMessage(HttpMethod.Get, AzureVmImdsEndpoint); - - try - { - internalTokenSource.CancelAfter(_azureVmImdsProbeTimeout); - await httpClient.SendAsync(imdsProbeRequest, linkedTokenSource.Token).ConfigureAwait(false); - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | The Instance Metadata Service (IMDS) service endpoint is accessible. Proceeding to acquire access token."); - } - catch (OperationCanceledException) - { - // request to IMDS timed out (internal cancellation token canceled), neither Azure VM IMDS nor App Services MSI are available - if (internalTokenSource.Token.IsCancellationRequested) - { - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | The Instance Metadata Service (IMDS) service endpoint is not accessible."); - // Throw error: Tried to get token using Managed Identity. Unable to connect to the Instance Metadata Service (IMDS). Skipping request to the Managed Service Identity (MSI) token endpoint. - throw SQL.Azure_ManagedIdentityException($"{Strings.Azure_ManagedIdentityUsed} {Strings.Azure_MetadataEndpointNotListening}"); - } - - throw; - } - } - } - else - { - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | This environment is identified as an Azure App Service environment. Proceeding to acquire access token from Endpoint URL: {0}", msiEndpoint); - } - - string objectIdParameter = string.Empty; - - // If user assigned managed identity is specified, include object ID parameter in request - if (!string.IsNullOrWhiteSpace(parameters.UserId)) - { - objectIdParameter = $"&object_id={Uri.EscapeDataString(parameters.UserId)}"; - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Identity Object id received and will be used for acquiring access token {0}", parameters.UserId); - } - - // Craft request as per the MSI protocol - var requestUrl = isAppServicesMsiAvailable - ? $"{msiEndpoint}?resource={parameters.Resource}{objectIdParameter}{AzureSystemApiVersion}" - : $"{AzureVmImdsEndpoint}?resource={parameters.Resource}{objectIdParameter}{AzureVmImdsApiVersion}"; - - HttpResponseMessage response = null; - - try - { - response = await httpClient.SendAsyncWithRetry(getRequestMessage, _retryTimeoutInSeconds, _maxRetryCount, default).ConfigureAwait(false); - HttpRequestMessage getRequestMessage() - { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); - - if (isAppServicesMsiAvailable) - { - request.Headers.Add("X-IDENTITY-HEADER", msiHeader); - } - else - { - request.Headers.Add("Metadata", "true"); - } - - return request; - } - } - catch (HttpRequestException) - { - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Failed after 5 retries. Unable to connect to the Managed Service Identity (MSI) endpoint."); - // Throw error: Tried to get token using Managed Service Identity. Failed after 5 retries. Unable to connect to the Managed Service Identity (MSI) endpoint. Please check that you are running on an Azure resource that has MSI setup. - throw SQL.Azure_ManagedIdentityException($"{Strings.Azure_ManagedIdentityUsed} {Strings.Azure_RetryFailure} {Strings.Azure_IdentityEndpointNotListening}"); - } - - // If the response is successful, it should have JSON response with an access_token field - if (response.IsSuccessStatusCode) - { - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Successful response received. Status Code {0}", response.StatusCode); - string jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - int accessTokenStartIndex = jsonResponse.IndexOf(AccessToken) + AccessToken.Length + 3; - var imdsAccessToken = jsonResponse.Substring(accessTokenStartIndex, jsonResponse.IndexOf('"', accessTokenStartIndex) - accessTokenStartIndex); - var expiresin = jsonResponse.Substring(jsonResponse.IndexOf(Expiry) + Expiry.Length + 3, FileTimeLength); - DateTime expiryTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(long.Parse(expiresin)); - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Access Token received. Expiry Time: {0}", expiryTime); - return new SqlAuthenticationToken(imdsAccessToken, expiryTime); - } - - // RetryFailure : Failed after 5 retries. - // NonRetryableError : Received a non-retryable error. - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Request to acquire access token failed with status code {0}", response.StatusCode); - string errorStatusDetail = response.IsRetryableStatusCode() - ? Strings.Azure_RetryFailure - : Strings.Azure_NonRetryableError; - - string errorText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Error occurred while acquiring access token: {0} Identity Response Code: {1}, Response: {2}", errorStatusDetail, response.StatusCode, errorText); - throw SQL.Azure_ManagedIdentityException($"{errorStatusDetail} Identity Response Code: {response.StatusCode}, Response: {errorText}"); - } - catch (Exception exp) - { - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Error occurred while acquiring access token: {0}", exp.Message); - if (exp is SqlException) - throw; - // Throw error: Access token could not be acquired. {exp.Message} - throw SQL.Azure_ManagedIdentityException($"{Strings.Azure_ManagedIdentityUsed} {Strings.Azure_GenericErrorMessage} {exp.Message}"); - } - } - - public override bool IsSupported(SqlAuthenticationMethod authentication) - { - return authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity - || authentication == SqlAuthenticationMethod.ActiveDirectoryMSI; - } - } - - #region IMDS Retry Helper - internal static class SqlManagedIdentityRetryHelper - { - internal const int DeltaBackOffInSeconds = 2; - internal const string RetryTimeoutError = "Reached retry timeout limit set by MsiRetryTimeout parameter in connection string."; - - internal static bool IsRetryableStatusCode(this HttpResponseMessage response) - { - // 404 NotFound, 429 TooManyRequests, and 5XX server error status codes are retryable - return Regex.IsMatch(((int)response.StatusCode).ToString(), @"404|429|5\d{2}"); - } - - /// - /// Implements recommended retry guidance here: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#retry-guidance - /// - internal static async Task SendAsyncWithRetry(this HttpClient httpClient, Func getRequest, int retryTimeoutInSeconds, int maxRetryCount, CancellationToken cancellationToken) - { - using (var timeoutTokenSource = new CancellationTokenSource()) - using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, cancellationToken)) - { - try - { - // if retry timeout is configured, configure cancellation after timeout period elapses - if (retryTimeoutInSeconds > 0) - { - timeoutTokenSource.CancelAfter(TimeSpan.FromSeconds(retryTimeoutInSeconds)); - } - - var attempts = 0; - var backoffTimeInSecs = 0; - HttpResponseMessage response; - - while (true) - { - attempts++; - - try - { - response = await httpClient.SendAsync(getRequest(), linkedTokenSource.Token).ConfigureAwait(false); - - if (response.IsSuccessStatusCode || !response.IsRetryableStatusCode() || attempts == maxRetryCount) - { - break; - } - } - catch (HttpRequestException e) - { - if (attempts == maxRetryCount) - { - throw; - } - SqlClientEventSource.Log.TryTraceEvent("SendAsyncWithRetry | Exception occurred {0} | Attempting retry: {1} of {2}", e.Message, attempts, maxRetryCount); - } - - // use recommended exponential backoff strategy, and use linked token wait handle so caller or retry timeout is still able to cancel - backoffTimeInSecs += (int)Math.Pow(DeltaBackOffInSeconds, attempts); - linkedTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(backoffTimeInSecs)); - linkedTokenSource.Token.ThrowIfCancellationRequested(); - } - - return response; - } - catch (OperationCanceledException) - { - if (timeoutTokenSource.IsCancellationRequested) - { - throw new TimeoutException(RetryTimeoutError); - } - - throw; - } - } - } - } - #endregion -} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs index 28942ae39f..8ee6dbd7d2 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs @@ -5,6 +5,7 @@ using System; using System.Runtime.InteropServices; using System.Security; +using Microsoft.Data.Common; namespace Microsoft.Data.SqlClient { @@ -36,6 +37,9 @@ public class SqlAuthenticationParameters /// public string DatabaseName { get; } + /// + public int TimeoutInMilliseconds = ADP.DefaultConnectionTimeout; + /// protected SqlAuthenticationParameters( SqlAuthenticationMethod authenticationMethod, @@ -45,7 +49,8 @@ protected SqlAuthenticationParameters( string authority, string userId, string password, - Guid connectionId) + Guid connectionId, + int timeoutInMilliseconds) { AuthenticationMethod = authenticationMethod; ServerName = serverName; @@ -55,6 +60,7 @@ protected SqlAuthenticationParameters( UserId = userId; Password = password; ConnectionId = connectionId; + TimeoutInMilliseconds = timeoutInMilliseconds; } /// @@ -70,6 +76,7 @@ internal class Builder private string _userId; private string _password; private Guid _connectionId = Guid.NewGuid(); + private int _timeoutInMilliseconds = ADP.DefaultConnectionTimeout; /// /// Implicitly converts to . @@ -84,7 +91,8 @@ public static implicit operator SqlAuthenticationParameters(Builder builder) authority: builder._authority, userId: builder._userId, password: builder._password, - connectionId: builder._connectionId); + connectionId: builder._connectionId, + timeoutInMilliseconds: builder._timeoutInMilliseconds); } /// @@ -132,6 +140,15 @@ public Builder WithConnectionId(Guid connectionId) return this; } + /// + /// Set connection timeout. + /// + public Builder WithConnectionTimeout(int timeout) + { + _timeoutInMilliseconds = timeout; + return this; + } + internal Builder(SqlAuthenticationMethod authenticationMethod, string resource, string authority, string serverName, string databaseName) { _authenticationMethod = authenticationMethod; diff --git a/tools/props/Versions.props b/tools/props/Versions.props index fc96c72988..b02ec3f871 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -17,6 +17,7 @@ + 1.3.0 4.21.1 6.8.0 6.8.0 diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 6f27e7e6b1..13e6d26bdf 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -29,6 +29,7 @@ When using NuGet 3.x this package requires at least version 3.4. + @@ -41,6 +42,7 @@ When using NuGet 3.x this package requires at least version 3.4. + @@ -53,6 +55,7 @@ When using NuGet 3.x this package requires at least version 3.4. + @@ -65,6 +68,7 @@ When using NuGet 3.x this package requires at least version 3.4. + @@ -77,6 +81,7 @@ When using NuGet 3.x this package requires at least version 3.4. + From 05a3c0cedf355a3cbf124cfa0d50c485f197f71f Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 25 Mar 2021 13:12:31 -0700 Subject: [PATCH 2/9] Fix refs --- .../netcore/ref/Microsoft.Data.SqlClient.cs | 6 ++++-- .../netfx/ref/Microsoft.Data.SqlClient.cs | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index 0b8047b7bc..1be4b56803 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -108,7 +108,7 @@ public enum SqlAuthenticationMethod public partial class SqlAuthenticationParameters { /// - protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId) { } + protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int timeoutInMilliseconds) { } /// public Microsoft.Data.SqlClient.SqlAuthenticationMethod AuthenticationMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// @@ -125,6 +125,8 @@ protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthentication public string ServerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// public string UserId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + /// + public int TimeoutInMilliseconds { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } /// public abstract partial class SqlAuthenticationProvider @@ -698,7 +700,7 @@ public static void RegisterColumnEncryptionKeyStoreProviders(System.Collections. /// /// for internal test only /// - [System.ComponentModel.DesignerSerializationVisibilityAttribute(0)] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(0)] internal string SQLDNSCachingSupportedState { get { throw null; } } /// /// for internal test only diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index 1ec87b7897..7ea534e033 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -126,7 +126,7 @@ public enum SqlAuthenticationMethod public partial class SqlAuthenticationParameters { /// - protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId) { } + protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int timeoutInMilliseconds) { } /// public Microsoft.Data.SqlClient.SqlAuthenticationMethod AuthenticationMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// @@ -143,6 +143,8 @@ protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthentication public string ServerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// public string UserId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + /// + public int TimeoutInMilliseconds { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } /// public abstract partial class SqlAuthenticationProvider From 57811060d4d66602ae248a631c0173878fc2abbf Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 25 Mar 2021 13:27:28 -0700 Subject: [PATCH 3/9] Update tests --- .../SqlAuthenticationMethod.xml | 4 ++-- .../tests/ManualTests/DataCommon/AADUtility.cs | 14 +++++++------- .../ManualTests/DataCommon/DataTestUtility.cs | 8 ++++---- .../SQL/ConnectivityTests/AADConnectionTest.cs | 4 ++-- .../Config.cs | 2 +- .../config.default.json | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml index 19927484fd..54b8f3d0a7 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationMethod.xml @@ -34,11 +34,11 @@ 6 - The authentication method uses Active Directory Managed Identity. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the object ID of the user identity. + The authentication method uses Active Directory Managed Identity. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. 7 - Alias for "Active Directory Managed Identity" authentication method. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the object ID of the user identity. + Alias for "Active Directory Managed Identity" authentication method. Use System Assigned or User Assigned Managed Identity to connect to SQL Database from Azure client environments that have enabled support for Managed Identity. For User Assigned Managed Identity, 'User Id' or 'UID' is required to be set to the "client ID" of the user identity. 8 diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/AADUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/AADUtility.cs index 228217c039..6abff25d13 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/AADUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/AADUtility.cs @@ -26,8 +26,8 @@ public static async Task AzureActiveDirectoryAuthenticationCallback(stri return result.AccessToken; } - public static async Task GetManagedIdentityToken(string objectId = null) => - await new MockManagedIdentityTokenProvider().AcquireTokenAsync(objectId).ConfigureAwait(false); + public static async Task GetManagedIdentityToken(string clientId = null) => + await new MockManagedIdentityTokenProvider().AcquireTokenAsync(clientId).ConfigureAwait(false); } @@ -59,20 +59,20 @@ internal class MockManagedIdentityTokenProvider internal readonly int _retryTimeoutInSeconds = DefaultRetryTimeout; internal readonly int _maxRetryCount = DefaultMaxRetryCount; - public async Task AcquireTokenAsync(string objectId = null) + public async Task AcquireTokenAsync(string clientId = null) { // Use the httpClient specified in the constructor. If it was not specified in the constructor, use the default httpClient. HttpClient httpClient = s_defaultHttpClient; try { - // If user assigned managed identity is specified, include object ID parameter in request - string objectIdParameter = objectId != null - ? $"&object_id={objectId}" + // If user assigned managed identity is specified, include client Id parameter in request + string clientIdParameter = !string.IsNullOrEmpty(clientId) + ? $"&client_id={clientId}" : string.Empty; // Craft request as per the MSI protocol - var requestUrl = $"{AzureVmImdsEndpoint}?resource={Resource}{objectIdParameter}{AzureVmImdsApiVersion}"; + var requestUrl = $"{AzureVmImdsEndpoint}?resource={Resource}{clientIdParameter}{AzureVmImdsApiVersion}"; HttpResponseMessage response = null; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index 80701905f3..58dd79df04 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -53,7 +53,7 @@ public static class DataTestUtility public static readonly string DNSCachingServerTR = null; // this is for the tenant ring public static readonly bool IsDNSCachingSupportedCR = false; // this is for the control ring public static readonly bool IsDNSCachingSupportedTR = false; // this is for the tenant ring - public static readonly string UserManagedIdentityObjectId = null; + public static readonly string UserManagedIdentityClientId = null; public static readonly string EnclaveAzureDatabaseConnString = null; public static bool ManagedIdentitySupported = true; @@ -93,7 +93,7 @@ static DataTestUtility() IsDNSCachingSupportedCR = c.IsDNSCachingSupportedCR; IsDNSCachingSupportedTR = c.IsDNSCachingSupportedTR; EnclaveAzureDatabaseConnString = c.EnclaveAzureDatabaseConnString; - UserManagedIdentityObjectId = c.UserManagedIdentityObjectId; + UserManagedIdentityClientId = c.UserManagedIdentityClientId; System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12; @@ -459,8 +459,8 @@ public static string GetUserIdentityAccessToken() { if (true == ManagedIdentitySupported && null == AADUserIdentityAccessToken && IsAADPasswordConnStrSetup()) { - // Pass User Assigned Managed Identity Object Id here. - AADUserIdentityAccessToken = AADUtility.GetManagedIdentityToken(UserManagedIdentityObjectId).GetAwaiter().GetResult(); + // Pass User Assigned Managed Identity Client Id here. + AADUserIdentityAccessToken = AADUtility.GetManagedIdentityToken(UserManagedIdentityClientId).GetAwaiter().GetResult(); if (AADUserIdentityAccessToken == null) { ManagedIdentitySupported = false; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs index 8036f5aaf6..4d53f5d494 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs @@ -491,7 +491,7 @@ public static void UserAssigned_ManagedIdentityTest() { string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityObjectId};"; + $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityClientId};"; ConnectAndDisconnect(connStr); } @@ -543,7 +543,7 @@ public static void Azure_UserManagedIdentityTest() { string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys) - + $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityObjectId}"; + + $"Authentication=Active Directory Managed Identity; User Id={DataTestUtility.UserManagedIdentityClientId}"; using (SqlConnection conn = new SqlConnection(connectionString)) { diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Config.cs b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Config.cs index de6fffd6ae..8379b81baa 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Config.cs +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Config.cs @@ -36,7 +36,7 @@ public class Config public bool IsDNSCachingSupportedCR = false; // this is for the control ring public bool IsDNSCachingSupportedTR = false; // this is for the tenant ring public string EnclaveAzureDatabaseConnString = null; - public string UserManagedIdentityObjectId = null; + public string UserManagedIdentityClientId = null; public static Config Load(string configPath = @"config.json") { diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json index 11ee9f25e5..4c725d8555 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json @@ -20,5 +20,5 @@ "UseManagedSNIOnWindows": false, "IsAzureSynapse": false, "EnclaveAzureDatabaseConnString": "", - "UserManagedIdentityObjectId": "" + "UserManagedIdentityClientId": "" } From 195da2d99af5f1ed9a04369cb9c6bfe47c1f067f Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 25 Mar 2021 13:58:53 -0700 Subject: [PATCH 4/9] Fix test --- .../ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs index 4d53f5d494..897a6ffbe9 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs @@ -388,7 +388,7 @@ public static void ActiveDirectoryManagedIdentityWithInvalidUserIdMustFail(strin AggregateException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); - string expectedMessage = "Response: {\"error\":\"invalid_request\",\"error_description\":\"Identity not found\"}"; + string expectedMessage = "ManagedIdentityCredential authentication unavailable, the requested identity has not been assigned to this resource."; Assert.Contains(expectedMessage, e.GetBaseException().Message); } From c3cf682f403c7f1ba9fc47de76e4b7ffb830b56a Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Tue, 13 Apr 2021 11:50:13 -0700 Subject: [PATCH 5/9] Review feedback + remove unused error messages --- ...uthenticationProviderManager.NetCoreApp.cs | 11 +--- ...thenticationProviderManager.NetStandard.cs | 11 +--- .../SqlAuthenticationProviderManager.cs | 17 +++++- .../SqlClient/SqlInternalConnectionTds.cs | 11 ++-- .../netcore/src/Resources/Strings.Designer.cs | 54 ------------------- .../netcore/src/Resources/Strings.resx | 18 ------- .../SqlAuthenticationProviderManager.cs | 20 +++---- .../SqlClient/SqlInternalConnectionTds.cs | 2 +- .../netfx/src/Resources/Strings.Designer.cs | 54 ------------------- .../netfx/src/Resources/Strings.resx | 18 ------- .../SqlClient/SqlAuthenticationProvider.cs | 4 +- 11 files changed, 38 insertions(+), 182 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs index ad76c371ed..c7b737fd5f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs @@ -33,15 +33,8 @@ static SqlAuthenticationProviderManager() SqlClientEventSource.Log.TryTraceEvent("static SqlAuthenticationProviderManager: Unable to load custom SqlAuthenticationProviders or SqlClientAuthenticationProviders. ConfigurationManager failed to load due to configuration errors: {0}", e); } - Instance = new SqlAuthenticationProviderManager(configurationSection); - var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + s_instance = new SqlAuthenticationProviderManager(configurationSection); + SetDefaultAuthProviders(); } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs index 7bb4b28bdb..a1f3f7b133 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs @@ -8,15 +8,8 @@ internal partial class SqlAuthenticationProviderManager { static SqlAuthenticationProviderManager() { - Instance = new SqlAuthenticationProviderManager(); - var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + s_instance = new SqlAuthenticationProviderManager(); + SetDefaultAuthProviders(); } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index f55bb9d8e4..f586b0ff0c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -28,8 +28,23 @@ internal partial class SqlAuthenticationProviderManager private readonly SqlClientLogger _sqlAuthLogger = new SqlClientLogger(); private readonly string _applicationClientId = ActiveDirectoryAuthentication.AdoClientId; - public static readonly SqlAuthenticationProviderManager Instance; + public static readonly SqlAuthenticationProviderManager s_instance; + /// + /// Sets default supported Active Directory Authentication providers by the driver + /// on the SqlAuthenticationProviderManager instance. + /// + private static void SetDefaultAuthProviders() + { + var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(s_instance._applicationClientId); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + } /// /// Constructor. /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 100c41290c..05fa2bfd3e 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -471,7 +471,7 @@ internal SqlInternalConnectionTds( } _activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper(); - _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.Instance; + _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.s_instance; _identity = identity; Debug.Assert(newSecurePassword != null || newPassword != null, "cannot have both new secure change password and string based change password to be null"); @@ -2292,7 +2292,6 @@ internal bool TryGetFedAuthTokenLocked(SqlFedAuthInfo fedAuthInfo, DbConnectionP /// SqlFedAuthToken internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) { - Debug.Assert(fedAuthInfo != null, "fedAuthInfo should not be null."); // No:of milliseconds to sleep for the inital back off. @@ -2347,7 +2346,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) } else { - Task.Run(() => _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); _activeDirectoryAuthTimeoutRetryHelper.CachedToken = _fedAuthToken; } break; @@ -2362,7 +2361,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) else { authParamsBuilder.WithUserId(ConnectionOptions.UserID); - Task.Run(() => _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); _activeDirectoryAuthTimeoutRetryHelper.CachedToken = _fedAuthToken; } break; @@ -2378,13 +2377,13 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) { username = _credential.UserId; authParamsBuilder.WithUserId(username).WithPassword(_credential.Password); - Task.Run(() => _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); } else { username = ConnectionOptions.UserID; authParamsBuilder.WithUserId(username).WithPassword(ConnectionOptions.Password); - Task.Run(() => _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + _fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); } _activeDirectoryAuthTimeoutRetryHelper.CachedToken = _fedAuthToken; } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs index a351132431..8a95a52351 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs @@ -897,60 +897,6 @@ internal static string AttestationTokenSignatureValidationFailed { } } - /// - /// Looks up a localized string similar to Access token could not be acquired.. - /// - internal static string Azure_GenericErrorMessage { - get { - return ResourceManager.GetString("Azure_GenericErrorMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to connect to the Managed Identity endpoint. Please check that you are running on an Azure resource that has Identity setup.. - /// - internal static string Azure_IdentityEndpointNotListening { - get { - return ResourceManager.GetString("Azure_IdentityEndpointNotListening", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tried to get token using Managed Identity.. - /// - internal static string Azure_ManagedIdentityUsed { - get { - return ResourceManager.GetString("Azure_ManagedIdentityUsed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to connect to the Instance Metadata Service (IMDS). Skipping request to the Managed Identity token endpoint.. - /// - internal static string Azure_MetadataEndpointNotListening { - get { - return ResourceManager.GetString("Azure_MetadataEndpointNotListening", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Received a non-retryable error.. - /// - internal static string Azure_NonRetryableError { - get { - return ResourceManager.GetString("Azure_NonRetryableError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed after 5 retries.. - /// - internal static string Azure_RetryFailure { - get { - return ResourceManager.GetString("Azure_RetryFailure", resourceCulture); - } - } - /// /// Looks up a localized string similar to .database.chinacloudapi.cn. /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx index 6854ef7fad..5dd36f38ac 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx @@ -1914,24 +1914,6 @@ Cannot use 'Authentication={0}', if the Credential property has been set. - - Access token could not be acquired. - - - Unable to connect to the Managed Identity endpoint. Please check that you are running on an Azure resource that has Identity setup. - - - Tried to get token using Managed Identity. - - - Unable to connect to the Instance Metadata Service (IMDS). Skipping request to the Managed Identity token endpoint. - - - Received a non-retryable error. - - - Failed after 5 retries. - Value '{0}' is out of range. Must be between {1} and {2}. diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index 561c0cd101..893f853c1b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -41,18 +41,18 @@ static SqlAuthenticationProviderManager() // Don't throw an error for invalid config files SqlClientEventSource.Log.TryTraceEvent("static SqlAuthenticationProviderManager: Unable to load custom SqlAuthenticationProviders or SqlClientAuthenticationProviders. ConfigurationManager failed to load due to configuration errors: {0}", e); } - Instance = new SqlAuthenticationProviderManager(configurationSection); + s_instance = new SqlAuthenticationProviderManager(configurationSection); - var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); - Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(s_instance._applicationClientId); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); } - public static readonly SqlAuthenticationProviderManager Instance; + public static readonly SqlAuthenticationProviderManager s_instance; private readonly string _typeName; private readonly SqlAuthenticationInitializer _initializer; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 4c79b037ba..2b4e742801 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -486,7 +486,7 @@ internal SqlInternalConnectionTds( } _activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper(); - _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.Instance; + _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.s_instance; _serverCallback = serverCallback; _clientCallback = clientCallback; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs index af7390b2a9..666ff47326 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs @@ -1833,60 +1833,6 @@ internal static string AttestationTokenSignatureValidationFailed { } } - /// - /// Looks up a localized string similar to Access token could not be acquired.. - /// - internal static string Azure_GenericErrorMessage { - get { - return ResourceManager.GetString("Azure_GenericErrorMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to connect to the Managed Identity endpoint. Please check that you are running on an Azure resource that has Identity setup.. - /// - internal static string Azure_IdentityEndpointNotListening { - get { - return ResourceManager.GetString("Azure_IdentityEndpointNotListening", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tried to get token using Managed Identity.. - /// - internal static string Azure_ManagedIdentityUsed { - get { - return ResourceManager.GetString("Azure_ManagedIdentityUsed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to connect to the Instance Metadata Service (IMDS). Skipping request to the Managed Identity token endpoint.. - /// - internal static string Azure_MetadataEndpointNotListening { - get { - return ResourceManager.GetString("Azure_MetadataEndpointNotListening", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Received a non-retryable error.. - /// - internal static string Azure_NonRetryableError { - get { - return ResourceManager.GetString("Azure_NonRetryableError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed after 5 retries.. - /// - internal static string Azure_RetryFailure { - get { - return ResourceManager.GetString("Azure_RetryFailure", resourceCulture); - } - } - /// /// Looks up a localized string similar to .database.chinacloudapi.cn. /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx index d1b907c6e9..6f12cd0ac6 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx @@ -4584,24 +4584,6 @@ Cannot use 'Authentication={0}', if the Credential property has been set. - - Access token could not be acquired. - - - Unable to connect to the Managed Identity endpoint. Please check that you are running on an Azure resource that has Identity setup. - - - Tried to get token using Managed Identity. - - - Unable to connect to the Instance Metadata Service (IMDS). Skipping request to the Managed Identity token endpoint. - - - Received a non-retryable error. - - - Failed after 5 retries. - Unexpected type detected on deserialize. diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs index 25e1cf006e..1907d0aec8 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs @@ -13,13 +13,13 @@ public abstract class SqlAuthenticationProvider /// public static SqlAuthenticationProvider GetProvider(SqlAuthenticationMethod authenticationMethod) { - return SqlAuthenticationProviderManager.Instance.GetProvider(authenticationMethod); + return SqlAuthenticationProviderManager.s_instance.GetProvider(authenticationMethod); } /// public static bool SetProvider(SqlAuthenticationMethod authenticationMethod, SqlAuthenticationProvider provider) { - return SqlAuthenticationProviderManager.Instance.SetProvider(authenticationMethod, provider); + return SqlAuthenticationProviderManager.s_instance.SetProvider(authenticationMethod, provider); } /// From a84346b5d773543f6701e1f4ffc6e38e655dca3f Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Tue, 13 Apr 2021 13:31:23 -0700 Subject: [PATCH 6/9] Improvements --- ...uthenticationProviderManager.NetCoreApp.cs | 2 +- ...thenticationProviderManager.NetStandard.cs | 4 ++-- .../SqlAuthenticationProviderManager.cs | 21 +++++++++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs index c7b737fd5f..2b9ca196c6 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs @@ -34,7 +34,7 @@ static SqlAuthenticationProviderManager() } s_instance = new SqlAuthenticationProviderManager(configurationSection); - SetDefaultAuthProviders(); + SetDefaultAuthProviders(s_instance); } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs index a1f3f7b133..373a6ba97a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs @@ -7,9 +7,9 @@ namespace Microsoft.Data.SqlClient internal partial class SqlAuthenticationProviderManager { static SqlAuthenticationProviderManager() - { + { s_instance = new SqlAuthenticationProviderManager(); - SetDefaultAuthProviders(); + SetDefaultAuthProviders(s_instance); } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index f586b0ff0c..a0246eb4d1 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -34,16 +34,19 @@ internal partial class SqlAuthenticationProviderManager /// Sets default supported Active Directory Authentication providers by the driver /// on the SqlAuthenticationProviderManager instance. /// - private static void SetDefaultAuthProviders() + private static void SetDefaultAuthProviders(SqlAuthenticationProviderManager instance) { - var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(s_instance._applicationClientId); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + if (instance != null) + { + var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(instance._applicationClientId); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + } } /// /// Constructor. From 7c5595746a4a1df0d279b7b22b661a0220bd1deb Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Tue, 13 Apr 2021 14:52:15 -0700 Subject: [PATCH 7/9] Rename back --- ...uthenticationProviderManager.NetCoreApp.cs | 4 ++-- ...thenticationProviderManager.NetStandard.cs | 4 ++-- .../SqlAuthenticationProviderManager.cs | 2 +- .../SqlClient/SqlInternalConnectionTds.cs | 2 +- .../SqlAuthenticationProviderManager.cs | 20 +++++++++---------- .../SqlClient/SqlInternalConnectionTds.cs | 2 +- .../SqlClient/SqlAuthenticationProvider.cs | 4 ++-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs index 2b9ca196c6..e253829b2c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetCoreApp.cs @@ -33,8 +33,8 @@ static SqlAuthenticationProviderManager() SqlClientEventSource.Log.TryTraceEvent("static SqlAuthenticationProviderManager: Unable to load custom SqlAuthenticationProviders or SqlClientAuthenticationProviders. ConfigurationManager failed to load due to configuration errors: {0}", e); } - s_instance = new SqlAuthenticationProviderManager(configurationSection); - SetDefaultAuthProviders(s_instance); + Instance = new SqlAuthenticationProviderManager(configurationSection); + SetDefaultAuthProviders(Instance); } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs index 373a6ba97a..01a84342f8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.NetStandard.cs @@ -8,8 +8,8 @@ internal partial class SqlAuthenticationProviderManager { static SqlAuthenticationProviderManager() { - s_instance = new SqlAuthenticationProviderManager(); - SetDefaultAuthProviders(s_instance); + Instance = new SqlAuthenticationProviderManager(); + SetDefaultAuthProviders(Instance); } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index a0246eb4d1..1841f016d0 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -28,7 +28,7 @@ internal partial class SqlAuthenticationProviderManager private readonly SqlClientLogger _sqlAuthLogger = new SqlClientLogger(); private readonly string _applicationClientId = ActiveDirectoryAuthentication.AdoClientId; - public static readonly SqlAuthenticationProviderManager s_instance; + public static readonly SqlAuthenticationProviderManager Instance; /// /// Sets default supported Active Directory Authentication providers by the driver diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 05fa2bfd3e..49129e405f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -471,7 +471,7 @@ internal SqlInternalConnectionTds( } _activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper(); - _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.s_instance; + _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.Instance; _identity = identity; Debug.Assert(newSecurePassword != null || newPassword != null, "cannot have both new secure change password and string based change password to be null"); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index 893f853c1b..561c0cd101 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -41,18 +41,18 @@ static SqlAuthenticationProviderManager() // Don't throw an error for invalid config files SqlClientEventSource.Log.TryTraceEvent("static SqlAuthenticationProviderManager: Unable to load custom SqlAuthenticationProviders or SqlClientAuthenticationProviders. ConfigurationManager failed to load due to configuration errors: {0}", e); } - s_instance = new SqlAuthenticationProviderManager(configurationSection); + Instance = new SqlAuthenticationProviderManager(configurationSection); - var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(s_instance._applicationClientId); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); - s_instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); + var activeDirectoryAuthProvider = new ActiveDirectoryAuthenticationProvider(Instance._applicationClientId); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryIntegrated, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, activeDirectoryAuthProvider); + Instance.SetProvider(SqlAuthenticationMethod.ActiveDirectoryMSI, activeDirectoryAuthProvider); } - public static readonly SqlAuthenticationProviderManager s_instance; + public static readonly SqlAuthenticationProviderManager Instance; private readonly string _typeName; private readonly SqlAuthenticationInitializer _initializer; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 2b4e742801..4c79b037ba 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -486,7 +486,7 @@ internal SqlInternalConnectionTds( } _activeDirectoryAuthTimeoutRetryHelper = new ActiveDirectoryAuthenticationTimeoutRetryHelper(); - _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.s_instance; + _sqlAuthenticationProviderManager = SqlAuthenticationProviderManager.Instance; _serverCallback = serverCallback; _clientCallback = clientCallback; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs index 1907d0aec8..25e1cf006e 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProvider.cs @@ -13,13 +13,13 @@ public abstract class SqlAuthenticationProvider /// public static SqlAuthenticationProvider GetProvider(SqlAuthenticationMethod authenticationMethod) { - return SqlAuthenticationProviderManager.s_instance.GetProvider(authenticationMethod); + return SqlAuthenticationProviderManager.Instance.GetProvider(authenticationMethod); } /// public static bool SetProvider(SqlAuthenticationMethod authenticationMethod, SqlAuthenticationProvider provider) { - return SqlAuthenticationProviderManager.s_instance.SetProvider(authenticationMethod, provider); + return SqlAuthenticationProviderManager.Instance.SetProvider(authenticationMethod, provider); } /// From cc750126b57e1f5f2d914346dac1bf6912430e67 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 14 Apr 2021 10:56:00 -0700 Subject: [PATCH 8/9] Address review feedback --- .../SqlAuthenticationParameters.xml | 6 +++--- .../netcore/ref/Microsoft.Data.SqlClient.cs | 6 +++--- .../Data/SqlClient/SqlInternalConnectionTds.cs | 2 +- .../Data/SqlClient/TdsParserStateObjectNative.cs | 1 - .../netfx/ref/Microsoft.Data.SqlClient.cs | 6 +++--- .../Data/SqlClient/SqlInternalConnectionTds.cs | 10 +++++----- .../ActiveDirectoryAuthenticationProvider.cs | 2 +- .../Data/SqlClient/SqlAuthenticationParameters.cs | 14 +++++++------- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml index ec6695297d..51fec0ae1f 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlAuthenticationParameters.xml @@ -12,7 +12,7 @@ The user login name/ID. The user password. The connection ID. - The connection timeout value in milliseconds. + The connection timeout value in seconds. Initializes a new instance of the class using the specified authentication method, server name, database name, resource URI, authority URI, user login name/ID, user password, connection ID and connection timeout value. @@ -47,9 +47,9 @@ Gets the database name. The database name. - + Gets the connection timeout value. The connection timeout value to be passed to Cancellation Token Source. - + diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index 1be4b56803..183546b535 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -108,7 +108,7 @@ public enum SqlAuthenticationMethod public partial class SqlAuthenticationParameters { /// - protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int timeoutInMilliseconds) { } + protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int connectionTimeout) { } /// public Microsoft.Data.SqlClient.SqlAuthenticationMethod AuthenticationMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// @@ -125,8 +125,8 @@ protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthentication public string ServerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// public string UserId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - /// - public int TimeoutInMilliseconds { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + /// + public int ConnectionTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } /// public abstract partial class SqlAuthenticationProvider diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 49129e405f..85699cce23 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -2324,7 +2324,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) serverName: ConnectionOptions.DataSource, databaseName: ConnectionOptions.InitialCatalog) .WithConnectionId(_clientConnectionId) - .WithConnectionTimeout(ConnectionOptions.ConnectTimeout * 1000); + .WithConnectionTimeout(ConnectionOptions.ConnectTimeout); switch (ConnectionOptions.Authentication) { case SqlAuthenticationMethod.ActiveDirectoryIntegrated: diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs index 1b7deb2a0b..34c7910dde 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs @@ -96,7 +96,6 @@ internal override void AssignPendingDNSInfo(string userProtocol, string DNSCache result = SNINativeMethodWrapper.SniGetConnectionPort(Handle, ref portFromSNI); Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionPort"); - result = SNINativeMethodWrapper.SniGetConnectionIPString(Handle, ref IPStringFromSNI); Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionIPString"); diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index 7ea534e033..16227cc0c8 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -126,7 +126,7 @@ public enum SqlAuthenticationMethod public partial class SqlAuthenticationParameters { /// - protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int timeoutInMilliseconds) { } + protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthenticationMethod authenticationMethod, string serverName, string databaseName, string resource, string authority, string userId, string password, System.Guid connectionId, int connectionTimeout) { } /// public Microsoft.Data.SqlClient.SqlAuthenticationMethod AuthenticationMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// @@ -143,8 +143,8 @@ protected SqlAuthenticationParameters(Microsoft.Data.SqlClient.SqlAuthentication public string ServerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } /// public string UserId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - /// - public int TimeoutInMilliseconds { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + /// + public int ConnectionTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } /// public abstract partial class SqlAuthenticationProvider diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 4c79b037ba..29aa201b86 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -2772,7 +2772,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) serverName: ConnectionOptions.DataSource, databaseName: ConnectionOptions.InitialCatalog) .WithConnectionId(_clientConnectionId) - .WithConnectionTimeout(ConnectionOptions.ConnectTimeout * 1000); + .WithConnectionTimeout(ConnectionOptions.ConnectTimeout); switch (ConnectionOptions.Authentication) { case SqlAuthenticationMethod.ActiveDirectoryIntegrated: @@ -2783,7 +2783,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) } else { - Task.Run(() => fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); _activeDirectoryAuthTimeoutRetryHelper.CachedToken = fedAuthToken; } break; @@ -2798,7 +2798,7 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) else { authParamsBuilder.WithUserId(ConnectionOptions.UserID); - Task.Run(() => fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); _activeDirectoryAuthTimeoutRetryHelper.CachedToken = fedAuthToken; } break; @@ -2814,13 +2814,13 @@ internal SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) { username = _credential.UserId; authParamsBuilder.WithUserId(username).WithPassword(_credential.Password); - Task.Run(() => fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); } else { username = ConnectionOptions.UserID; authParamsBuilder.WithUserId(username).WithPassword(ConnectionOptions.Password); - Task.Run(() => fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken()).Wait(); + fedAuthToken = authProvider.AcquireTokenAsync(authParamsBuilder).Result.ToSqlFedAuthToken(); } _activeDirectoryAuthTimeoutRetryHelper.CachedToken = fedAuthToken; } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs index 342e834697..7247ebce98 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -108,7 +108,7 @@ public override async Task AcquireTokenAsync(SqlAuthenti CancellationTokenSource cts = new CancellationTokenSource(); // Use Connection timeout value to cancel token acquire request after certain period of time. - cts.CancelAfter(parameters.TimeoutInMilliseconds); + cts.CancelAfter(parameters.ConnectionTimeout * 1000); // Convert to milliseconds string scope = parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix; string[] scopes = new string[] { scope }; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs index 8ee6dbd7d2..745ba716e3 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationParameters.cs @@ -37,8 +37,8 @@ public class SqlAuthenticationParameters /// public string DatabaseName { get; } - /// - public int TimeoutInMilliseconds = ADP.DefaultConnectionTimeout; + /// + public int ConnectionTimeout = ADP.DefaultConnectionTimeout; /// protected SqlAuthenticationParameters( @@ -50,7 +50,7 @@ protected SqlAuthenticationParameters( string userId, string password, Guid connectionId, - int timeoutInMilliseconds) + int connectionTimeout) { AuthenticationMethod = authenticationMethod; ServerName = serverName; @@ -60,7 +60,7 @@ protected SqlAuthenticationParameters( UserId = userId; Password = password; ConnectionId = connectionId; - TimeoutInMilliseconds = timeoutInMilliseconds; + ConnectionTimeout = connectionTimeout; } /// @@ -76,7 +76,7 @@ internal class Builder private string _userId; private string _password; private Guid _connectionId = Guid.NewGuid(); - private int _timeoutInMilliseconds = ADP.DefaultConnectionTimeout; + private int _connectionTimeout = ADP.DefaultConnectionTimeout; /// /// Implicitly converts to . @@ -92,7 +92,7 @@ public static implicit operator SqlAuthenticationParameters(Builder builder) userId: builder._userId, password: builder._password, connectionId: builder._connectionId, - timeoutInMilliseconds: builder._timeoutInMilliseconds); + connectionTimeout: builder._connectionTimeout); } /// @@ -145,7 +145,7 @@ public Builder WithConnectionId(Guid connectionId) /// public Builder WithConnectionTimeout(int timeout) { - _timeoutInMilliseconds = timeout; + _connectionTimeout = timeout; return this; } From 811f4c73f13a1a6cd957b091b399a541253b062b Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 14 Apr 2021 14:57:34 -0700 Subject: [PATCH 9/9] Fix test --- .../SqlClient/ActiveDirectoryAuthenticationProvider.cs | 10 +++++----- .../SQL/ConnectivityTests/AADConnectionTest.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs index 7247ebce98..65aeec11c8 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -177,7 +177,7 @@ public override async Task AcquireTokenAsync(SqlAuthenti .WithCorrelationId(parameters.ConnectionId) .ExecuteAsync(cancellationToken: cts.Token); } - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Integrated auth mode. Expiry Time: {0}", result.ExpiresOn); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Integrated auth mode. Expiry Time: {0}", result?.ExpiresOn); } else if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryPassword) { @@ -189,7 +189,7 @@ public override async Task AcquireTokenAsync(SqlAuthenti result = await app.AcquireTokenByUsernamePassword(scopes, parameters.UserId, password) .WithCorrelationId(parameters.ConnectionId) .ExecuteAsync(cancellationToken: cts.Token); - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Password auth mode. Expiry Time: {0}", result.ExpiresOn); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Active Directory Password auth mode. Expiry Time: {0}", result?.ExpiresOn); } else if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryInteractive || parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow) @@ -213,7 +213,7 @@ public override async Task AcquireTokenAsync(SqlAuthenti // If 'account' is available in 'app', we use the same to acquire token silently. // Read More on API docs: https://docs.microsoft.com/dotnet/api/microsoft.identity.client.clientapplicationbase.acquiretokensilent result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken: cts.Token); - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (silent) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (silent) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result?.ExpiresOn); } catch (MsalUiRequiredException) { @@ -221,14 +221,14 @@ public override async Task AcquireTokenAsync(SqlAuthenti // for instance, if no refresh token was in the cache, or the user needs to consent, or re-sign-in (for instance if the password expired), // or the user needs to perform two factor authentication. result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod, cts); - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result?.ExpiresOn); } } else { // If no existing 'account' is found, we request user to sign in interactively. result = await AcquireTokenInteractiveDeviceFlowAsync(app, scopes, parameters.ConnectionId, parameters.UserId, parameters.AuthenticationMethod, cts); - SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result.ExpiresOn); + SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token (interactive) for {0} auth mode. Expiry Time: {1}", parameters.AuthenticationMethod, result?.ExpiresOn); } } else diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs index 897a6ffbe9..d5ea380f3c 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs @@ -164,7 +164,7 @@ public static void AADPasswordWithWrongPassword() AggregateException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); string expectedMessage = "ID3242: The security token could not be authenticated or authorized."; - Assert.Contains(expectedMessage, e.InnerException.InnerException.InnerException.Message); + Assert.Contains(expectedMessage, e.InnerException.InnerException.Message); }