【问题标题】:Using Always Encrypted with EF Core and storing Master Key in Azure Key Vault通过 EF Core 使用 Always Encrypted 并将主密钥存储在 Azure Key Vault 中
【发布时间】:2020-03-06 19:24:03
【问题描述】:

我有一个使用 EF Core 访问 Azure SQL 数据库中的数据的 .Net Core 3.1 项目。我目前正在尝试在某些敏感列上实现始终加密功能。

我成功加密了该列,将主密钥存储在 Azure Key Vault 中,我在其中创建了一个可以访问此密钥的应用注册。

我使用这个视频来实现这一点:https://www.youtube.com/watch?v=POLTjo7GpRc

然后我能够在我的 c# 代码中检索主密钥并启动 SQL 查询,这是从加密表中进行的简单选择。

我可以用明文(解密)检索加密列,很好。

我现在的问题是,如何配置 EF Core 以在 Azure Key Vault 中检索我的主密钥并在我的实体中返回解密的值? Sql 查询有效,但我不知道如何使其与 EF Core 一起使用。

非常感谢!

【问题讨论】:

    标签: sql azure-keyvault .net-core-3.1 always-encrypted ef-core-3.1


    【解决方案1】:

    根据我的测试,如果你已经为你的 SQL Server 配置了 Always Encrypted 和 Azure 密钥库,请使用Microsoft.EntityFrameworkCore.SqlServer 在你的应用程序中实现 EF 核心。

    例如

    1. Configure Always Encrypted

    2. 创建 Azure AD 应用程序并为 Azure 密钥保管库中的应用程序配置访问策略。

    3. 配置应用程序

      一个。安装sdk

       ItemGroup>
      <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
      <PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.1.0" />
      <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      </PackageReference>
      <PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.7" />
      <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
      </ItemGroup>
      
      

      b.创建模型

      public class Patient
      {
      
        public int PatientId { get; set; }
        public string SSN { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
      }
      

      c。创建 DbContext

      public class TestContext :DbContext
      {
         private static Boolean isInitialized;
         public  TestContext(DbContextOptions<TestContext> options) : base(options)
         {
             if(! isInitialized) { InitializeAzureKeyVaultProvider(); isInitialized = true; }
      
      
         }
      
      
         public DbSet<Patient> Patients { get; set; }
         protected override void OnModelCreating(ModelBuilder modelBuilder)
         {
             modelBuilder.Entity<Patient>().ToTable("Patients");
         }
      
         private static string clientId = "the ad application appid";
         private static string clientSecret = "the ad application appSecret";
         private static ClientCredential _clientCredential;
      
         private static void  InitializeAzureKeyVaultProvider()
         {
             _clientCredential = new ClientCredential(clientId, clientSecret);
      
             SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider =
               new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);
      
             Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers =
               new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
      
             providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
             SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
         }
      
         private async static Task<string> GetToken(string authority, string resource, string scope)
         {
             var authContext = new AuthenticationContext(authority);
             AuthenticationResult result = await authContext.AcquireTokenAsync(resource, _clientCredential);
      
             if (result == null)
                 throw new InvalidOperationException("Failed to obtain the access token");
             return result.AccessToken;
         }
      }
      

      d。注册 DbContext。在Startup.cs 中添加以下代码。 public void ConfigureServices(IServiceCollection services) { services.AddDbContext<TestContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddControllersWithViews(); }

      e。在 appsettings.json 中添加 connectionString

      {
      "ConnectionStrings": {
      "DefaultConnection": "Server=tcp:<your server name>.database.windows.net,1433;
      Initial Catalog=<db name>;
      Persist Security Info=False;
      User ID=<user>;
      Password=<password>;
      Column Encryption Setting=enabled;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
      },
      ...
      

    更多详情请参考

    https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-3.1

    https://docs.microsoft.com/en-us/sql/connect/ado-net/sql/sqlclient-support-always-encrypted?view=sql-server-ver15

    【讨论】:

    • 你能告诉我我们是从哪里得到clientIdclientSecret 的吗?在 Azure 上找不到类似的东西
    猜你喜欢
    • 2019-02-04
    • 2017-10-25
    • 1970-01-01
    • 2020-10-01
    • 2017-12-10
    • 2021-03-16
    • 2023-01-26
    • 2019-07-28
    • 2019-12-24
    相关资源
    最近更新 更多