【发布时间】:2020-12-11 04:35:18
【问题描述】:
我有一个带有加密列的 Azure SQL Db(始终使用 Azure KeyVault 加密)。我可以从 SSMS 访问这个数据库,我可以看到解密后的数据。
我还有一个使用 .Net Core 5.0 制作的 Web 应用程序,它部署到 Azure 应用程序服务。应用服务已打开托管标识,并且具有该 SQL Db 的编码/解码密钥的 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://docs.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" />
【问题讨论】:
-
这有帮助吗?它看起来像同样的问题,虽然接受的答案似乎不适用于这里stackoverflow.com/questions/51618582/…
-
我感觉到你的痛苦....这几乎有用,但没有用。 docs.microsoft.com/en-us/sql/relational-databases/security/…
-
能否提供您为 MSI 配置的访问策略?
-
像往常一样:键:获取,列表;加密:打开、包装、验证、签名。否则它不会在其他任何地方工作。我相信 Key-List 并不是真正需要的。但无论如何它都在那里
标签: azure .net-core azure-sql-database azure-keyvault always-encrypted