我有一个Azure SQL数据库,其中包含加密列(使用Azure KeyVault始终加密)。我可以从SSMS访问此数据库,并且可以看到解密后的数据。
我还有一个使用.Net Core 5.0制作的Web应用程序,部署在Azure App Service上。该应用服务已启用托管身份验证,并且具有可对该SQL数据库进行解密的enc/dec密钥的Key Vault,其访问策略设置允许此应用服务解密数据。
Web应用程序使用托管身份验证,因为我可以看到未加密的数据被检索而无任何问题。
此外,连接字符串确实包括Column Encryption Setting=enabled;
。以下是连接字符串:
Server=tcp:server.database.windows.net,1433;Database=somedb;Column Encryption Setting=enabled;
问题是我找不到任何这种设置的样例。 我找到了一些并且我理解我需要注册
SqlColumnEncryptionAzureKeyVaultProvider
。 这是我的代码来获取SqlConnection: internal static class AzureSqlConnection
{
private static bool _isInitialized;
private static void InitKeyVaultProvider(ILogger logger)
{
/*
* from here - https://github.com/dotnet/SqlClient/blob/master/release-notes/add-ons/AzureKeyVaultProvider/1.2/1.2.0.md
* and - https://github.com/dotnet/SqlClient/blob/master/doc/samples/AzureKeyVaultProviderExample.cs
*
*/
try
{
// Initialize AKV provider
SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider =
new SqlColumnEncryptionAzureKeyVaultProvider(AzureActiveDirectoryAuthenticationCallback);
// Register AKV provider
SqlConnection.RegisterColumnEncryptionKeyStoreProviders(
new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(1, StringComparer.OrdinalIgnoreCase)
{
{SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, sqlColumnEncryptionAzureKeyVaultProvider}
});
_isInitialized = true;
}
catch (Exception ex)
{
logger.LogError(ex, "Could not register SqlColumnEncryptionAzureKeyVaultProvider");
throw;
}
}
internal static async Task<SqlConnection> GetSqlConnection(string connectionString, ILogger logger)
{
if (!_isInitialized) InitKeyVaultProvider(logger);
try
{
SqlConnection conn = new SqlConnection(connectionString);
/*
* This is Managed Identity (not Always Encrypted)
* https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi#modify-aspnet-core
*
*/
#if !DEBUG
conn.AccessToken = await new AzureServiceTokenProvider().GetAccessTokenAsync("https://database.windows.net/");
logger.LogInformation($"token: {conn.AccessToken}");
#endif
await conn.OpenAsync();
return conn;
}
catch (Exception ex)
{
logger.LogError(ex, "Could not establish a connection to SQL Server");
throw;
}
}
private static async Task<string> AzureActiveDirectoryAuthenticationCallback(string authority, string resource, string scope)
{
return await new AzureServiceTokenProvider().GetAccessTokenAsync("https://database.windows.net/");
//AuthenticationContext? authContext = new AuthenticationContext(authority);
//ClientCredential clientCred = new ClientCredential(s_clientId, s_clientSecret);
//AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
//if (result == null)
//{
// throw new InvalidOperationException($"Failed to retrieve an access token for {resource}");
//}
//return result.AccessToken;
}
}
这段代码不会抛出任何异常,并且适用于非加密查询。但是对于加密查询,我收到以下错误:
解密列加密键失败。无效的密钥存储提供程序名称:'AZURE_KEY_VAULT'。密钥存储提供程序名称必须表示系统密钥存储提供程序或已注册的自定义密钥存储提供程序。有效的系统密钥存储提供程序名称为:'MSSQL_CERTIFICATE_STORE'、'MSSQL_CNG_STORE'、'MSSQL_CSP_PROVIDER'。当前已注册的有效自定义密钥存储提供程序名称为:。请在数据库中验证列主密钥定义中的密钥存储提供程序信息,并验证应用程序中使用的所有自定义密钥存储提供程序是否已正确注册。解密列加密键失败。无效的密钥存储提供程序名称:'AZURE_KEY_VAULT'。密钥存储提供程序名称必须表示系统密钥存储提供程序或已注册的自定义密钥存储提供程序。有效的系统密钥存储提供程序名称为:'MSSQL_CERTIFICATE_STORE'、'MSSQL_CNG_STORE'、'MSSQL_CSP_PROVIDER'。当前已注册的有效自定义密钥存储提供程序名称为:。请在数据库中验证列主密钥定义中的密钥存储提供程序信息,并验证应用程序中使用的所有自定义密钥存储提供程序是否已正确注册。
看起来密钥保管库提供程序没有注册。
我该怎么做才能让它查询加密数据?
使用的软件包
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.6.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.0" />
<PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />