SQL Server Always Encrypted 与 .NET Core 不兼容

Posted

技术标签:

【中文标题】SQL Server Always Encrypted 与 .NET Core 不兼容【英文标题】:SQL Server Always Encrypted with .NET Core not compatible 【发布时间】:2017-04-23 00:22:48 【问题描述】:

我正在尝试将 SQL Server 2016 的 Always Encrypted 功能与 .NET Core 一起使用,但似乎(还)无法使用。尝试从 Nuget 导入 Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider,我收到一条错误消息,指出它不兼容:

包 Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider 1.0.201501028 与 netstandard1.6 (.NETStandard,Version=v1.6) 不兼容

关于如何/在哪里获得兼容版本的任何想法?

【问题讨论】:

目前正在这里跟踪:github.com/aspnet/EntityFrameworkCore/issues/9193 【参考方案1】:

.Net Core 3.1 LTS 现在支持始终加密。

您必须使用 Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider nuget 包

    Install-Package Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider -Version 1.1.1

确保您有 Keyvault 设置。

为了在 VS 中调试您的帐户,您必须拥有足够的权限才能访问密钥库。 (发布时,应用程序本身必须具有足够的权限:请参阅https://docs.microsoft.com/en-us/azure/key-vault/managed-identity)仅获取和列出权限可能还不够。

然后在 program.cs 中:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Data.SqlClient;
using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureKeyVault;
using Microsoft.Extensions.Hosting;
//namespaces etc omitted
 public static IHostBuilder CreateHostBuilder(string[] args) =>
     Host.CreateDefaultBuilder(args)
         .ConfigureAppConfiguration((context, config) =>
         
             var keyVaultEndpoint = GetKeyVaultEndpoint();
             if (!string.IsNullOrEmpty(keyVaultEndpoint))
             
                 var azureServiceTokenProvider = new AzureServiceTokenProvider();
                 var keyVaultClient = new KeyVaultClient(
                     new KeyVaultClient.AuthenticationCallback(
                         azureServiceTokenProvider.KeyVaultTokenCallback));
                 config.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
                 SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new KeyVaultClient.AuthenticationCallback(
                         azureServiceTokenProvider.KeyVaultTokenCallback));
                 SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders: new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(capacity: 1, comparer: StringComparer.OrdinalIgnoreCase)
                 
                      
                         SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, sqlColumnEncryptionAzureKeyVaultProvider
                     
                 );                     
             
         )
         .ConfigureWebHostDefaults(webBuilder =>
         
             webBuilder.UseStartup<Startup>();
         );
    private static string GetKeyVaultEndpoint() => "https://YOURKEYVAULT.vault.azure.net/";

在 StartUp.cs 中配置服务:

using Microsoft.Data.SqlClient;
//Code omitted
services.AddDbContext<EnitiesModel>(options =>
            options.UseSqlServer(new SqlConnection(Configuration.GetConnectionString("EntitiesModel"))));

确保您的连接字符串包含 Column Encryption Setting=Enabled 参数:

 "ConnectionStrings": 
"EntitiesModel": "Server=SOMESERVER.database.windows.net;Database=SOMEDB;Trusted_Connection=False;Encrypt=True;Integrated Security=False;
MultipleActiveResultSets=true;persist security info=True;user id=SOMEDBACCOUNT;password=SOMEPASSWORD;
Column Encryption Setting=enabled;"   
  

小问题:如果您使用数据库脚手架,请确保模型连接字符串也具有列加密设置! (如果你没有改变它,它是标准的 DBModel 类在脚手架后带有 VS 警告)

这应该让你启动并运行......

【讨论】:

您知道是否可以将其与带有应用注册的密钥保管库一起使用?我正在开发一个将部署在 IIS 而不是 Azure 中的应用程序。所以我没有应用服务。但我正在使用 keyvaults 来存储连接字符串和令牌。所以我在 Azure 中有一个可以访问密钥保管库的应用程序注册。应用注册不支持 MSI,所以我不能使用你的方法。但我也找不到我应该如何让它在我的情况下工作。 也许通过应用配置? docs.microsoft.com/en-us/azure/azure-app-configuration/… 感谢您的建议。我可以通过设置 SqlColumnEncryptionAzureKeyVaultProvider 来获取令牌,方法是使用应用注册的客户端 ID 和密钥以及 ActiveDirectory ClientCredential 类来获取令牌。 我已经阅读了数十页文档和示例,试图让基于 azure 的列加密与 EF 一起使用。这可能是唯一一个能做到这三个方面的例子。 +1。 要补充一点:Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider 与 Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider 不一样 大多数过时的文档使用的是 .SqlServer 命名空间,这是我的问题的一半.【参考方案2】:

免责声明:我是 Microsoft 的项目经理

.NET Core 目前不支持始终加密。它在我们的路线图上,我们还没有时间表。

现在支持。请参阅下面的答案。

【讨论】:

对于那些感兴趣的人,类似的Q/A在这里:***.com/questions/41175489/… @Jakub Szymaszek - Microsoft 现在怎么样,有没有关于这个问题的新更新? 现在呢? 这个问题有什么更新吗?我认为这是 MS 在赶上框架更新时留下的主要安全问题,并且它与其他产品的组织性不好。 Mocrosoft.Data.SqlClient 1.1 发布后有什么更新吗? (youtube.com/watch?v=zhzRzRBDTyE)【参考方案3】:

现在 .NET Core 3.0 Preview 5 支持它,它提供了一个新的 SqlClient 支持 Always Encrypted 等。请参阅此comment 了解更多信息。

对于 Key Vault 提供程序,您需要改用 Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider。

【讨论】:

虽然这不是 Key Vault 提供程序,但我认为 SqlClient 对列加密的支持确实使他们能够完成 Key Vault 提供程序的工作。 Key Vault 提供程序也在 2 个月前更新:nuget.org/packages/… 支持 .NET Core 2.1 及更高版本。【参考方案4】:

上面 Tim 的回答中的 Program.cs 的变体,但适用于在 Azure App Registration 中注册的应用:

namespace Sample

   public class Program
   
       public static void Main(string[] args)
       
           CreateHostBuilder(args).Build().Run();
       

       public static IHostBuilder CreateHostBuilder(string[] args) =>
     Host.CreateDefaultBuilder(args)
         .ConfigureAppConfiguration((context, config) =>
         
             var keyVaultEndpoint = GetKeyVaultEndpoint();
             if (!string.IsNullOrEmpty(keyVaultEndpoint))
             
                 var azureServiceTokenProvider = new AzureServiceTokenProvider(keyVaultEndpoint);
                 var keyVaultClient = new KeyVaultClient(
                     new KeyVaultClient.AuthenticationCallback(
                         azureServiceTokenProvider.KeyVaultTokenCallback));
                 
                 SqlColumnEncryptionAzureKeyVaultProvider sqlColumnEncryptionAzureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(new KeyVaultClient.AuthenticationCallback(
                         azureServiceTokenProvider.KeyVaultTokenCallback));
                 SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders: new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>(capacity: 1, comparer: StringComparer.OrdinalIgnoreCase)
                 
                     
                         SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, sqlColumnEncryptionAzureKeyVaultProvider
                     
                 );
             
         )
        .ConfigureWebHostDefaults(webBuilder =>
        
            webBuilder.UseStartup<Startup>();
        );

       private static string GetKeyVaultEndpoint() => "RunAs=App;AppId=<app ID>;TenantId=<tenant ID>.onmicrosoft.com;AppKey=<app secret>";
   
 

【讨论】:

以上是关于SQL Server Always Encrypted 与 .NET Core 不兼容的主要内容,如果未能解决你的问题,请参考以下文章

Sql Server Always On 读写分离配置方法

Windows Server 2012搭建SQL Server Always On踩坑全记录

SQL Server Always ON 数据同步原理

SQL SERVER ALWAYS ON 之 添加新的同步数据库

Skype for Business Server 部署SQL always on 已知问题

SQL Server Always Encrypted 与 .NET Core 不兼容