使用 EF Core 始终加密并将主密钥存储在 Azure Key Vault 中

Lek*_*001 4 sql azure-keyvault always-encrypted .net-core-3.1 ef-core-3.1

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

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

我使用此视频来实现此目的:https://www.youtube.com/watch ?v=POLTjo7GpRc

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

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

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

多谢!

Jim*_* Xu 7

根据我的测试,如果您使用 Azure Key Vault 为 SQL Server 配置了 Always Encrypted,请Microsoft.EntityFrameworkCore.SqlServer 在您的应用程序中使用 EF core 实现。

例如

  1. 配置始终加密

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

  3. 配置应用程序

    A。安装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>
    
    
    Run Code Online (Sandbox Code Playgroud)

    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; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    C。创建数据库上下文

    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;
       }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    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;"
    },
    ...
    
    Run Code Online (Sandbox Code Playgroud)

欲了解更多详情,请参阅

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

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