From 197c28724db8fa08d4caee3301e1023149b5cd77 Mon Sep 17 00:00:00 2001 From: "Javad Rahnama (SIMBA TECHNOLOGIES INC)" Date: Thu, 25 Apr 2024 12:55:46 -0700 Subject: [PATCH 1/6] Initial commit - updating to managed identity token credential --- .../ManualTests/AlwaysEncrypted/AKVUnitTests.cs | 17 ++++++++++------- .../TestFixtures/Setup/CertificateUtility.cs | 5 +++-- .../SqlClientCustomTokenCredential.cs | 8 +++++--- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index 85192076fc..35646b8aec 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -86,8 +86,9 @@ public static void TokenCredentialTest() Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); using DataTestUtility.AKVEventListener AKVListener = new(); - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); + //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); + ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); + SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); @@ -104,8 +105,9 @@ public static void TokenCredentialRotationTest() // SqlClientCustomTokenCredential implements a legacy authentication callback to request the access token from the client-side. SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); + //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); + ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); + SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithNewProvider); @@ -129,15 +131,16 @@ public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion() { string keyName = keyPathUri.Segments[2]; string keyVersion = keyPathUri.Segments[3]; - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - KeyClient keyClient = new KeyClient(vaultUri, clientSecretCredential); + //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); + ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); + KeyClient keyClient = new KeyClient(vaultUri, miCredential); KeyVaultKey currentVersionKey = keyClient.GetKey(keyName); KeyVaultKey specifiedVersionKey = keyClient.GetKey(keyName, keyVersion); //If specified versioned key is the most recent version of the key then we cannot test. if (!KeyIsLatestVersion(specifiedVersionKey, currentVersionKey)) { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(clientSecretCredential); + SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); // Perform an operation to initialize the internal caches azureKeyProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVOriginalUrl, EncryptionAlgorithm, s_columnEncryptionKey); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs index 1c054f3769..bcf7ca6d16 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs @@ -141,8 +141,9 @@ internal static X509Certificate2 CreateCertificate() private static async Task SetupAKVKeysAsync() { - ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); - KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, clientSecretCredential); + //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); + ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); + KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, miCredential); AsyncPageable keys = keyClient.GetPropertiesOfKeysAsync(); IAsyncEnumerator enumerator = keys.GetAsyncEnumerator(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs index 8b1ef93e61..412e7ea471 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs @@ -106,9 +106,11 @@ public static async Task AzureActiveDirectoryAuthenticationCallback string authorityHost = authority.Remove(separatorIndex + 1); string audience = authority.Substring(separatorIndex + 1); TokenCredentialOptions tokenCredentialOptions = new TokenCredentialOptions() { AuthorityHost = new Uri(authorityHost) }; - ClientSecretCredential clientSecretCredential = s_clientSecretCredentials.GetOrAdd(authority + "|--|" + resource, - new ClientSecretCredential(audience, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret, tokenCredentialOptions)); - AccessToken accessToken = await clientSecretCredential.GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); + //ClientSecretCredential clientSecretCredential = s_clientSecretCredentials.GetOrAdd(authority + "|--|" + resource, + // new ClientSecretCredential(audience, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret, tokenCredentialOptions)); + ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); + AccessToken accessToken = await miCredential.GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); + //AccessToken accessToken = await clientSecretCredential.GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); return accessToken; } } From f52bf550dd81b655b51420d4fc4be096326f2321 Mon Sep 17 00:00:00 2001 From: "Javad Rahnama (SIMBA TECHNOLOGIES INC)" Date: Fri, 26 Apr 2024 10:39:18 -0700 Subject: [PATCH 2/6] Removing references to AzureKeyVaultClientId and AzureKeyVaultClientSecrets --- BUILDGUIDE.md | 2 -- .../tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs | 3 --- .../TestFixtures/Setup/CertificateUtility.cs | 1 - .../tests/ManualTests/DataCommon/DataTestUtility.cs | 6 +----- .../DataCommon/SqlClientCustomTokenCredential.cs | 3 --- .../tools/Microsoft.Data.SqlClient.TestUtilities/Config.cs | 2 -- .../config.default.json | 2 -- 7 files changed, 1 insertion(+), 18 deletions(-) diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index 4434af3f1a..2061e136ea 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -176,8 +176,6 @@ Manual Tests require the below setup to run: |AADSecurePrincipalSecret | (Optional) A Secret defined for a registered application which has been granted permission to the database defined in the AADPasswordConnectionString. | {Secret} | |AzureKeyVaultURL | (Optional) Azure Key Vault Identifier URL | `https://{keyvaultname}.vault.azure.net/` | |AzureKeyVaultTenantId | (Optional) The Azure Active Directory tenant (directory) Id of the service principal. | _{Tenant ID of Active Directory}_ | - |AzureKeyVaultClientId | (Optional) "Application (client) ID" of an Active Directory registered application, granted access to the Azure Key Vault specified in `AZURE_KEY_VAULT_URL`. Requires the key permissions Get, List, Import, Decrypt, Encrypt, Unwrap, Wrap, Verify, and Sign. | _{Client Application ID}_ | - |AzureKeyVaultClientSecret | (Optional) "Client Secret" of the Active Directory registered application, granted access to the Azure Key Vault specified in `AZURE_KEY_VAULT_URL` | _{Client Application Secret}_ | |SupportsIntegratedSecurity | (Optional) Whether or not the USER running tests has integrated security access to the target SQL Server.| `true` OR `false`| |LocalDbAppName | (Optional) If Local Db Testing is supported, this property configures the name of Local DB App instance available in client environment. Empty string value disables Local Db testing. | Name of Local Db App to connect to.| |LocalDbSharedInstanceName | (Optional) If LocalDB testing is supported and the instance is shared, this property configures the name of the shared instance of LocalDB to connect to. | Name of shared instance of LocalDB. | diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index 35646b8aec..c7f9db573f 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -86,7 +86,6 @@ public static void TokenCredentialTest() Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); using DataTestUtility.AKVEventListener AKVListener = new(); - //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); @@ -105,7 +104,6 @@ public static void TokenCredentialRotationTest() // SqlClientCustomTokenCredential implements a legacy authentication callback to request the access token from the client-side. SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); @@ -131,7 +129,6 @@ public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion() { string keyName = keyPathUri.Segments[2]; string keyVersion = keyPathUri.Segments[3]; - //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); KeyClient keyClient = new KeyClient(vaultUri, miCredential); KeyVaultKey currentVersionKey = keyClient.GetKey(keyName); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs index bcf7ca6d16..6920ce1f53 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs @@ -141,7 +141,6 @@ internal static X509Certificate2 CreateCertificate() private static async Task SetupAKVKeysAsync() { - //ClientSecretCredential clientSecretCredential = new ClientSecretCredential(DataTestUtility.AKVTenantId, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret); ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, miCredential); AsyncPageable keys = keyClient.GetPropertiesOfKeysAsync(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index d588761bdb..1abd074631 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -41,8 +41,6 @@ public static class DataTestUtility public static readonly string AKVUrl = null; public static readonly string AKVOriginalUrl = null; public static readonly string AKVTenantId = null; - public static readonly string AKVClientId = null; - public static readonly string AKVClientSecret = null; public static readonly string LocalDbAppName = null; public static readonly string LocalDbSharedInstanceName = null; public static List AEConnStrings = new List(); @@ -194,8 +192,6 @@ static DataTestUtility() } AKVTenantId = c.AzureKeyVaultTenantId; - AKVClientId = c.AzureKeyVaultClientId; - AKVClientSecret = c.AzureKeyVaultClientSecret; if (EnclaveEnabled) { @@ -458,7 +454,7 @@ public static bool IsNotAzureServer() // Ref: https://feedback.azure.com/forums/307516-azure-synapse-analytics/suggestions/17858869-support-always-encrypted-in-sql-data-warehouse public static bool IsAKVSetupAvailable() { - return !string.IsNullOrEmpty(AKVUrl) && !string.IsNullOrEmpty(AKVClientId) && !string.IsNullOrEmpty(AKVClientSecret) && !string.IsNullOrEmpty(AKVTenantId) && IsNotAzureSynapse(); + return !string.IsNullOrEmpty(AKVUrl) && !string.IsNullOrEmpty(UserManagedIdentityClientId) && !string.IsNullOrEmpty(AKVTenantId) && IsNotAzureSynapse(); } public static bool IsTargetReadyForAeWithKeyStore() diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs index 412e7ea471..9cad8e86a4 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs @@ -106,11 +106,8 @@ public static async Task AzureActiveDirectoryAuthenticationCallback string authorityHost = authority.Remove(separatorIndex + 1); string audience = authority.Substring(separatorIndex + 1); TokenCredentialOptions tokenCredentialOptions = new TokenCredentialOptions() { AuthorityHost = new Uri(authorityHost) }; - //ClientSecretCredential clientSecretCredential = s_clientSecretCredentials.GetOrAdd(authority + "|--|" + resource, - // new ClientSecretCredential(audience, DataTestUtility.AKVClientId, DataTestUtility.AKVClientSecret, tokenCredentialOptions)); ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); AccessToken accessToken = await miCredential.GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); - //AccessToken accessToken = await clientSecretCredential.GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); return accessToken; } } 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 49c368c790..14dcd5e086 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 @@ -22,8 +22,6 @@ public class Config public string AADServicePrincipalSecret = null; public string AzureKeyVaultURL = null; public string AzureKeyVaultTenantId = null; - public string AzureKeyVaultClientId = null; - public string AzureKeyVaultClientSecret = null; public string LocalDbAppName = null; public string LocalDbSharedInstanceName = null; public bool EnclaveEnabled = false; diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json index 411f4ad88f..f656c3ae15 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/config.default.json @@ -13,8 +13,6 @@ "AADServicePrincipalSecret": "", "AzureKeyVaultURL": "", "AzureKeyVaultTenantId": "", - "AzureKeyVaultClientId": "", - "AzureKeyVaultClientSecret": "", "SupportsIntegratedSecurity": true, "LocalDbAppName": "", "LocalDbSharedInstanceName": "", From 55a77cf438c27b8741d72b38ecab60964687ae3b Mon Sep 17 00:00:00 2001 From: "Javad Rahnama (SIMBA TECHNOLOGIES INC)" Date: Fri, 26 Apr 2024 14:34:29 -0700 Subject: [PATCH 3/6] Using DefaultAzureCredentials --- .../ManualTests/AlwaysEncrypted/AKVUnitTests.cs | 14 +++++++------- .../TestFixtures/Setup/CertificateUtility.cs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index c7f9db573f..69c56db3e7 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -86,8 +86,8 @@ public static void TokenCredentialTest() Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); using DataTestUtility.AKVEventListener AKVListener = new(); - ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); + DefaultAzureCredential defaultAzureCredential = new(); = new(); + SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); @@ -104,8 +104,8 @@ public static void TokenCredentialRotationTest() // SqlClientCustomTokenCredential implements a legacy authentication callback to request the access token from the client-side. SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); - SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); + DefaultAzureCredential defaultAzureCredential = new(); + SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithNewProvider); @@ -129,15 +129,15 @@ public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion() { string keyName = keyPathUri.Segments[2]; string keyVersion = keyPathUri.Segments[3]; - ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); - KeyClient keyClient = new KeyClient(vaultUri, miCredential); + DefaultAzureCredential defaultAzureCredential = new(); + KeyClient keyClient = new KeyClient(vaultUri, defaultAzureCredential); KeyVaultKey currentVersionKey = keyClient.GetKey(keyName); KeyVaultKey specifiedVersionKey = keyClient.GetKey(keyName, keyVersion); //If specified versioned key is the most recent version of the key then we cannot test. if (!KeyIsLatestVersion(specifiedVersionKey, currentVersionKey)) { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(miCredential); + SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); // Perform an operation to initialize the internal caches azureKeyProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVOriginalUrl, EncryptionAlgorithm, s_columnEncryptionKey); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs index 6920ce1f53..749071a40a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs @@ -141,8 +141,8 @@ internal static X509Certificate2 CreateCertificate() private static async Task SetupAKVKeysAsync() { - ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); - KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, miCredential); + DefaultAzureCredential defaultAzureCredential = new(); + KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, defaultAzureCredential); AsyncPageable keys = keyClient.GetPropertiesOfKeysAsync(); IAsyncEnumerator enumerator = keys.GetAsyncEnumerator(); From 0158de8e8f21e4cc953861a33be31d7f0bfdf345 Mon Sep 17 00:00:00 2001 From: "Javad Rahnama (SIMBA TECHNOLOGIES INC)" Date: Fri, 26 Apr 2024 21:54:46 -0700 Subject: [PATCH 4/6] fix typo --- .../tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index 69c56db3e7..6bd5a25edc 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -86,7 +86,7 @@ public static void TokenCredentialTest() Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); using DataTestUtility.AKVEventListener AKVListener = new(); - DefaultAzureCredential defaultAzureCredential = new(); = new(); + DefaultAzureCredential defaultAzureCredential = new(); SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); From e2b20d902a2ea5a113575cdc86be9ab75e37a635 Mon Sep 17 00:00:00 2001 From: Javad Rahnama Date: Mon, 29 Apr 2024 13:44:18 -0700 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: David Engel --- .../tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs | 11 ++++------- .../TestFixtures/Setup/CertificateUtility.cs | 3 +-- .../tests/ManualTests/DataCommon/DataTestUtility.cs | 7 +++++++ .../DataCommon/SqlClientCustomTokenCredential.cs | 3 +-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index 6bd5a25edc..bd86af6c75 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -86,8 +86,7 @@ public static void TokenCredentialTest() Guid activityId = Trace.CorrelationManager.ActivityId = Guid.NewGuid(); using DataTestUtility.AKVEventListener AKVListener = new(); - DefaultAzureCredential defaultAzureCredential = new(); - SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); + SqlColumnEncryptionAzureKeyVaultProvider akvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(DataTestUtility.GetTokenCredential()); byte[] encryptedCek = akvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCek = akvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCek); @@ -104,8 +103,7 @@ public static void TokenCredentialRotationTest() // SqlClientCustomTokenCredential implements a legacy authentication callback to request the access token from the client-side. SqlColumnEncryptionAzureKeyVaultProvider oldAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new SqlClientCustomTokenCredential()); - DefaultAzureCredential defaultAzureCredential = new(); - SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); + SqlColumnEncryptionAzureKeyVaultProvider newAkvProvider = new SqlColumnEncryptionAzureKeyVaultProvider(DataTestUtility.GetTokenCredential()); byte[] encryptedCekWithNewProvider = newAkvProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, s_columnEncryptionKey); byte[] decryptedCekWithOldProvider = oldAkvProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, EncryptionAlgorithm, encryptedCekWithNewProvider); @@ -129,15 +127,14 @@ public static void ReturnSpecifiedVersionOfKeyWhenItIsNotTheMostRecentVersion() { string keyName = keyPathUri.Segments[2]; string keyVersion = keyPathUri.Segments[3]; - DefaultAzureCredential defaultAzureCredential = new(); - KeyClient keyClient = new KeyClient(vaultUri, defaultAzureCredential); + KeyClient keyClient = new KeyClient(vaultUri, DataTestUtility.GetTokenCredential()); KeyVaultKey currentVersionKey = keyClient.GetKey(keyName); KeyVaultKey specifiedVersionKey = keyClient.GetKey(keyName, keyVersion); //If specified versioned key is the most recent version of the key then we cannot test. if (!KeyIsLatestVersion(specifiedVersionKey, currentVersionKey)) { - SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(defaultAzureCredential); + SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(DataTestUtility.GetTokenCredential()); // Perform an operation to initialize the internal caches azureKeyProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVOriginalUrl, EncryptionAlgorithm, s_columnEncryptionKey); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs index 749071a40a..3d3c717b31 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CertificateUtility.cs @@ -141,8 +141,7 @@ internal static X509Certificate2 CreateCertificate() private static async Task SetupAKVKeysAsync() { - DefaultAzureCredential defaultAzureCredential = new(); - KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, defaultAzureCredential); + KeyClient keyClient = new KeyClient(DataTestUtility.AKVBaseUri, DataTestUtility.GetTokenCredential()); AsyncPageable keys = keyClient.GetPropertiesOfKeysAsync(); IAsyncEnumerator enumerator = keys.GetAsyncEnumerator(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index 1abd074631..f37cd2d917 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -457,6 +457,13 @@ public static bool IsAKVSetupAvailable() return !string.IsNullOrEmpty(AKVUrl) && !string.IsNullOrEmpty(UserManagedIdentityClientId) && !string.IsNullOrEmpty(AKVTenantId) && IsNotAzureSynapse(); } + private static DefaultAzureCredential defaultCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = UserManagedIdentityClientId }); + + public static TokenCredential GetTokenCredential() + { + return defaultCredential; + } + public static bool IsTargetReadyForAeWithKeyStore() { return DataTestUtility.AreConnStringSetupForAE() diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs index 9cad8e86a4..eb276493a7 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/SqlClientCustomTokenCredential.cs @@ -106,8 +106,7 @@ public static async Task AzureActiveDirectoryAuthenticationCallback string authorityHost = authority.Remove(separatorIndex + 1); string audience = authority.Substring(separatorIndex + 1); TokenCredentialOptions tokenCredentialOptions = new TokenCredentialOptions() { AuthorityHost = new Uri(authorityHost) }; - ManagedIdentityCredential miCredential = new(DataTestUtility.UserManagedIdentityClientId); - AccessToken accessToken = await miCredential.GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); + AccessToken accessToken = await DataTestUtility.GetTokenCredential().GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false); return accessToken; } } From 641114c9ba981f0b3b1d14a06737bcc9219162f5 Mon Sep 17 00:00:00 2001 From: "Javad Rahnama (SIMBA TECHNOLOGIES INC)" Date: Mon, 29 Apr 2024 13:54:58 -0700 Subject: [PATCH 6/6] adding ManagedIdentity to DefaultAzureDredential options - refactor GetToken --- .../tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs | 2 -- .../tests/ManualTests/DataCommon/DataTestUtility.cs | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs index bd86af6c75..9374b3783c 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/AKVUnitTests.cs @@ -3,12 +3,10 @@ // See the LICENSE file in the project root for more information. using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider; -using Azure.Identity; using Xunit; using Azure.Security.KeyVault.Keys; using System.Reflection; using System; -using System.Linq; using System.Collections.Generic; using System.Threading; using System.Diagnostics.Tracing; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index f37cd2d917..06209e1ad2 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -22,6 +22,8 @@ using System.Text; using System.Security.Principal; using System.Runtime.InteropServices; +using Azure.Identity; +using Azure.Core; namespace Microsoft.Data.SqlClient.ManualTesting.Tests { @@ -457,11 +459,11 @@ public static bool IsAKVSetupAvailable() return !string.IsNullOrEmpty(AKVUrl) && !string.IsNullOrEmpty(UserManagedIdentityClientId) && !string.IsNullOrEmpty(AKVTenantId) && IsNotAzureSynapse(); } - private static DefaultAzureCredential defaultCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = UserManagedIdentityClientId }); + private static readonly DefaultAzureCredential s_defaultCredential = new(new DefaultAzureCredentialOptions { ManagedIdentityClientId = UserManagedIdentityClientId }); public static TokenCredential GetTokenCredential() { - return defaultCredential; + return s_defaultCredential; } public static bool IsTargetReadyForAeWithKeyStore()