diff --git a/.github/instructions/testing.instructions.md b/.github/instructions/testing.instructions.md index df6b909f8a..4db8e8cc13 100644 --- a/.github/instructions/testing.instructions.md +++ b/.github/instructions/testing.instructions.md @@ -58,9 +58,9 @@ Copy `config.default.jsonc` to `config.jsonc` and configure: | Property | Description | |----------|-------------| -| `TCPConnectionString` | Primary TCP connection | -| `NPConnectionString` | Named Pipes connection | -| `AADPasswordConnectionString` | Entra ID password auth | +| `TCPConnectionString` | Primary TCP connection to on-premises SQL Server | +| `NPConnectionString` | Named Pipes connection to on-premises SQL Server | +| `AzureSqlConnectionString` | Entra ID connection string to Azure SQL Database | | `AzureKeyVaultURL` | AKV for encryption tests | | `EnclaveEnabled` | Enable enclave tests | | `FileStreamDirectory` | FileStream test path | diff --git a/TESTGUIDE.md b/TESTGUIDE.md index 791d4a7bcc..44a73f9199 100644 --- a/TESTGUIDE.md +++ b/TESTGUIDE.md @@ -254,8 +254,8 @@ dotnet build -t:TestSqlClientManual -p:TestSet=2 | `TCPConnectionStringAASSGX` | Optional connection string for SQL Server with SGX enclave and Microsoft Azure Attestation. | Include `Attestation Protocol=AAS` and `Enclave Attestation Url`. | | `EnclaveEnabled` | Enables tests that require an enclave-configured server. | `true` or `false`. | | `TracingEnabled` | Enables tracing-related tests. | `true` or `false`. | -| `AADAuthorityURL` | Optional OAuth authority for `AADPasswordConnectionString`. | `https://login.windows.net/` | -| `AADPasswordConnectionString` | Optional connection string for Microsoft Entra ID password authentication tests. | Uses `Authentication=Active Directory Password`. | +| `AADAuthorityURL` | Optional OAuth authority for `AzureSqlConnectionString`. | `https://login.windows.net/` | +| `AzureSqlConnectionString` | Optional connection string for Microsoft Entra ID authentication tests, contains Server and Initial Catalog properties only. | Authentication information and credentials are configured by the test code. | | `AADServicePrincipalId` | Optional application ID for service-principal authentication tests. | Former docs may refer to this as a secure principal ID. | | `AADServicePrincipalSecret` | Optional application secret for service-principal authentication tests. | Keep this only in local, ignored config files or secure pipeline variables. | | `AzureKeyVaultURL` | Optional Azure Key Vault URL for Always Encrypted tests. | `https://.vault.azure.net/` | diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index 1b1ea7a2e7..67c58cba41 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -255,8 +255,8 @@ jobs: EnclaveEnabled: ${{ eq(parameters.configProperties.EnclaveEnabled, 'true') }} ${{ if parameters.configProperties.TracingEnabled }}: TracingEnabled: ${{ eq(parameters.configProperties.TracingEnabled, 'true') }} - ${{ if parameters.configProperties.AADPasswordConnectionString }}: - AADPasswordConnectionString: ${{ parameters.configProperties.AADPasswordConnectionString }} + ${{ if parameters.configProperties.AzureSqlConnectionString }}: + AzureSqlConnectionString: ${{ parameters.configProperties.AzureSqlConnectionString }} ${{ if parameters.configProperties.AADServicePrincipalId }}: AADServicePrincipalId: ${{ parameters.configProperties.AADServicePrincipalId }} ${{ if parameters.configProperties.AADServicePrincipalSecret }}: diff --git a/eng/pipelines/common/templates/steps/update-config-file-step.yml b/eng/pipelines/common/templates/steps/update-config-file-step.yml index fd57828df0..3cf5c575d1 100644 --- a/eng/pipelines/common/templates/steps/update-config-file-step.yml +++ b/eng/pipelines/common/templates/steps/update-config-file-step.yml @@ -45,7 +45,7 @@ parameters: type: string default: '' - - name: AADPasswordConnectionString + - name: AzureSqlConnectionString type: string default: '' @@ -154,7 +154,7 @@ steps: $p.AADAuthorityURL="${{parameters.AADAuthorityURL }}" - $p.AADPasswordConnectionString="${{parameters.AADPasswordConnectionString }}" + $p.AzureSqlConnectionString="${{parameters.AzureSqlConnectionString }}" $p.AADServicePrincipalId="${{parameters.AADServicePrincipalId }}" diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 9ee7c7132d..b100a9665c 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -504,14 +504,14 @@ stages: configProperties: TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING) NPConnectionString: $(AZURE_DB_NP_CONN_STRING) + AzureSqlConnectionString: $(AZURE_SQL_CONN_STRING_WestUS2) AADAuthorityURL: $(AADAuthorityURL) # Pipeline runs against forks of the repo don't have access to Library secrets, so we # omit them entirely from the configProperties, which causes the dependent tests to be # skipped. ${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}: - AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) AADServicePrincipalSecret: $(AADServicePrincipalSecret) - AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalId: $(AADServicePrincipalId) AzureKeyVaultUrl: $(AzureKeyVaultUrl) AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) SupportsIntegratedSecurity: false @@ -535,11 +535,11 @@ stages: configProperties: TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING_eastus) NPConnectionString: $(AZURE_DB_NP_CONN_STRING_eastus) + AzureSqlConnectionString: $(AZURE_SQL_CONN_STRING_EastUS) AADAuthorityURL: $(AADAuthorityURL) ${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}: - AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR_eastus) AADServicePrincipalSecret: $(AADServicePrincipalSecret) - AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalId: $(AADServicePrincipalId) AzureKeyVaultUrl: $(AzureKeyVaultUrl) AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) SupportsIntegratedSecurity: false @@ -586,11 +586,11 @@ stages: configProperties: TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING) NPConnectionString: $(AZURE_DB_NP_CONN_STRING) + AzureSqlConnectionString: $(AZURE_SQL_CONN_STRING_WestUS2) AADAuthorityURL: $(AADAuthorityURL) ${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}: - AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) AADServicePrincipalSecret: $(AADServicePrincipalSecret) - AADServicePrincipalId: $(AADServicePrincipalId) + AADServicePrincipalId: $(AADServicePrincipalId) AzureKeyVaultUrl: $(AzureKeyVaultUrl) AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) SupportsIntegratedSecurity: false diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index eb9e36152a..3ea1a8fbbe 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -264,20 +264,19 @@ jobs: # The config.jsonc file has many options, but only some of them are # used by the Azure package tests. We only specify the ones that are # necessary here. - - AADServicePrincipalId: $(AADServicePrincipalId) AzureKeyVaultTenantId: $(AzureKeyVaultTenantId) # macOS doesn't support managed identities. ManagedIdentitySupported: ${{ not(eq(parameters.vmImage, 'macos-latest')) }} SupportsIntegratedSecurity: ${{ parameters.supportsIntegratedSecurity }} TCPConnectionString: $(AZURE_DB_TCP_CONN_STRING) + AzureSqlConnectionString: $(AZURE_SQL_CONN_STRING_WestUS2) UserManagedIdentityClientId: $(UserManagedIdentityClientId) WorkloadIdentityFederationServiceConnectionId: $(WorkloadIdentityFederationServiceConnectionId) # Avoid exposing secrets to pipeline jobs triggered via forks. This # prevents external contributors from creating PRs and running # pipelines that could expose these secrets. ${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}: - AADPasswordConnectionString: $(AAD_PASSWORD_CONN_STR) + AADServicePrincipalId: $(AADServicePrincipalId) AADServicePrincipalSecret: $(AADServicePrincipalSecret) # Perform any local SQL Server setup. diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/AADConnectionTest.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/AADConnectionTest.cs index 5dd3ac336e..b65024a603 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/AADConnectionTest.cs @@ -8,6 +8,7 @@ // new unit and/or integration tests in the future. using System.Text.RegularExpressions; +using Microsoft.Data.SqlClient.Tests.Common; namespace Microsoft.Data.SqlClient.Extensions.Azure.Test; @@ -28,21 +29,24 @@ public static void KustoDatabaseTest() [ConditionalFact( typeof(Config), - nameof(Config.HasPasswordConnectionString), + nameof(Config.HasAzureSqlConnectionString), nameof(Config.HasServicePrincipal))] public static void NoCredentialsActiveDirectoryServicePrincipal() { // test Passes with correct connection string. - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = RemoveKeysInConnStr(Config.PasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Service Principal; User ID={Config.ServicePrincipalId}; PWD={Config.ServicePrincipalSecret};"; - ConnectAndDisconnect(connStr); + string connString = Config.AzureSqlConnString + .AddServicePrincipalAuthenticationToConnString() + .AddUserToConnString(Config.ServicePrincipalId) + .AddPasswordToConnString(Config.ServicePrincipalSecret); + + ConnectAndDisconnect(connString); // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = RemoveKeysInConnStr(Config.PasswordConnectionString, credKeys) + - "Authentication=Active Directory Service Principal;"; - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + string connStrWithNoCred = Config.AzureSqlConnString + .AddServicePrincipalAuthenticationToConnString(); + + InvalidOperationException e = Assert.Throws + (() => ConnectAndDisconnect(connStrWithNoCred)); string expectedMessage = "Either Credential or both 'User ID' and 'Password' (or 'UID' and 'PWD') connection string keywords must be specified, if 'Authentication=Active Directory Service Principal'."; Assert.Contains(expectedMessage, e.Message); @@ -50,21 +54,24 @@ public static void NoCredentialsActiveDirectoryServicePrincipal() [ConditionalTheory( typeof(Config), - nameof(Config.HasPasswordConnectionString), + nameof(Config.HasAzureSqlConnectionString), nameof(Config.HasUserManagedIdentityClientId))] [InlineData("2445343 2343253")] [InlineData("2445343$#^@@%2343253")] public static void ActiveDirectoryManagedIdentityWithInvalidUserIdMustFail(string userId) { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = RemoveKeysInConnStr(Config.PasswordConnectionString, credKeys) + - $"Authentication=Active Directory Managed Identity; User Id={userId}"; + string connStrWithNoCred = Config.AzureSqlConnString + .AddManagedIdentityAuthenticationToConnString() + .AddUserToConnString(userId); SqlException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); + // The Azure.Identity surface message can vary across SDK versions and + // platforms, so assert on the stable driver-emitted error that proves + // the managed-identity auth path was taken and failed. Regex expected = new( - @"(\[Managed Identity\]|ManagedIdentityCredential) Authentication unavailable", + @"Failed to authenticate the user.*Authentication=ActiveDirectoryManagedIdentity", RegexOptions.IgnoreCase); Assert.Matches(expected, e.GetBaseException().Message); @@ -73,13 +80,13 @@ public static void ActiveDirectoryManagedIdentityWithInvalidUserIdMustFail(strin [ConditionalFact( typeof(Config), nameof(Config.OnAdoPool), - nameof(Config.HasPasswordConnectionString), + nameof(Config.HasAzureSqlConnectionString), nameof(Config.HasUserManagedIdentityClientId))] public static void ActiveDirectoryDefaultMustPass() { - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = RemoveKeysInConnStr(Config.PasswordConnectionString, credKeys) + - $"Authentication=ActiveDirectoryDefault;User ID={Config.UserManagedIdentityClientId};"; + string connStr = Config.AzureSqlConnString + .AddAADDefaultAuthenticationToConnString() + .AddUserToConnString(Config.UserManagedIdentityClientId); // Connection should be established using Managed Identity by default. ConnectAndDisconnect(connStr); @@ -105,9 +112,9 @@ public static void ActiveDirectoryDefaultMustPass() public static void ADIntegratedUsingSSPI() { // test Passes with correct connection string. - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connStr = RemoveKeysInConnStr(Config.TcpConnectionString, removeKeys) + - $"Authentication=Active Directory Integrated;"; + string connStr = Config.TcpConnectionString + .RemoveAuthAndCredsProperties() + .AddAADIntegratedAuthenticationToConnString(); ConnectAndDisconnect(connStr); } @@ -115,25 +122,26 @@ public static void ADIntegratedUsingSSPI() typeof(Config), nameof(Config.SupportsManagedIdentity), nameof(Config.SupportsSystemAssignedManagedIdentity), - nameof(Config.HasPasswordConnectionString))] + nameof(Config.HasAzureSqlConnectionString))] public static void SystemAssigned_ManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = RemoveKeysInConnStr(Config.PasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Managed Identity;"; + string connStr = Config.AzureSqlConnString + .AddManagedIdentityAuthenticationToConnString(); + ConnectAndDisconnect(connStr); } [ConditionalFact( typeof(Config), nameof(Config.OnAdoPool), - nameof(Config.HasPasswordConnectionString), + nameof(Config.HasAzureSqlConnectionString), nameof(Config.HasUserManagedIdentityClientId))] public static void UserAssigned_ManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = RemoveKeysInConnStr(Config.PasswordConnectionString, removeKeys) + - $"Authentication=Active Directory Managed Identity; User Id={Config.UserManagedIdentityClientId};"; + string connStr = Config.AzureSqlConnString + .AddManagedIdentityAuthenticationToConnString() + .AddUserToConnString(Config.UserManagedIdentityClientId); + ConnectAndDisconnect(connStr); } @@ -145,16 +153,14 @@ public static void UserAssigned_ManagedIdentityTest() nameof(Config.IsAzureSqlServer))] public static void Azure_SystemManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = RemoveKeysInConnStr(Config.TcpConnectionString, removeKeys) - + $"Authentication=Active Directory Managed Identity;"; + string connectionString = Config.TcpConnectionString + .RemoveAuthAndCredsProperties() + .AddManagedIdentityAuthenticationToConnString(); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.Open(); + using SqlConnection conn = new(connectionString); + conn.Open(); - Assert.Equal(System.Data.ConnectionState.Open, conn.State); - } + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } [ConditionalFact( @@ -166,16 +172,15 @@ public static void Azure_SystemManagedIdentityTest() nameof(Config.IsAzureSqlServer))] public static void Azure_UserManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = RemoveKeysInConnStr(Config.TcpConnectionString, removeKeys) - + $"Authentication=Active Directory Managed Identity; User Id={Config.UserManagedIdentityClientId}"; + string connectionString = Config.TcpConnectionString + .RemoveAuthAndCredsProperties() + .AddManagedIdentityAuthenticationToConnString() + .AddUserToConnString(Config.UserManagedIdentityClientId); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.Open(); + using SqlConnection conn = new(connectionString); + conn.Open(); - Assert.Equal(System.Data.ConnectionState.Open, conn.State); - } + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } // The helpers below were copied verbatim from AADConnectionTest.cs and ManualTests @@ -203,36 +208,6 @@ private static void ConnectAndDisconnect( #region Helpers from ManualTests DataTestUtility.cs - public static string RemoveKeysInConnStr(string connStr, string[] keysToRemove) - { - // tokenize connection string and remove input keys. - string res = ""; - if (connStr != null && keysToRemove != null) - { - string[] keys = connStr.Split(';'); - foreach (var key in keys) - { - if (!string.IsNullOrEmpty(key.Trim())) - { - bool removeKey = false; - foreach (var keyToRemove in keysToRemove) - { - if (key.Trim().ToLower().StartsWith(keyToRemove.Trim().ToLower(), StringComparison.Ordinal)) - { - removeKey = true; - break; - } - } - if (!removeKey) - { - res += key + ";"; - } - } - } - } - return res; - } - public static string? FetchKeyInConnStr(string connStr, string[] keys) { // tokenize connection string and find matching key diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj index 1c020c2ae4..067e31f0b5 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj @@ -47,6 +47,9 @@ Condition="'$(ReferenceType)' == 'Package'"/> + + + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Config.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Config.cs index 1f0587685e..a717142ee9 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Config.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Config.cs @@ -40,8 +40,7 @@ internal static class Config internal static bool DebugEmit { get; } = false; internal static bool IntegratedSecuritySupported { get; } = false; internal static bool ManagedIdentitySupported { get; } = false; - // @TODO Remove PasswordConnectionString from config; AAD Password auth is deprecated - internal static string PasswordConnectionString { get; } = string.Empty; + internal static string AzureSqlConnString { get; } = string.Empty; internal static string ServicePrincipalId { get; } = string.Empty; internal static string ServicePrincipalSecret { get; } = string.Empty; internal static string SystemAccessToken { get; } = string.Empty; @@ -56,7 +55,7 @@ internal static class Config #region Conditional Fact/Theory Helpers - internal static bool HasPasswordConnectionString() => !PasswordConnectionString.IsEmpty(); + internal static bool HasAzureSqlConnectionString() => !AzureSqlConnString.IsEmpty(); internal static bool HasServicePrincipal() => !ServicePrincipalId.IsEmpty() && !ServicePrincipalSecret.IsEmpty(); internal static bool HasSystemAccessToken() => !SystemAccessToken.IsEmpty(); internal static bool HasTcpConnectionString() => !TcpConnectionString.IsEmpty(); @@ -117,7 +116,7 @@ static Config() // IntegratedSecuritySupported = GetBool(root, "SupportsIntegratedSecurity"); ManagedIdentitySupported = GetBool(root, "ManagedIdentitySupported"); - PasswordConnectionString = GetString(root, "AADPasswordConnectionString"); + AzureSqlConnString = GetString(root, "AzureSqlConnectionString"); ServicePrincipalId = GetString(root, "AADServicePrincipalId"); ServicePrincipalSecret = GetString(root, "AADServicePrincipalSecret"); SystemAssignedManagedIdentitySupported = @@ -164,9 +163,9 @@ string Base64Encode(string s) Console.WriteLine( $" ManagedIdentitySupported: {ManagedIdentitySupported}"); Console.WriteLine( - $" PasswordConnectionString: {PasswordConnectionString}"); + $" AzureSqlConnectionString: {AzureSqlConnString}"); Console.WriteLine( - $" {Base64Encode(PasswordConnectionString)}"); + $" {Base64Encode(AzureSqlConnString)}"); Console.WriteLine( $" ServicePrincipalId: {ServicePrincipalId}"); Console.WriteLine( diff --git a/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs index eed5c58a69..9497aa0605 100644 --- a/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/src/Resources/Strings.Designer.cs @@ -3048,15 +3048,6 @@ internal static string SQL_CannotFindActiveDirectoryAuthProvider { } } - /// - /// Looks up a localized string similar to Setting 'useWamBroker' requires the 'Microsoft.Data.SqlClient.Extensions.Azure' package to expose 'Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProviderOptions'. Upgrade the 'Microsoft.Data.SqlClient.Extensions.Azure' package to a version that includes this type.. - /// - internal static string SQL_UseWamBrokerRequiresAzureExtensionUpgrade { - get { - return ResourceManager.GetString("SQL_UseWamBrokerRequiresAzureExtensionUpgrade", resourceCulture); - } - } - /// /// Looks up a localized string similar to Cannot find an authentication provider for '{0}'.. /// @@ -4245,6 +4236,15 @@ internal static string SQL_UserInstanceFailure { } } + /// + /// Looks up a localized string similar to Setting 'useWamBroker' requires the 'Microsoft.Data.SqlClient.Extensions.Azure' package to expose 'Microsoft.Data.SqlClient.ActiveDirectoryAuthenticationProviderOptions'. Upgrade the 'Microsoft.Data.SqlClient.Extensions.Azure' package to at least v1.1.0 that includes this type.. + /// + internal static string SQL_UseWamBrokerRequiresAzureExtensionUpgrade { + get { + return ResourceManager.GetString("SQL_UseWamBrokerRequiresAzureExtensionUpgrade", resourceCulture); + } + } + /// /// Looks up a localized string similar to Invalid attempt to get vector data from column '{0}'. Vectors are only supported for columns of type vector.. /// diff --git a/src/Microsoft.Data.SqlClient/tests/Common/CommonUtils.cs b/src/Microsoft.Data.SqlClient/tests/Common/CommonUtils.cs new file mode 100644 index 0000000000..abf2903258 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/tests/Common/CommonUtils.cs @@ -0,0 +1,49 @@ +// 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.Security; + +namespace Microsoft.Data.SqlClient.Tests.Common; + +public static class CommonUtils +{ + // Ensures the base connection string ends with ';' before appending a new keyword. + public static string EnsureSeparator(string connectionString) + => string.IsNullOrEmpty(connectionString) || connectionString.EndsWith(";", StringComparison.Ordinal) ? connectionString : connectionString + ';'; + + // Returns randomly generated characters of specified length. + public static SecureString GenerateRandomSecureString(int length = 10) + { + SecureString secureString = new(); + + byte[] bytes = new byte[length]; + using (System.Security.Cryptography.RandomNumberGenerator rng = System.Security.Cryptography.RandomNumberGenerator.Create()) + { + rng.GetBytes(bytes); + } + + // Map random bytes into the printable ASCII range [33, 126). + for (int i = 0; i < length; i++) + { + secureString.AppendChar((char)(33 + (bytes[i] % 93))); + } + + secureString.MakeReadOnly(); + return secureString; + } + + // Returns randomly generated characters of specified length with a prefix. + public static string GenerateRandomCharacters(string prefix, int length = 11) + { + string path = Path.GetRandomFileName(); + path = path.Replace(".", ""); // Remove period. + return string.Concat(prefix, path.Substring(0, length)); + } + + public static string GenerateObjectName() + { + return string.Format("TEST_{0}{1}{2}", Environment.GetEnvironmentVariable("ComputerName"), Environment.TickCount, Guid.NewGuid()).Replace('-', '_'); + } + +} diff --git a/src/Microsoft.Data.SqlClient/tests/Common/StringExtensions.cs b/src/Microsoft.Data.SqlClient/tests/Common/StringExtensions.cs new file mode 100644 index 0000000000..1de2269386 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/tests/Common/StringExtensions.cs @@ -0,0 +1,153 @@ +// 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.Net; +using System.Security; +using static Microsoft.Data.SqlClient.Tests.Common.CommonUtils; + +namespace Microsoft.Data.SqlClient.Tests.Common +{ + /// + /// Extension methods for string class to add connection string keywords to connection string + /// for testing connection string parsing logic + /// + public static class StringExtensions + { + /// + /// Adds a user provided or a dummy user to the connection string to test the connection string parsing logic + /// + public static string AddUserToConnString(this string connectionString, string? user = null) + => EnsureSeparator(connectionString) + "UID=" + (user ?? "DummyUser") + ';'; + + /// + /// Adds user provided or a dummy password to the connection string to test the connection string parsing logic + /// + public static string AddPasswordToConnString(this string connectionString, string? password = null) + { + string? pwd = password; + if(string.IsNullOrEmpty(pwd)) + { + using SecureString secureString = CommonUtils.GenerateRandomSecureString(20); + pwd = new NetworkCredential(string.Empty, secureString).Password; + } + return EnsureSeparator(connectionString) + "PWD=" + pwd + ';'; + } + + /// + /// Adds integrated security to the connection string to test the connection string parsing logic + /// + public static string AddIntegratedSecurityToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Integrated Security=True;"; + + /// + /// Adds AAD password authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADPasswordAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryPassword;"; + + /// + /// Adds AAD integrated authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADIntegratedAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryIntegrated;"; + + /// + /// Adds AAD interactive authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADInteractiveAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryInteractive;"; + + /// + /// Adds AAD device code flow authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADDeviceCodeFlowAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryDeviceCodeFlow;"; + + /// + /// Adds AAD service principal authentication to the connection string to test the connection string parsing logic + /// + /// + /// + public static string AddServicePrincipalAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryServicePrincipal;"; + + /// + /// Adds AAD workload identity authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADWorkloadIdentityAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryWorkloadIdentity;"; + + /// + /// Adds AAD MSI authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADMSIAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryMSI;"; + + /// + /// Adds AAD default authentication to the connection string to test the connection string parsing logic + /// + public static string AddAADDefaultAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryDefault;"; + + /// + /// Adds an invalid AAD authentication to the connection string to test the connection string parsing logic + /// + public static string AddInvalidAADAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryInvalid;"; + + /// + /// Adds managed identity authentication to the connection string to test the connection string parsing logic + /// + public static string AddManagedIdentityAuthenticationToConnString(this string connectionString) + => EnsureSeparator(connectionString) + "Authentication=ActiveDirectoryManagedIdentity;"; + + /// + /// Removes the authentication and credential properties from the connection string. The properties removed are: "Authentication", "User ID", "Password", "UID", and "PWD". + /// This is useful for testing scenarios where you want to ensure that the connection string does not contain any sensitive information related to authentication or credentials. + /// + /// + /// + public static string RemoveAuthAndCredsProperties(this string connectionString) + { + string[] removeKeys = ["Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security"]; + return RemoveKeysInConnStr(connectionString, removeKeys); + } + + /// + /// Removes the specified keys from the connection string. The keys are case-insensitive and will be removed if they match the start of a key in the connection string. + /// + /// The connection string to modify. + /// The keys to remove from the connection string. + /// The modified connection string with the specified keys removed. + public static string RemoveKeysInConnStr(this string connStr, string[] keysToRemove) + { + // tokenize connection string and remove input keys. + string res = ""; + if (connStr != null && keysToRemove != null) + { + string[] keys = connStr.Split(';'); + foreach (var key in keys) + { + if (!string.IsNullOrEmpty(key.Trim())) + { + bool removeKey = false; + foreach (var keyToRemove in keysToRemove) + { + if (key.Trim().ToLower().StartsWith(keyToRemove.Trim().ToLower(), StringComparison.Ordinal)) + { + removeKey = true; + break; + } + } + if (!removeKey) + { + res += key + ";"; + } + } + } + } + return res; + } + } +} diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index 9bf1c0f519..84b51a864e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -22,6 +22,7 @@ using System.Threading.Tasks; using Azure.Core; using Azure.Identity; +using Microsoft.Data.SqlClient.Tests.Common; using Microsoft.Data.SqlClient.Tests.Common.Fixtures.DatabaseObjects; using Microsoft.Data.SqlClient.TestUtilities; using Microsoft.Identity.Client; @@ -38,7 +39,7 @@ public static class DataTestUtility public static readonly string TCPConnectionStringNoneVBS = null; public static readonly string TCPConnectionStringAASSGX = null; public static readonly string AADAuthorityURL = null; - public static readonly string AADPasswordConnectionString = null; + public static readonly string AzureSqlConnectionString = null; public static readonly string AADServicePrincipalId = null; public static readonly string AADServicePrincipalSecret = null; public static readonly string AKVOriginalUrl = null; @@ -66,9 +67,9 @@ public static class DataTestUtility public static readonly string EnclaveAzureDatabaseConnString = null; - public static bool ManagedIdentitySupported = true; + public static bool IsUserManagedIdentitySupported = true; public static string AADAccessToken = null; - public static bool SupportsSystemAssignedManagedIdentity = false; + public static bool IsSystemManagedIdentitySupported = false; public static string AADSystemIdentityAccessToken = null; public static string AADUserIdentityAccessToken = null; public const string ApplicationClientId = "2fd908ad-0664-4344-b9be-cd3e8b574c38"; @@ -254,7 +255,7 @@ static DataTestUtility() TCPConnectionStringNoneVBS = c.TCPConnectionStringNoneVBS; TCPConnectionStringAASSGX = c.TCPConnectionStringAASSGX; AADAuthorityURL = c.AADAuthorityURL; - AADPasswordConnectionString = c.AADPasswordConnectionString; + AzureSqlConnectionString = c.AzureSqlConnectionString; AADServicePrincipalId = c.AADServicePrincipalId; AADServicePrincipalSecret = c.AADServicePrincipalSecret; LocalDbAppName = c.LocalDbAppName; @@ -274,7 +275,7 @@ static DataTestUtility() PowerShellPath = c.PowerShellPath; KerberosDomainPassword = c.KerberosDomainPassword; KerberosDomainUser = c.KerberosDomainUser; - ManagedIdentitySupported = c.ManagedIdentitySupported; + IsUserManagedIdentitySupported = c.ManagedIdentitySupported; IsManagedInstance = c.IsManagedInstance; AliasName = c.AliasName; @@ -336,7 +337,7 @@ static DataTestUtility() // globally. SqlAuthenticationProvider.SetProvider( SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, - new ManagedIdentityProvider()); + new UserAssignedManagedIdentityProvider()); } public static IEnumerable ConnectionStrings => GetConnectionStrings(withEnclave: true); @@ -610,35 +611,17 @@ public static bool AreConnStringSetupForAE() public static bool IsSGXEnclaveConnStringSetup() => !string.IsNullOrEmpty(TCPConnectionStringAASSGX); - public static bool IsAADPasswordConnStrSetup() - { - return !string.IsNullOrEmpty(AADPasswordConnectionString); - } + public static bool IsAzureConnStringSetup() => !string.IsNullOrEmpty(AzureSqlConnectionString); - public static bool IsAADServicePrincipalSetup() - { - return !string.IsNullOrEmpty(AADServicePrincipalId) && !string.IsNullOrEmpty(AADServicePrincipalSecret); - } + public static bool IsAADServicePrincipalSetup() => !string.IsNullOrEmpty(AADServicePrincipalId) && !string.IsNullOrEmpty(AADServicePrincipalSecret); - public static bool IsAADAuthorityURLSetup() - { - return !string.IsNullOrEmpty(AADAuthorityURL); - } + public static bool IsAADAuthorityURLSetup() => !string.IsNullOrEmpty(AADAuthorityURL); - public static bool IsNotAzureServer() - { - return !AreConnStringsSetup() || !Utils.IsAzureSqlServer(new SqlConnectionStringBuilder(TCPConnectionString).DataSource); - } + public static bool IsNotAzureServer() => !AreConnStringsSetup() || !Utils.IsAzureSqlServer(new SqlConnectionStringBuilder(TCPConnectionString).DataSource); - public static bool IsAzureServer() - { - return AreConnStringsSetup() && Utils.IsAzureSqlServer(new SqlConnectionStringBuilder(TCPConnectionString).DataSource); - } + public static bool IsAzureServer() => AreConnStringsSetup() && Utils.IsAzureSqlServer(new SqlConnectionStringBuilder(TCPConnectionString).DataSource); - public static bool IsNotNamedInstance() - { - return !AreConnStringsSetup() || !new SqlConnectionStringBuilder(TCPConnectionString).DataSource.Contains(@"\"); - } + public static bool IsNotNamedInstance() => !AreConnStringsSetup() || !new SqlConnectionStringBuilder(TCPConnectionString).DataSource.Contains(@"\"); public static bool IsLocalHost() { @@ -648,21 +631,21 @@ public static bool IsLocalHost() // Synapse: Always Encrypted is not supported with Azure Synapse. // Ref: https://feedback.azure.com/forums/307516-azure-synapse-analytics/suggestions/17858869-support-always-encrypted-in-sql-data-warehouse - public static bool IsAKVSetupAvailable() - { - return AKVBaseUri != null && !string.IsNullOrEmpty(UserManagedIdentityClientId) && !string.IsNullOrEmpty(AKVTenantId) && IsNotAzureSynapse(); - } + public static bool IsAKVSetupAvailable() => AKVBaseUri != null && !string.IsNullOrEmpty(UserManagedIdentityClientId) && !string.IsNullOrEmpty(AKVTenantId) && IsNotAzureSynapse(); - private static readonly DefaultAzureCredential s_defaultCredential = new(new DefaultAzureCredentialOptions { ManagedIdentityClientId = UserManagedIdentityClientId }); + private static readonly DefaultAzureCredential s_defaultCredential = + new(new DefaultAzureCredentialOptions { ManagedIdentityClientId = UserManagedIdentityClientId }); - public static TokenCredential GetTokenCredential() - { - return s_defaultCredential; - } + public static string GetUserIdentityConnectionString() + => AzureSqlConnectionString + .AddManagedIdentityAuthenticationToConnString() + .AddUserToConnString(UserManagedIdentityClientId); + + public static TokenCredential GetTokenCredential() => s_defaultCredential; public static bool IsTargetReadyForAeWithKeyStore() { - return DataTestUtility.AreConnStringSetupForAE() + return AreConnStringSetupForAE() #if !NETFRAMEWORK // AE tests on Windows will use the Cert Store. On non-Windows, they require AKV. && (OperatingSystem.IsWindows() || DataTestUtility.IsAKVSetupAvailable()) @@ -698,30 +681,26 @@ public static bool IsUTF8Supported() bool retval = false; if (AreConnStringsSetup() && IsNotAzureSynapse()) { - using (SqlConnection connection = new SqlConnection(TCPConnectionString)) - using (SqlCommand command = new SqlCommand()) - { - command.Connection = connection; - command.CommandText = "SELECT CONNECTIONPROPERTY('SUPPORT_UTF8')"; - connection.Open(); + using SqlConnection connection = new SqlConnection(TCPConnectionString); + using SqlCommand command = new SqlCommand(); + command.Connection = connection; + command.CommandText = "SELECT CONNECTIONPROPERTY('SUPPORT_UTF8')"; + connection.Open(); - using (SqlDataReader reader = command.ExecuteReader()) + using (SqlDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) { - while (reader.Read()) - { - // CONNECTIONPROPERTY('SUPPORT_UTF8') returns NULL in SQLServer versions that don't support UTF-8. - retval = !reader.IsDBNull(0); - } + // CONNECTIONPROPERTY('SUPPORT_UTF8') returns NULL in SQLServer versions that don't support UTF-8. + retval = !reader.IsDBNull(0); } } } return retval; } - public static bool IsTCPConnectionStringPasswordIncluded() - { - return RetrieveValueFromConnStr(TCPConnectionString, new string[] { "Password", "PWD" }) != string.Empty; - } + public static bool IsTCPConnectionStringPasswordIncluded() => + RetrieveValueFromConnStr(TCPConnectionString, ["Password", "PWD"]) != string.Empty; public static bool DoesHostAddressContainBothIPv4AndIPv6() { @@ -729,12 +708,10 @@ public static bool DoesHostAddressContainBothIPv4AndIPv6() { return false; } - using (var connection = new SqlConnection(DNSCachingConnString)) - { - List ipAddresses = Dns.GetHostAddresses(connection.DataSource).ToList(); - return ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetwork) && - ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetworkV6); - } + using var connection = new SqlConnection(DNSCachingConnString); + List ipAddresses = Dns.GetHostAddresses(connection.DataSource).ToList(); + return ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetwork) && + ipAddresses.Exists(ip => ip.AddressFamily == AddressFamily.InterNetworkV6); } public static string GetShortName(string prefix, bool withBracket = true) => @@ -810,48 +787,42 @@ public static void DropDatabase(SqlConnection sqlConnection, string dbName) public static bool IsLocalDBInstalled() => !string.IsNullOrEmpty(LocalDbAppName?.Trim()) && IsIntegratedSecuritySetup(); public static bool IsLocalDbSharedInstanceSetup() => !string.IsNullOrEmpty(LocalDbSharedInstanceName?.Trim()) && IsIntegratedSecuritySetup(); public static bool IsIntegratedSecuritySetup() => SupportsIntegratedSecurity; + public static async Task IsAccessTokenAsyncSetup() => + !string.IsNullOrEmpty(await GetSystemIdentityAccessTokenAsync()) + || !string.IsNullOrEmpty(await GetUserIdentityAccessTokenAsync()); - public static string GetAccessToken() - { - if (AADAccessToken == null && IsAADPasswordConnStrSetup() && IsAADAuthorityURLSetup()) - { - string username = RetrieveValueFromConnStr(AADPasswordConnectionString, new string[] { "User ID", "UID" }); - string password = RetrieveValueFromConnStr(AADPasswordConnectionString, new string[] { "Password", "PWD" }); - AADAccessToken = GenerateAccessToken(AADAuthorityURL, username, password); - } - // Creates a new Object Reference of Access Token - See GitHub Issue 438 - return AADAccessToken != null ? new string(AADAccessToken.ToCharArray()) : null; - } + public static Task GetAccessTokenAsync() => + IsUserManagedIdentitySupported ? GetUserIdentityAccessTokenAsync() : + (IsSystemManagedIdentitySupported ? GetSystemIdentityAccessTokenAsync() : + Task.FromResult(null)); - public static string GetSystemIdentityAccessToken() + public static async Task GetSystemIdentityAccessTokenAsync() { - if (ManagedIdentitySupported && SupportsSystemAssignedManagedIdentity && AADSystemIdentityAccessToken == null && IsAADPasswordConnStrSetup()) + if (IsSystemManagedIdentitySupported && AADSystemIdentityAccessToken == null && IsAzureConnStringSetup()) { - AADSystemIdentityAccessToken = AADUtility.GetManagedIdentityToken().GetAwaiter().GetResult(); + AADSystemIdentityAccessToken = await AADUtility.GetManagedIdentityToken(); if (AADSystemIdentityAccessToken == null) { - ManagedIdentitySupported = false; + IsSystemManagedIdentitySupported = false; } } return AADSystemIdentityAccessToken != null ? new string(AADSystemIdentityAccessToken.ToCharArray()) : null; } - public static string GetUserIdentityAccessToken() + public static async Task GetUserIdentityAccessTokenAsync() { - if (ManagedIdentitySupported && AADUserIdentityAccessToken == null && IsAADPasswordConnStrSetup()) + if (IsUserManagedIdentitySupported && AADUserIdentityAccessToken == null && IsAzureConnStringSetup()) { // Pass User Assigned Managed Identity Client Id here. - AADUserIdentityAccessToken = AADUtility.GetManagedIdentityToken(UserManagedIdentityClientId).GetAwaiter().GetResult(); + AADUserIdentityAccessToken = await AADUtility.GetManagedIdentityToken(UserManagedIdentityClientId); if (AADUserIdentityAccessToken == null) { - ManagedIdentitySupported = false; + IsUserManagedIdentitySupported = false; } } return AADUserIdentityAccessToken != null ? new string(AADUserIdentityAccessToken.ToCharArray()) : null; } - public static bool IsAccessTokenSetup() => !string.IsNullOrEmpty(GetAccessToken()); - public static bool IsFileStreamSetup() => !string.IsNullOrEmpty(FileStreamDirectory) && IsNotAzureServer() && IsNotAzureSynapse(); private static bool CheckException(Exception ex, string exceptionMessage, bool innerExceptionMustBeNull) where TException : Exception @@ -913,7 +884,7 @@ public static TException AssertThrowsInner( TException ex = AssertThrows(actionThatFails, exceptionMessage); Assert.NotNull(ex.InnerException); - Assert.IsAssignableFrom(ex.InnerException); + Assert.IsType(ex.InnerException, exactMatch: false); if (innerExceptionMessage != null) { @@ -979,19 +950,6 @@ public static TException ExpectFailure(Action actionThatFails, strin } } - public static string GenerateObjectName() - { - return string.Format("TEST_{0}{1}{2}", Environment.GetEnvironmentVariable("ComputerName"), Environment.TickCount, Guid.NewGuid()).Replace('-', '_'); - } - - // Returns randomly generated characters of length 11. - public static string GenerateRandomCharacters(string prefix) - { - string path = Path.GetRandomFileName(); - path = path.Replace(".", ""); // Remove period. - return prefix + path; - } - public static void RunNonQuery(string connectionString, string sql, int numberOfRetries = 0) { int retries = 0; @@ -999,14 +957,12 @@ public static void RunNonQuery(string connectionString, string sql, int numberOf { try { - using (SqlConnection connection = new SqlConnection(connectionString)) - using (SqlCommand command = connection.CreateCommand()) - { - connection.Open(); - command.CommandText = sql; - command.ExecuteNonQuery(); - break; - } + using SqlConnection connection = new(connectionString); + using SqlCommand command = connection.CreateCommand(); + connection.Open(); + command.CommandText = sql; + command.ExecuteNonQuery(); + break; } catch (Exception) { @@ -1088,36 +1044,6 @@ public static string FetchKeyInConnStr(string connStr, string[] keys) return null; } - public static string RemoveKeysInConnStr(string connStr, string[] keysToRemove) - { - // tokenize connection string and remove input keys. - string res = ""; - if (connStr != null && keysToRemove != null) - { - string[] keys = connStr.Split(';'); - foreach (var key in keys) - { - if (!string.IsNullOrEmpty(key.Trim())) - { - bool removeKey = false; - foreach (var keyToRemove in keysToRemove) - { - if (key.Trim().ToLower().StartsWith(keyToRemove.Trim().ToLower(), StringComparison.Ordinal)) - { - removeKey = true; - break; - } - } - if (!removeKey) - { - res += key + ";"; - } - } - } - } - return res; - } - public static string RetrieveValueFromConnStr(string connStr, string[] keywords) { // tokenize connection string and retrieve value for a specific key. diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/ManagedIdentityProvider.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/ManagedIdentityProvider.cs index baafec4205..bc7cff7b61 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/ManagedIdentityProvider.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/ManagedIdentityProvider.cs @@ -14,7 +14,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests; -internal class ManagedIdentityProvider : SqlAuthenticationProvider +internal class UserAssignedManagedIdentityProvider : SqlAuthenticationProvider { // Our cache of managed identity user Ids to credential instances. private readonly ConcurrentDictionary diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/XEventScope.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/XEventScope.cs index ab89a97b10..f9e7df485e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/XEventScope.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/XEventScope.cs @@ -6,6 +6,7 @@ using System.Data; using System.Threading; using System.Xml; +using Microsoft.Data.SqlClient.Tests.Common; #nullable enable @@ -62,7 +63,7 @@ public XEventScope( string targetSpecification, ushort durationInMinutes = 5) { - SessionName = DataTestUtility.GenerateRandomCharacters(sessionName); + SessionName = CommonUtils.GenerateRandomCharacters(sessionName); _connection = connection; if (connection.State is not ConnectionState.Open) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AADFedAuthTokenRefreshTest/AADFedAuthTokenRefreshTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AADFedAuthTokenRefreshTest/AADFedAuthTokenRefreshTest.cs index e5616776b1..11b4e4e24b 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AADFedAuthTokenRefreshTest/AADFedAuthTokenRefreshTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AADFedAuthTokenRefreshTest/AADFedAuthTokenRefreshTest.cs @@ -20,22 +20,18 @@ public AADFedAuthTokenRefreshTest(ITestOutputHelper testOutputHelper) _testOutputHelper = testOutputHelper; } - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAADPasswordConnStrSetup))] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureConnStringSetup))] public void FedAuthTokenRefreshTest() { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity); try { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new UsernamePasswordProvider(DataTestUtility.ApplicationClientId)); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, new UserAssignedManagedIdentityProvider()); - string connectionString = DataTestUtility.AADPasswordConnectionString; + string connectionString = DataTestUtility.GetUserIdentityConnectionString(); - using SqlConnection connection = new SqlConnection(connectionString); + using SqlConnection connection = new(connectionString); connection.Open(); string oldTokenHash = ""; @@ -56,7 +52,7 @@ public void FedAuthTokenRefreshTest() Assert.True(result != string.Empty, "The connection's command must return a value"); // The new connection will use the same FedAuthToken but will refresh it first as it will expire in 1 minute. - using (SqlConnection connection2 = new SqlConnection(connectionString)) + using (SqlConnection connection2 = new(connectionString)) { connection2.Open(); @@ -80,9 +76,7 @@ public void FedAuthTokenRefreshTest() if (original is not null) { // Reset to driver internal provider. - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, original); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, original); } } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs index 960f3ee822..542ff0d392 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/AdapterTest/AdapterTest.cs @@ -12,6 +12,7 @@ using System.Reflection; using System.Text; using Xunit; +using Microsoft.Data.SqlClient.Tests.Common; namespace Microsoft.Data.SqlClient.ManualTesting.Tests { @@ -249,7 +250,7 @@ public void PrepUnprepTest() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] public void SqlVariantTest() { - string tableName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); // good test for null values and unicode strings using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) using (SqlCommand cmd = new SqlCommand(null, conn)) @@ -345,7 +346,7 @@ public void SqlVariantTest() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] public void ParameterTest_AllTypes() { - string procName = DataTestUtility.GenerateObjectName(); + string procName = CommonUtils.GenerateObjectName(); string spCreateAllTypes = "CREATE PROCEDURE " + procName + " " + "@Cnumeric numeric(10,2) OUTPUT, " + @@ -936,8 +937,8 @@ public void UpdateRefreshTest() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] public void UpdateNullTest() { - string tableName = DataTestUtility.GenerateObjectName(); - string procName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); + string procName = CommonUtils.GenerateObjectName(); string createTable = "CREATE TABLE " + tableName + "(cvarbin VARBINARY(7000), cimage IMAGE)"; string createSP = @@ -993,8 +994,8 @@ public void UpdateNullTest() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] public void UpdateOffsetTest() { - string tableName = DataTestUtility.GenerateObjectName(); - string procName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); + string procName = CommonUtils.GenerateObjectName(); string createTable = "CREATE TABLE " + tableName + "(cvarbin VARBINARY(7000), cimage IMAGE)"; string createSP = diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs index 4b63ff655f..aa282ad502 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectionPoolTest/ConnectionPoolTest.cs @@ -14,19 +14,19 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests { public class ConnectionPoolConnectionStringProvider : IEnumerable { - private static readonly string _TCPConnectionString = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { + private static readonly string s_tcpConnectionString = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = false, Pooling = true}.ConnectionString; - private static readonly string _tcpMarsConnStr = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { + private static readonly string s_tcpMarsConnStr = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true, Pooling = true }.ConnectionString; public IEnumerator GetEnumerator() { - yield return new object[] { _TCPConnectionString }; + yield return new object[] { s_tcpConnectionString }; if (DataTestUtility.IsNotAzureSynapse()) { - yield return new object[] { _tcpMarsConnStr }; + yield return new object[] { s_tcpMarsConnStr }; } } @@ -35,21 +35,21 @@ public IEnumerator GetEnumerator() public class ConnectionPoolConnectionStringAndPoolVersionProvider : IEnumerable { - private static readonly string _TCPConnectionString = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { + private static readonly string s_tcpConnectionString = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = false, Pooling = true }.ConnectionString; - private static readonly string _tcpMarsConnStr = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { + private static readonly string s_tcpMarsConnStr = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { MultipleActiveResultSets = true, Pooling = true }.ConnectionString; public IEnumerator GetEnumerator() { - yield return new object[] { _TCPConnectionString, false }; - yield return new object[] { _TCPConnectionString, true }; + yield return new object[] { s_tcpConnectionString, false }; + yield return new object[] { s_tcpConnectionString, true }; if (DataTestUtility.IsNotAzureSynapse()) { - yield return new object[] { _tcpMarsConnStr, false }; - yield return new object[] { _tcpMarsConnStr, true }; + yield return new object[] { s_tcpMarsConnStr, false }; + yield return new object[] { s_tcpMarsConnStr, true }; } } @@ -72,21 +72,21 @@ public static void BasicConnectionPoolingTest(string connectionString) InternalConnectionWrapper internalConnection; ConnectionPoolWrapper connectionPool; - using (SqlConnection connection = new SqlConnection(connectionString)) + using (SqlConnection connection = new(connectionString)) { connection.Open(); internalConnection = new InternalConnectionWrapper(connection); connectionPool = new ConnectionPoolWrapper(connection); } - using (SqlConnection connection2 = new SqlConnection(connectionString)) + using (SqlConnection connection2 = new(connectionString)) { connection2.Open(); Assert.True(internalConnection.IsInternalConnectionOf(connection2), "New connection does not use same internal connection"); Assert.True(connectionPool.ContainsConnection(connection2), "New connection is in a different pool"); } - using (SqlConnection connection3 = new SqlConnection(connectionString + ";App=SqlConnectionPoolUnitTest;")) + using (SqlConnection connection3 = new(connectionString + ";App=SqlConnectionPoolUnitTest;")) { connection3.Open(); Assert.False(internalConnection.IsInternalConnectionOf(connection3), "Connection with different connection string uses same internal connection"); @@ -95,7 +95,7 @@ public static void BasicConnectionPoolingTest(string connectionString) connectionPool.Cleanup(); - using (SqlConnection connection4 = new SqlConnection(connectionString)) + using (SqlConnection connection4 = new(connectionString)) { connection4.Open(); Assert.True(internalConnection.IsInternalConnectionOf(connection4), "New connection does not use same internal connection"); @@ -103,31 +103,27 @@ public static void BasicConnectionPoolingTest(string connectionString) } } - [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAADPasswordConnStrSetup), nameof(DataTestUtility.IsAADAuthorityURLSetup))] - public static void AccessTokenConnectionPoolingTest() + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureConnStringSetup), nameof(DataTestUtility.IsAADAuthorityURLSetup))] + public static async Task AccessTokenConnectionPoolingTest() { SqlConnection.ClearAllPools(); - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using SqlConnection connection = new SqlConnection(connectionString); - connection.AccessToken = DataTestUtility.GetAccessToken(); + using SqlConnection connection = new(DataTestUtility.AzureSqlConnectionString); + connection.AccessToken = await DataTestUtility.GetAccessTokenAsync(); connection.Open(); - InternalConnectionWrapper internalConnection = new InternalConnectionWrapper(connection); - ConnectionPoolWrapper connectionPool = new ConnectionPoolWrapper(connection); + InternalConnectionWrapper internalConnection = new(connection); + ConnectionPoolWrapper connectionPool = new(connection); connection.Close(); - using SqlConnection connection2 = new SqlConnection(connectionString); - connection2.AccessToken = DataTestUtility.GetAccessToken(); + using SqlConnection connection2 = new(DataTestUtility.AzureSqlConnectionString); + connection2.AccessToken = await DataTestUtility.GetAccessTokenAsync(); connection2.Open(); Assert.True(internalConnection.IsInternalConnectionOf(connection2), "New connection does not use same internal connection"); Assert.True(connectionPool.ContainsConnection(connection2), "New connection is in a different pool"); connection2.Close(); - using SqlConnection connection3 = new SqlConnection(connectionString + ";App=SqlConnectionPoolUnitTest;"); - connection3.AccessToken = DataTestUtility.GetAccessToken(); + using SqlConnection connection3 = new(DataTestUtility.AzureSqlConnectionString + ";App=SqlConnectionPoolUnitTest;"); + connection3.AccessToken = await DataTestUtility.GetAccessTokenAsync(); connection3.Open(); Assert.False(internalConnection.IsInternalConnectionOf(connection3), "Connection with different connection string uses same internal connection"); Assert.False(connectionPool.ContainsConnection(connection3), "Connection with different connection string uses same connection pool"); @@ -135,8 +131,8 @@ public static void AccessTokenConnectionPoolingTest() connectionPool.Cleanup(); - using SqlConnection connection4 = new SqlConnection(connectionString); - connection4.AccessToken = DataTestUtility.GetAccessToken(); + using SqlConnection connection4 = new(DataTestUtility.AzureSqlConnectionString); + connection4.AccessToken = await DataTestUtility.GetAccessTokenAsync(); connection4.Open(); Assert.True(internalConnection.IsInternalConnectionOf(connection4), "New connection does not use same internal connection"); Assert.True(connectionPool.ContainsConnection(connection4), "New connection is in a different pool"); @@ -156,21 +152,19 @@ public static void ClearAllPoolsTest(string connectionString, bool usePoolV2) SqlConnection.ClearAllPools(); Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); - using (SqlConnection connection = new SqlConnection(connectionString)) - { - connection.Open(); - ConnectionPoolWrapper pool = new ConnectionPoolWrapper(connection); - connection.Close(); - ConnectionPoolWrapper[] allPools = ConnectionPoolWrapper.AllConnectionPools(); + using SqlConnection connection = new(connectionString); + connection.Open(); + ConnectionPoolWrapper pool = new(connection); + connection.Close(); + ConnectionPoolWrapper[] allPools = ConnectionPoolWrapper.AllConnectionPools(); - DataTestUtility.AssertEqualsWithDescription(1, allPools.Length, "Incorrect number of pools exist."); - Assert.True(allPools[0].Equals(pool), "Saved pool is not in the list of all pools"); - DataTestUtility.AssertEqualsWithDescription(1, pool.ConnectionCount, "Saved pool has incorrect number of connections"); + DataTestUtility.AssertEqualsWithDescription(1, allPools.Length, "Incorrect number of pools exist."); + Assert.True(allPools[0].Equals(pool), "Saved pool is not in the list of all pools"); + DataTestUtility.AssertEqualsWithDescription(1, pool.ConnectionCount, "Saved pool has incorrect number of connections"); - SqlConnection.ClearAllPools(); - Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); - DataTestUtility.AssertEqualsWithDescription(0, pool.ConnectionCount, "Saved pool has incorrect number of connections."); - } + SqlConnection.ClearAllPools(); + Assert.True(0 == ConnectionPoolWrapper.AllConnectionPools().Length, "Pools exist after clearing all pools"); + DataTestUtility.AssertEqualsWithDescription(0, pool.ConnectionCount, "Saved pool has incorrect number of connections."); } /// @@ -181,7 +175,7 @@ public static void ClearAllPoolsTest(string connectionString, bool usePoolV2) [ClassData(typeof(ConnectionPoolConnectionStringProvider))] public static void ReclaimEmancipatedOnOpenTest(string connectionString) { - string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }).ConnectionString; + string newConnectionString = new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }.ConnectionString; SqlConnection.ClearAllPools(); InternalConnectionWrapper internalConnection = CreateEmancipatedConnection(newConnectionString); @@ -193,12 +187,10 @@ public static void ReclaimEmancipatedOnOpenTest(string connectionString) DataTestUtility.AssertEqualsWithDescription(1, connectionPool.ConnectionCount, "Wrong number of connections in the pool."); DataTestUtility.AssertEqualsWithDescription(0, connectionPool.FreeConnectionCount, "Wrong number of free connections in the pool."); - using (SqlConnection connection = new SqlConnection(newConnectionString)) - { - connection.Open(); - Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); - Assert.True(connectionPool.ContainsConnection(connection), "Connection is in wrong connection pool"); - } + using SqlConnection connection = new(newConnectionString); + connection.Open(); + Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); + Assert.True(connectionPool.ContainsConnection(connection), "Connection is in wrong connection pool"); } /// @@ -208,15 +200,15 @@ public static void ReclaimEmancipatedOnOpenTest(string connectionString) [ClassData(typeof(ConnectionPoolConnectionStringProvider))] public static void MaxPoolWaitForConnectionTest(string connectionString) { - string newConnectionString = (new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }).ConnectionString; + string newConnectionString = new SqlConnectionStringBuilder(connectionString) { MaxPoolSize = 1 }.ConnectionString; SqlConnection.ClearAllPools(); - using SqlConnection connection1 = new SqlConnection(newConnectionString); + using SqlConnection connection1 = new(newConnectionString); connection1.Open(); - InternalConnectionWrapper internalConnection = new InternalConnectionWrapper(connection1); - ConnectionPoolWrapper connectionPool = new ConnectionPoolWrapper(connection1); - ManualResetEventSlim taskAllowedToSpeak = new ManualResetEventSlim(false); + InternalConnectionWrapper internalConnection = new(connection1); + ConnectionPoolWrapper connectionPool = new(connection1); + using ManualResetEventSlim taskAllowedToSpeak = new(false); Task waitTask = Task.Factory.StartNew(() => MaxPoolWaitForConnectionTask(newConnectionString, internalConnection, connectionPool, taskAllowedToSpeak)); int count = 5; @@ -236,7 +228,7 @@ internal static InternalConnectionWrapper ReplacementConnectionUsesSemaphoreTask { InternalConnectionWrapper internalConnection = null; - using (SqlConnection connection = new SqlConnection(connectionString)) + using (SqlConnection connection = new(connectionString)) { try { @@ -257,14 +249,14 @@ internal static InternalConnectionWrapper ReplacementConnectionUsesSemaphoreTask private static InternalConnectionWrapper CreateEmancipatedConnection(string connectionString) { - SqlConnection connection = new SqlConnection(connectionString); + SqlConnection connection = new(connectionString); connection.Open(); return new InternalConnectionWrapper(connection); } private static void MaxPoolWaitForConnectionTask(string connectionString, InternalConnectionWrapper internalConnection, ConnectionPoolWrapper connectionPool, ManualResetEventSlim waitToSpeak) { - using SqlConnection connection = new SqlConnection(connectionString); + using SqlConnection connection = new(connectionString); connection.Open(); waitToSpeak.Wait(); Assert.True(internalConnection.IsInternalConnectionOf(connection), "Connection has wrong internal connection"); @@ -273,7 +265,7 @@ private static void MaxPoolWaitForConnectionTask(string connectionString, Intern internal static SqlConnection ReplacementConnectionObeys0TimeoutTask(string connectionString) { - SqlConnection connection = new SqlConnection(connectionString); + SqlConnection connection = new(connectionString); connection.Open(); return connection; } 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 b60b4a1e9e..94dfad1f45 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/AADConnectionTest.cs @@ -7,6 +7,7 @@ using System.Security; using System.Threading.Tasks; using Azure.Core; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -16,132 +17,106 @@ public class AADConnectionTest { private static void ConnectAndDisconnect(string connectionString, SqlCredential credential = null) { - using (SqlConnection conn = new SqlConnection(connectionString)) + using SqlConnection conn = new(connectionString); + if (credential != null) { - if (credential != null) - { - conn.Credential = credential; - } - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); + conn.Credential = credential; } + conn.Open(); + + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } private static bool AreConnStringsSetup() => DataTestUtility.AreConnStringsSetup(); private static bool IsAzure() => !DataTestUtility.IsNotAzureServer(); - private static bool IsAccessTokenSetup() => DataTestUtility.IsAccessTokenSetup(); - private static bool IsAADConnStringsSetup() => DataTestUtility.IsAADPasswordConnStrSetup(); - private static bool IsManagedIdentitySetup() => DataTestUtility.ManagedIdentitySupported; - private static bool SupportsSystemAssignedManagedIdentity() => DataTestUtility.SupportsSystemAssignedManagedIdentity; + private static bool IsAccessTokenSetup() => DataTestUtility.IsAccessTokenAsyncSetup().GetAwaiter().GetResult(); + private static bool IsAzureSqlConnStringSetup() => DataTestUtility.IsAzureConnStringSetup() && DataTestUtility.IsUserManagedIdentitySupported; + private static bool IsManagedIdentitySetup() => DataTestUtility.IsUserManagedIdentitySupported; + private static bool SupportsSystemAssignedManagedIdentity() => DataTestUtility.IsSystemManagedIdentitySupported; - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenTest() + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] + public static async Task AccessTokenTest() { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - connection.AccessToken = DataTestUtility.GetAccessToken(); - connection.Open(); + using SqlConnection connection = new(DataTestUtility.AzureSqlConnectionString); + connection.AccessToken = await DataTestUtility.GetAccessTokenAsync(); + await connection.OpenAsync(); - Assert.True(connection.State == System.Data.ConnectionState.Open); - } + Assert.Equal(System.Data.ConnectionState.Open, connection.State); } - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void InvalidAccessTokenTest() + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] + public static async Task InvalidAccessTokenTest() { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - - using (SqlConnection connection = new SqlConnection(connStr)) - { - connection.AccessToken = DataTestUtility.GetAccessToken() + "abc"; - SqlException e = Assert.Throws(() => connection.Open()); + using SqlConnection connection = new(DataTestUtility.AzureSqlConnectionString); + connection.AccessToken = await DataTestUtility.GetAccessTokenAsync() + "abc"; + SqlException e = Assert.Throws(() => connection.Open()); - string expectedMessage = "Login failed for user"; - Assert.Contains(expectedMessage, e.Message); - } + string expectedMessage = "Login failed for user"; + Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenWithAuthType() + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] + public static async Task AccessTokenWithAuthType() { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + using SqlConnection connection = new(DataTestUtility.AzureSqlConnectionString.AddManagedIdentityAuthenticationToConnString()); + InvalidOperationException e = await Assert.ThrowsAsync + (async () => + connection.AccessToken = await DataTestUtility.GetAccessTokenAsync() + ); - using (SqlConnection connection = new SqlConnection(connStr)) - { - InvalidOperationException e = Assert.Throws(() => - connection.AccessToken = DataTestUtility.GetAccessToken()); - - string expectedMessage = "Cannot set the AccessToken property if 'Authentication' has been specified in the connection string."; - Assert.Contains(expectedMessage, e.Message); - } + string expectedMessage = "Cannot set the AccessToken property if 'Authentication' has been specified in the connection string."; + Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] - public static void AccessTokenWithCred() + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] + public static async Task AccessTokenWithCred() { - // Remove cred info and add invalid token - string[] credKeys = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + string connString = DataTestUtility.AzureSqlConnectionString + .AddUserToConnString() + .AddPasswordToConnString(); - using (SqlConnection connection = new SqlConnection(connStr)) - { - InvalidOperationException e = Assert.Throws(() => - connection.AccessToken = DataTestUtility.GetAccessToken()); + using SqlConnection connection = new(connString); + InvalidOperationException e = await Assert.ThrowsAsync + (async () => + connection.AccessToken = await DataTestUtility.GetAccessTokenAsync() + ); - string expectedMessage = "Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string."; - Assert.Contains(expectedMessage, e.Message); - } + string expectedMessage = "Cannot set the AccessToken property if 'UserID', 'UID', 'Password', or 'PWD' has been specified in connection string."; + Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] public static void AccessTokenTestWithEmptyToken() { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); + string connStr = DataTestUtility.AzureSqlConnectionString; - using (SqlConnection connection = new SqlConnection(connStr)) - { - connection.AccessToken = ""; - SqlException e = Assert.Throws(() => connection.Open()); + using SqlConnection connection = new(connStr); + connection.AccessToken = ""; + SqlException e = Assert.Throws(() => connection.Open()); - string expectedMessage = "A connection was successfully established with the server, but then an error occurred during the login process."; - Assert.Contains(expectedMessage, e.Message); - } + string expectedMessage = "A connection was successfully established with the server, but then an error occurred during the login process."; + Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] public static void AccessTokenTestWithIntegratedSecurityTrue() { - // Remove cred info and add invalid token - string[] credKeys = { "User ID", "Password", "UID", "PWD", "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Integrated Security=True;"; + string connStr = DataTestUtility.AzureSqlConnectionString + .AddIntegratedSecurityToConnString(); - using (SqlConnection connection = new SqlConnection(connStr)) - { - InvalidOperationException e = Assert.Throws(() => connection.AccessToken = ""); + using SqlConnection connection = new(connStr); + InvalidOperationException e = Assert.Throws(() => connection.AccessToken = ""); - string expectedMessage = "Cannot set the AccessToken property if the 'Integrated Security' connection string keyword has been set to 'true' or 'SSPI'."; - Assert.Contains(expectedMessage, e.Message); - } + string expectedMessage = "Cannot set the AccessToken property if the 'Integrated Security' connection string keyword has been set to 'true' or 'SSPI'."; + Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAccessTokenSetup), nameof(IsAzureSqlConnStringSetup))] public static void InvalidAuthTypeTest() { - // Remove cred info and add invalid token - string[] credKeys = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + "Authentication=Active Directory Pass;"; + string connStr = DataTestUtility.AzureSqlConnectionString + .AddInvalidAADAuthenticationToConnString(); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); @@ -149,10 +124,14 @@ public static void InvalidAuthTypeTest() Assert.Contains(expectedMessage, e.Message, StringComparison.OrdinalIgnoreCase); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void AADPasswordWithIntegratedSecurityTrue() { - string connStr = DataTestUtility.AADPasswordConnectionString + "Integrated Security=True;"; + string connStr = DataTestUtility.AzureSqlConnectionString + .AddAADPasswordAuthenticationToConnString() + .AddUserToConnString() + .AddPasswordToConnString() + .AddIntegratedSecurityToConnString(); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); @@ -160,93 +139,53 @@ public static void AADPasswordWithIntegratedSecurityTrue() Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void GetAccessTokenByPasswordTest() + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] + public static void TestCustomProviderAuthentication() { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity); try { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new UsernamePasswordProvider(DataTestUtility.ApplicationClientId)); - #pragma warning restore 0618 // Type or member is obsolete - - using (SqlConnection connection = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) - { - connection.Open(); - Assert.True(connection.State == System.Data.ConnectionState.Open); - } - } - finally - { - if (original is not null) - { - // Reset to driver internal provider. - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, original); - #pragma warning restore 0618 // Type or member is obsolete - } - } - } + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, new UserAssignedManagedIdentityProvider()); - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void TestCustomProviderAuthentication() - { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword); - #pragma warning restore 0618 // Type or member is obsolete + string connStr = DataTestUtility.GetUserIdentityConnectionString(); + // Connect to Azure DB with managed identity and retrieve user name using custom authentication provider + using SqlConnection conn = new(connStr); - try - { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new UsernamePasswordProvider(DataTestUtility.ApplicationClientId)); - #pragma warning restore 0618 // Type or member is obsolete - // Connect to Azure DB with password and retrieve user name using custom authentication provider - using (SqlConnection conn = new SqlConnection(DataTestUtility.AADPasswordConnectionString)) - { - conn.Open(); - using (SqlCommand sqlCommand = new SqlCommand - ( - cmdText: $"SELECT SUSER_SNAME();", - connection: conn, - transaction: null - )) - { - string customerId = (string)sqlCommand.ExecuteScalar(); - string expected = DataTestUtility.RetrieveValueFromConnStr(DataTestUtility.AADPasswordConnectionString, new string[] { "User ID", "UID" }); - Assert.Equal(expected, customerId); - } - } + conn.Open(); + using SqlCommand sqlCommand = new( + cmdText: "SELECT SUSER_SNAME();", + connection: conn, + transaction: null); + string customerId = (string)sqlCommand.ExecuteScalar(); + Assert.Equal(DataTestUtility.UserManagedIdentityClientId, customerId); } finally { if (original is not null) { // Reset to driver internal provider. - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, original); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, original); } } } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryPasswordWithNoAuthType() { - // connection fails with expected error message. - string[] AuthKey = { "Authentication" }; - string connStrWithNoAuthType = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey); + string connStrWithNoAuthType = DataTestUtility.AzureSqlConnectionString + .AddUserToConnString() + .AddPasswordToConnString(); Assert.Throws(() => ConnectAndDisconnect(connStrWithNoAuthType)); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] - public static void IntegratedAuthWithCred() + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] + public static void AADIntegratedAuthWithCred() { - // connection fails with expected error message. - string[] AuthKey = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey) + "Authentication=Active Directory Integrated;"; + string connStr = DataTestUtility.AzureSqlConnectionString + .AddAADIntegratedAuthenticationToConnString() + .AddUserToConnString() + .AddPasswordToConnString(); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); string[] expectedMessage = { "Cannot use 'Authentication=Active Directory Integrated' with 'User ID', 'UID', 'Password' or 'PWD' connection string keywords.", //netfx @@ -254,101 +193,85 @@ public static void IntegratedAuthWithCred() Assert.Contains(e.Message, expectedMessage); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void MFAAuthWithPassword() { // connection fails with expected error message. - string[] AuthKey = { "Authentication" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, AuthKey) + "Authentication=Active Directory Interactive;"; + string connStr = DataTestUtility.AzureSqlConnectionString + .AddAADInteractiveAuthenticationToConnString() + .AddUserToConnString() + .AddPasswordToConnString(); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStr)); string expectedMessage = "Cannot use 'Authentication=Active Directory Interactive' with 'Password' or 'PWD' connection string keywords."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryDeviceCodeFlowWithUserIdMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithUID = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Device Code Flow; UID=someuser;"; + string connStrWithUID = DataTestUtility.AzureSqlConnectionString + .AddAADDeviceCodeFlowAuthenticationToConnString() + .AddUserToConnString("someuser"); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithUID)); string expectedMessage = "Cannot use 'Authentication=Active Directory Device Code Flow' with 'User ID', 'UID', 'Password' or 'PWD' connection string keywords."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryDeviceCodeFlowWithCredentialsMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Device Code Flow;"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADDeviceCodeFlowAuthenticationToConnString(); - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); + using SecureString str = CommonUtils.GenerateRandomSecureString(10); + SqlCredential credential = new("someuser", str); InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Device Code Flow' has been specified in the connection string."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryManagedIdentityWithCredentialsMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Managed Identity;"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddManagedIdentityAuthenticationToConnString(); - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); + using SecureString str = CommonUtils.GenerateRandomSecureString(10); + SqlCredential credential = new("someuser", str); InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Managed Identity' has been specified in the connection string."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryWorkloadIdentityWithCredentialsMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Workload Identity;"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADWorkloadIdentityAuthenticationToConnString(); - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); + using SecureString str = CommonUtils.GenerateRandomSecureString(10); + SqlCredential credential = new("someuser", str); InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Workload Identity' has been specified in the connection string."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup), nameof(IsManagedIdentitySetup))] public static void ActiveDirectoryManagedIdentityWithPasswordMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Managed Identity; Password=anything"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddManagedIdentityAuthenticationToConnString() + .AddPasswordToConnString("anything"); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); @@ -356,34 +279,29 @@ public static void ActiveDirectoryManagedIdentityWithPasswordMustFail() Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryMSIWithCredentialsMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory MSI;"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADMSIAuthenticationToConnString(); - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); + using SecureString str = CommonUtils.GenerateRandomSecureString(10); + SqlCredential credential = new("someuser", str); + InvalidOperationException e = Assert.Throws + (() => ConnectAndDisconnect(connStrWithNoCred, credential)); string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory MSI' has been specified in the connection string."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryMSIWithPasswordMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=ActiveDirectoryMSI; Password=anything"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADMSIAuthenticationToConnString() + .AddPasswordToConnString(); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); @@ -391,34 +309,30 @@ public static void ActiveDirectoryMSIWithPasswordMustFail() Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryDefaultWithCredentialsMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=Active Directory Default;"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADDefaultAuthenticationToConnString(); - SecureString str = new SecureString(); - foreach (char c in "hello") - { - str.AppendChar(c); - } - str.MakeReadOnly(); - SqlCredential credential = new SqlCredential("someuser", str); - InvalidOperationException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred, credential)); + using SecureString str = CommonUtils.GenerateRandomSecureString(10); + + SqlCredential credential = new("someuser", str); + InvalidOperationException e = Assert.Throws + (() => ConnectAndDisconnect(connStrWithNoCred, credential)); string expectedMessage = "Cannot set the Credential property if 'Authentication=Active Directory Default' has been specified in the connection string."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryDefaultWithPasswordMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=ActiveDirectoryDefault; Password=anything"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADDefaultAuthenticationToConnString() + .AddPasswordToConnString("anything"); ArgumentException e = Assert.Throws(() => ConnectAndDisconnect(connStrWithNoCred)); @@ -426,117 +340,109 @@ public static void ActiveDirectoryDefaultWithPasswordMustFail() Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ActiveDirectoryDefaultWithAccessTokenCallbackMustFail() { // connection fails with expected error message. - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStrWithNoCred = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - "Authentication=ActiveDirectoryDefault"; + string connStrWithNoCred = DataTestUtility.AzureSqlConnectionString + .AddAADDefaultAuthenticationToConnString(); + InvalidOperationException e = Assert.Throws(() => { - using (SqlConnection conn = new SqlConnection(connStrWithNoCred)) - { - conn.AccessTokenCallback = (ctx, token) => - Task.FromResult(new SqlAuthenticationToken("my token", DateTimeOffset.MaxValue)); - conn.Open(); + using SqlConnection conn = new(connStrWithNoCred); + conn.AccessTokenCallback = (ctx, token) => + Task.FromResult(new SqlAuthenticationToken("my token", DateTimeOffset.MaxValue)); + conn.Open(); - Assert.NotEqual(System.Data.ConnectionState.Open, conn.State); - } + Assert.NotEqual(System.Data.ConnectionState.Open, conn.State); }); string expectedMessage = "Cannot set the AccessTokenCallback property if 'Authentication=Active Directory Default' has been specified in the connection string."; Assert.Contains(expectedMessage, e.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void AccessTokenCallbackMustOpenPassAndChangePropertyFail() { - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys); - var cred = DataTestUtility.GetTokenCredential(); + string connStr = DataTestUtility.AzureSqlConnectionString; + + TokenCredential cred = DataTestUtility.GetTokenCredential(); const string defaultScopeSuffix = "/.default"; - using (SqlConnection conn = new SqlConnection(connStr)) - { - conn.AccessTokenCallback = (ctx, cancellationToken) => - { - string scope = ctx.Resource.EndsWith(defaultScopeSuffix) ? ctx.Resource : ctx.Resource + defaultScopeSuffix; - AccessToken token = cred.GetToken(new TokenRequestContext(new[] { scope }), cancellationToken); - return Task.FromResult(new SqlAuthenticationToken(token.Token, token.ExpiresOn)); - }; - conn.Open(); - Assert.Equal(System.Data.ConnectionState.Open, conn.State); - InvalidOperationException ex = Assert.Throws(() => conn.AccessTokenCallback = null); - string expectedMessage = "Not allowed to change the 'AccessTokenCallback' property. The connection's current state is open."; - Assert.Contains(expectedMessage, ex.Message); - } + using SqlConnection conn = new(connStr); + conn.AccessTokenCallback = (ctx, cancellationToken) => + { + string scope = ctx.Resource.EndsWith(defaultScopeSuffix) ? ctx.Resource : ctx.Resource + defaultScopeSuffix; + AccessToken token = cred.GetToken(new TokenRequestContext([scope]), cancellationToken); + return Task.FromResult(new SqlAuthenticationToken(token.Token, token.ExpiresOn)); + }; + conn.Open(); + Assert.Equal(System.Data.ConnectionState.Open, conn.State); + + InvalidOperationException ex = Assert.Throws(() => conn.AccessTokenCallback = null); + string expectedMessage = "Not allowed to change the 'AccessTokenCallback' property. The connection's current state is open."; + Assert.Contains(expectedMessage, ex.Message); } - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void AccessTokenCallbackReceivesUsernameAndPassword() { var userId = "someuser"; var pwd = "somepassword"; - string[] credKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, credKeys) + - $"User ID={userId}; Password={pwd}"; - var cred = DataTestUtility.GetTokenCredential(); + string connStr = DataTestUtility.AzureSqlConnectionString + .AddUserToConnString(userId) + .AddPasswordToConnString(pwd); + + TokenCredential cred = DataTestUtility.GetTokenCredential(); const string defaultScopeSuffix = "/.default"; - using (SqlConnection conn = new SqlConnection(connStr)) + + using SqlConnection conn = new(connStr); + conn.AccessTokenCallback = (parms, cancellationToken) => { - conn.AccessTokenCallback = (parms, cancellationToken) => - { - Assert.Equal(userId, parms.UserId); - Assert.Equal(pwd, parms.Password); - string scope = parms.Resource.EndsWith(defaultScopeSuffix) ? parms.Resource : parms.Resource + defaultScopeSuffix; - AccessToken token = cred.GetToken(new TokenRequestContext(new[] { scope }), cancellationToken); - return Task.FromResult(new SqlAuthenticationToken(token.Token, token.ExpiresOn)); - }; - conn.Open(); - } + Assert.Equal(userId, parms.UserId); + Assert.Equal(pwd, parms.Password); + string scope = parms.Resource.EndsWith(defaultScopeSuffix) ? parms.Resource : parms.Resource + defaultScopeSuffix; + AccessToken token = cred.GetToken(new TokenRequestContext([scope]), cancellationToken); + return Task.FromResult(new SqlAuthenticationToken(token.Token, token.ExpiresOn)); + }; + conn.Open(); } - // Test passes locally everytime, but in pieplines fails randomly with uncertainity. + // Test passes locally everytime, but in pipelines fails randomly with uncertainty. // e.g. Second Entra ID connection too slow (802ms)! (More than 30% of the first (576ms).) [ActiveIssue("16058")] - [ConditionalFact(nameof(IsAADConnStringsSetup))] + [ConditionalFact(nameof(IsAzureSqlConnStringSetup))] public static void ConnectionSpeed() { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider original = SqlAuthenticationProvider.GetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity); try { - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, new UsernamePasswordProvider(DataTestUtility.ApplicationClientId)); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, new UserAssignedManagedIdentityProvider()); - var connString = DataTestUtility.AADPasswordConnectionString; + string connString = DataTestUtility.GetUserIdentityConnectionString(); - //Ensure server endpoints are warm - using (var connectionDrill = new SqlConnection(connString)) + // Ensure server endpoints are warm + using (SqlConnection connectionDrill = new(connString)) { connectionDrill.Open(); } SqlConnection.ClearAllPools(); - Stopwatch firstConnectionTime = new Stopwatch(); - Stopwatch secondConnectionTime = new Stopwatch(); + Stopwatch firstConnectionTime = new(); + Stopwatch secondConnectionTime = new(); - using (var connectionDrill = new SqlConnection(connString)) + using (SqlConnection connectionDrill = new(connString)) { firstConnectionTime.Start(); connectionDrill.Open(); firstConnectionTime.Stop(); - using (var connectionDrill2 = new SqlConnection(connString)) - { - secondConnectionTime.Start(); - connectionDrill2.Open(); - secondConnectionTime.Stop(); - } + + using SqlConnection connectionDrill2 = new(connString); + secondConnectionTime.Start(); + connectionDrill2.Open(); + secondConnectionTime.Stop(); } // Subsequent Entra ID connections within a short timeframe should use an auth token cached from the connection pool @@ -548,69 +454,57 @@ public static void ConnectionSpeed() if (original is not null) { // Reset to driver internal provider. - #pragma warning disable 0618 // Type or member is obsolete - SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryPassword, original); - #pragma warning restore 0618 // Type or member is obsolete + SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, original); } } } #region Managed Identity Authentication tests - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup), nameof(SupportsSystemAssignedManagedIdentity))] - public static void AccessToken_SystemManagedIdentityTest() + [ConditionalFact(nameof(IsAzureSqlConnStringSetup), nameof(IsManagedIdentitySetup), nameof(SupportsSystemAssignedManagedIdentity))] + public static async Task AccessToken_SystemManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetSystemIdentityAccessToken(); - conn.Open(); + using SqlConnection conn = new(DataTestUtility.AzureSqlConnectionString); + conn.AccessToken = await DataTestUtility.GetSystemIdentityAccessTokenAsync(); + conn.Open(); - Assert.True(conn.State == System.Data.ConnectionState.Open); - } + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } - [ConditionalFact(nameof(IsAADConnStringsSetup), nameof(IsManagedIdentitySetup))] - public static void AccessToken_UserManagedIdentityTest() + [ConditionalFact(nameof(IsAzureSqlConnStringSetup), nameof(IsManagedIdentitySetup))] + public static async Task AccessToken_UserManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.AADPasswordConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetUserIdentityAccessToken(); - conn.Open(); + using SqlConnection conn = new(DataTestUtility.AzureSqlConnectionString); + conn.AccessToken = await DataTestUtility.GetUserIdentityAccessTokenAsync(); + conn.Open(); - Assert.True(conn.State == System.Data.ConnectionState.Open); - } + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsAccessTokenSetup), nameof(IsManagedIdentitySetup), nameof(SupportsSystemAssignedManagedIdentity))] - public static void Azure_AccessToken_SystemManagedIdentityTest() + public static async Task Azure_AccessToken_SystemManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetSystemIdentityAccessToken(); - conn.Open(); + string connectionString = DataTestUtility.TCPConnectionString + .RemoveAuthAndCredsProperties(); - Assert.True(conn.State == System.Data.ConnectionState.Open); - } + using SqlConnection conn = new(connectionString); + conn.AccessToken = await DataTestUtility.GetSystemIdentityAccessTokenAsync(); + conn.Open(); + + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } [ConditionalFact(nameof(AreConnStringsSetup), nameof(IsAzure), nameof(IsAccessTokenSetup), nameof(IsManagedIdentitySetup))] - public static void Azure_AccessToken_UserManagedIdentityTest() + public static async Task Azure_AccessToken_UserManagedIdentityTest() { - string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection", "Integrated Security" }; - string connectionString = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); - using (SqlConnection conn = new SqlConnection(connectionString)) - { - conn.AccessToken = DataTestUtility.GetUserIdentityAccessToken(); - conn.Open(); - - Assert.True(conn.State == System.Data.ConnectionState.Open); - } + string connectionString = DataTestUtility.TCPConnectionString + .RemoveAuthAndCredsProperties(); + + using SqlConnection conn = new(connectionString); + conn.AccessToken = await DataTestUtility.GetUserIdentityAccessTokenAsync(); + conn.Open(); + + Assert.Equal(System.Data.ConnectionState.Open, conn.State); } #endregion } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs index fbbee8db26..c84f0d1349 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -19,7 +20,7 @@ public static class ConnectivityTest private const string COL_PROGRAM_NAME = "ProgramName"; private const string COL_HOSTNAME = "HostName"; private static readonly string s_databaseName = "d_" + Guid.NewGuid().ToString().Replace('-', '_'); - private static readonly string s_tableName = DataTestUtility.GenerateObjectName(); + private static readonly string s_tableName = CommonUtils.GenerateObjectName(); private static readonly string s_connectionString = DataTestUtility.TCPConnectionString; private static readonly string s_dbConnectionString = new SqlConnectionStringBuilder(s_connectionString) { InitialCatalog = s_databaseName }.ConnectionString; private static readonly string s_createDatabaseCmd = $"CREATE DATABASE {s_databaseName}"; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs index 2a2132dbcb..b825cabfca 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DataReaderTest/DataReaderTest.cs @@ -13,6 +13,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; using SwitchesHelper = Microsoft.Data.SqlClient.Tests.Common.LocalAppContextSwitchesHelper; @@ -71,7 +72,7 @@ public static void MultiQuerySchema() public static void CheckSparseColumnBit() { const int sparseColumns = 4095; - string tempTableName = DataTestUtility.GenerateObjectName(); + string tempTableName = CommonUtils.GenerateObjectName(); // TSQL for "CREATE TABLE" with sparse columns // table name will be provided as an argument @@ -241,7 +242,7 @@ public static void CheckHiddenColumns() // requested. The additional key information is provided as hidden columns and can be seen using // the difference between VisibleFieldCount and FieldCount on the reader - string tempTableName = DataTestUtility.GenerateObjectName(); + string tempTableName = CommonUtils.GenerateObjectName(); string createQuery = $@" create table [{tempTableName}] ( @@ -554,7 +555,7 @@ integrated into a comprehensive development "; - string tableName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString); builder.PersistSecurityInfo = true; @@ -696,7 +697,7 @@ public static async Task CanReadBinaryData() byte[] data = Enumerable.Range(0, Size) .Select(i => (byte)(i % 256)) .ToArray(); - string tableName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) { @@ -855,7 +856,7 @@ public static async Task CanReadLargeNTextColumn() { await cn.OpenAsync(); - string tableName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); try { @@ -1063,7 +1064,7 @@ public static async Task CanReadAwkwardDataLengths() { await cn.OpenAsync(); - string tableName = DataTestUtility.GenerateObjectName(); + string tableName = CommonUtils.GenerateObjectName(); try { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs index 81dbd0e35d..23f2aea1e0 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ExceptionTest/ExceptionTest.cs @@ -8,6 +8,7 @@ using System.Data; using System.Globalization; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -212,17 +213,17 @@ public static void ExceptionTests() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] public static void VariousExceptionTests() { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString); + SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString); // Strip the password in connection string if Authentication=Active Directory Managed Identity as it can not be used with a Password if (builder.Authentication == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity) { - string[] removeKeys = { "Password", "PWD" }; - string connStr = DataTestUtility.RemoveKeysInConnStr(DataTestUtility.TCPConnectionString, removeKeys); + string[] removeKeys = ["Password", "PWD"]; + string connStr = DataTestUtility.TCPConnectionString.RemoveKeysInConnStr(removeKeys); builder = new SqlConnectionStringBuilder(connStr); } // Test 1 - A - SqlConnectionStringBuilder badBuilder = new SqlConnectionStringBuilder(builder.ConnectionString) { DataSource = badServer, ConnectTimeout = 1 }; + SqlConnectionStringBuilder badBuilder = new(builder.ConnectionString) { DataSource = badServer, ConnectTimeout = 1 }; using (var sqlConnection = new SqlConnection(badBuilder.ConnectionString)) { using (SqlCommand command = sqlConnection.CreateCommand()) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs index 437e02c579..4bbbb3e5de 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/InstanceNameTest/InstanceNameTest.cs @@ -9,6 +9,7 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -115,7 +116,7 @@ private static void PortNumberInSPNTest(string connectionString, int expectedPor if (DataTestUtility.IsIntegratedSecuritySetup()) { string[] removeKeys = { "Authentication", "User ID", "Password", "UID", "PWD", "Trusted_Connection" }; - connectionString = DataTestUtility.RemoveKeysInConnStr(connectionString, removeKeys) + $"Integrated Security=true"; + connectionString = connectionString.RemoveKeysInConnStr(removeKeys) + $"Integrated Security=true"; } SqlConnectionStringBuilder builder = new(connectionString); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSTest/MARSTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSTest/MARSTest.cs index a067ad841a..41901977b8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSTest/MARSTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/MARSTest/MARSTest.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -648,7 +649,7 @@ public static async Task MarsScenarioClientJoin() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] public static void MarsConcurrencyTest() { - var table = DataTestUtility.GenerateObjectName(); + var table = CommonUtils.GenerateObjectName(); using (var conn = new SqlConnection(DataTestUtility.TCPConnectionString)) { conn.Open(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlSchemaInfoTest/SqlSchemaInfoTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlSchemaInfoTest/SqlSchemaInfoTest.cs index a7ef4993bb..cb372a4e98 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlSchemaInfoTest/SqlSchemaInfoTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlSchemaInfoTest/SqlSchemaInfoTest.cs @@ -9,6 +9,7 @@ using System.Data.Common; using System.Linq; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -43,7 +44,7 @@ public static void TestGetSchema(bool openTransaction) Assert.Equal(1, dataBases.Rows.Count); Assert.Equal(firstDatabaseName, dataBases.Rows[0]["database_name"] as string); - string nonexistentDatabaseName = DataTestUtility.GenerateRandomCharacters("NonExistentDatabase_"); + string nonexistentDatabaseName = CommonUtils.GenerateRandomCharacters("NonExistentDatabase_"); dataBases = conn.GetSchema("DATABASES", [nonexistentDatabaseName]); Assert.Equal(0, dataBases.Rows.Count); @@ -97,7 +98,7 @@ public static async Task TestGetSchemaAsync(bool openTransaction) Assert.Equal(1, dataBases.Rows.Count); Assert.Equal(firstDatabaseName, dataBases.Rows[0]["database_name"] as string); - string nonexistentDatabaseName = DataTestUtility.GenerateRandomCharacters("NonExistentDatabase_"); + string nonexistentDatabaseName = CommonUtils.GenerateRandomCharacters("NonExistentDatabase_"); dataBases = await conn.GetSchemaAsync("DATABASES", [nonexistentDatabaseName]); Assert.Equal(0, dataBases.Rows.Count); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/DistributedTransactionTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/DistributedTransactionTest.cs index 7d1098ccad..1201724937 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/DistributedTransactionTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/DistributedTransactionTest.cs @@ -6,6 +6,7 @@ using System.Data; using System.Threading.Tasks; using System.Transactions; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -170,7 +171,7 @@ private static async Task RunTestSet(Func TestCase) builder.Enlist = true; ConnectionString = builder.ConnectionString; - TestTableName = DataTestUtility.GenerateObjectName(); + TestTableName = CommonUtils.GenerateObjectName(); DataTestUtility.RunNonQuery(ConnectionString, $"create table {TestTableName} (col1 int, col2 text)"); try { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/TransactionEnlistmentTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/TransactionEnlistmentTest.cs index 527665d2b1..c1d8ae44a6 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/TransactionEnlistmentTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/TransactionEnlistmentTest.cs @@ -6,6 +6,7 @@ using System.Data; using System.Threading.Tasks; using System.Transactions; +using Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -221,7 +222,7 @@ private static void RunTestSet(Action TestCase) private static void RunTestFormat(Action testCase) { - TestTableName = DataTestUtility.GenerateObjectName(); + TestTableName = CommonUtils.GenerateObjectName(); DataTestUtility.RunNonQuery(ConnectionString, $"create table {TestTableName} (col1 int, col2 text)"); try { 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 6b1dda8ae0..d291341226 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 @@ -28,7 +28,7 @@ public class Config public bool EnclaveEnabled = false; public bool TracingEnabled = false; public string? AADAuthorityURL = null; - public string? AADPasswordConnectionString = null; + public string? AzureSqlConnectionString = null; public string? AADServicePrincipalId = null; public string? AADServicePrincipalSecret = null; public string? AzureKeyVaultURL = null; diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.jsonc b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.jsonc index b2200b03c0..7a59905f49 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.jsonc +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.jsonc @@ -14,7 +14,10 @@ "EnclaveEnabled": false, "TracingEnabled": false, "AADAuthorityURL": "", - "AADPasswordConnectionString": "", + // Typical Azure SQL Database connection string (Server, Initial Catalog) without any credentials or authentication information. + // This is used to test the AAD authentication scenarios - credentials and authentication information are provided by the tests, + // configured with other properties, such as AADServicePrincipalId, AADServicePrincipalSecret, UserManagedIdentityClientId, etc. + "AzureSqlConnectionString": "", "AADServicePrincipalId": "", "AADServicePrincipalSecret": "", "AzureKeyVaultURL": "",