Использование Always Encrypted с EF Core и хранение Мастер Ключа в Azure Key Vault - PullRequest
0 голосов
/ 06 марта 2020

У меня есть проект. Net Core 3.1, использующий EF Core для доступа к данным в базе данных Azure SQL. В настоящее время я пытаюсь реализовать функцию «Всегда зашифровано» в некотором чувствительном столбце.

Я успешно зашифровал столбец, сохранив мастер-ключ в Azure хранилище ключей, где я создал регистрацию приложения с доступом к этому ключу.

Я использовал это видео для достижения этой цели: https://www.youtube.com/watch?v=POLTjo7GpRc

Затем я смог получить мастер-ключ в моем коде c# и запустить SQL запрос, простой выбор из зашифрованной таблицы.

Я мог бы получить зашифрованный столбец в виде открытого текста (расшифрованный), хорошо.

Мой вопрос сейчас, как я могу настроить EF Core для восстановить мой мастер-ключ в Azure хранилище ключей и вернуть дешифрованное значение в моих сущностях? Sql запрос работает, но я не знаю, как заставить его работать с EF Core.

Большое спасибо!

1 Ответ

0 голосов
/ 11 марта 2020

Согласно моему тесту, если вы настроили Always Encrypted для вашего SQL Сервера с хранилищем ключей Azure, используйте 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>
    
    

    б. Создать модуль

    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. добавить connectionString в appsettings. json

    {
    "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

...