Neste guia, você pode aprender como usar o EF Core Provider para criptografar campos de documento específicos usando a Queryable Encryption (QE).
Visão geral
O Queryable Encryption criptografa campos de documento confidenciais na camada do aplicação antes de gravar dados no MongoDB, ao mesmo tempo em que permite que seu aplicação consulte esses campos. Somente aplicativos que têm acesso às suas chaves de criptografia podem ler os dados em texto simples. Se um invasor obtiver acesso ao banco de dados, ele só poderá ver apenas o texto cifrado porque não tem acesso às chaves de criptografia.
Por exemplo, você pode usar a Queryable Encryption para criptografar campos que contêm:
Números da Segurança Social
Números de cartão de crédito
Informações médicas ou de saúde
Informações financeiras
Qualquer outra informação sensível ou pessoalmente identificável
O EF Core Provider oferece suporte à Queryable Encryption por meio de uma API de modelo fluente. Você configura quais propriedades da entidade criptografar usando o método OnModelCreating() e o fornecedor lida com a criptografia automaticamente ao ler e gravar dados.
Pré-requisitos
Antes de configurar a Queryable Encryption com o EF Core Provider, certifique-se de ter o seguinte:
Um cluster do MongoDB Enterprise ou do MongoDB Atlas executando o MongoDB 7.0 ou posterior.
Acesso a um serviço de gerenciamento de chaves (KMS). Os fornecedores de KMS compatíveis incluem Amazon Web Services, Azure, Google Cloud Platform, KMIP (protocolo de interoperabilidade de gerenciamento de chaves) e fornecedores de chaves locais.
A Biblioteca compartilhada de criptografia automática ()
CRYPT_SHAREDoumongocryptdinstalada em seu ambiente. Para saber como instalar a biblioteca compartilhada, consulte Instalar um componente de análise de query na documentação do MongoDB Server .
Habilitar queryable encryption
As seções a seguir descrevem como configurar as opções de criptografia em seu contexto e marcar as propriedades da entidade para criptografia em seu modelo:
Configurar opções de criptografia
Antes de configurar qualquer contexto que use Queryable Encryption, você deve registrar o provedor de criptografia automática uma vez para seu aplicação executando o seguinte código:
MongoClientSettings.Extensions.AddAutoEncryption();
Em seguida, crie uma instância MongoOptionsExtension e encadeie os seguintes métodos antes de passar a instância para o método UseMongoDB():
WithKmsProviders()— especifica seu provedor de KMS e credenciais.WithKeyVaultNamespace()— especifica a collection usada para armazenar chaves de encriptação de dados.WithCryptProvider()— especifica a biblioteca de criptografia a ser usada e seu caminho.
O exemplo a seguir configura um provedor de KMS local para uso de desenvolvimento:
var kmsProviders = new Dictionary< string, IReadOnlyDictionary<string, object>> { { "local", new Dictionary<string, object> { { "key", localMasterKey } } } }; var keyVaultNamespace = CollectionNamespace.FromFullName( "encryption.__keyVault"); var mongoOptions = new MongoOptionsExtension() .WithConnectionString(connectionString) .WithDatabaseName("myDatabase") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")); var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoOptions);
Para usar mongocryptd em vez da biblioteca compartilhada, passe CryptProvider.Mongocryptd e o caminho para o binário mongocryptd para o método WithCryptProvider().
Aviso
Não use um provedor KMS local em produção. Sem um KMS remoto, você corre o risco de acesso não autorizado à chave mestre ou de perda permanente da chave necessária para descriptografar seus dados.
Marcar campos para criptografia
No método OnModelCreating(), chame um método de criptografia em cada propriedade que você deseja criptografar. O método escolhido controla quais tipos de query estão disponíveis nesse campo:
Método | Suporte a consultas | Notas |
|---|---|---|
| none | Criptografa o campo sem suporte de query. Use para os campos que você armazena, mas nunca filtra diretamente. |
| Igualdade ( | Não disponível para os tipos de armazenamento BSON do |
| Intervalo ( | Compatível apenas com os tipos de armazenamento BSON |
Para criptografar uma entidade de propriedade em vez de uma propriedade escalar, chame IsEncrypted(dataKeyId) no OwnedNavigationBuilder ou OwnershipBuilder retornado de OwnsOne() ou OwnsMany().
Para obter um exemplo completo que usa os métodos anteriores, consulte a seção Exemplo: criptografar dados do usuário .
Exemplo: criptografar dados do doente
A seguinte entidade Patient define o modelo de documento , com os campos SSN e DateOfBirth para criptografar:
public class Patient { public ObjectId Id { get; set; } public string Name { get; set; } = null!; public string SSN { get; set; } = null!; public DateTime DateOfBirth { get; set; } }
O HospitalContext a seguir marca esses campos para criptografia no método OnModelCreating(). SSN é criptografado sem suporte a query e DateOfBirth é criptografado com suporte a query de faixa. O construtor aceita os IDs de duas chaves de encriptação de dados, que você cria em seu cofre de chave antes de inicializar o contexto:
public class HospitalContext : DbContext { public DbSet<Patient> Patients { get; set; } = null!; private readonly Guid _ssnDataKeyId; private readonly Guid _dobDataKeyId; public HospitalContext( DbContextOptions options, Guid ssnDataKeyId, Guid dobDataKeyId) : base(options) { _ssnDataKeyId = ssnDataKeyId; _dobDataKeyId = dobDataKeyId; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Patient>(entity => { entity.ToCollection("patients"); entity.Property(p => p.SSN) .IsEncrypted(_ssnDataKeyId); entity.Property(p => p.DateOfBirth) .IsEncryptedForRange( new DateTime(1900, 1, 1), new DateTime(2100, 12, 31), _dobDataKeyId); }); } }
O código a seguir configura as opções de criptografia, instancia o HospitalContext com os IDs da chave de dados e insere e executa uma query de um documento Patient :
var mongoOptions = new MongoOptionsExtension() .WithConnectionString("<connection string URI>") .WithDatabaseName("hospitalDb") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")); using var context = new HospitalContext( new DbContextOptionsBuilder<HospitalContext>() .UseMongoDB(mongoOptions) .Options, ssnDataKeyId, dobDataKeyId); context.Database.EnsureCreated(); context.Patients.Add(new Patient { Name = "John Doe", SSN = "123-45-6789", DateOfBirth = new DateTime(1985, 6, 15) }); context.SaveChanges(); var results = context.Patients .Where(p => p.DateOfBirth > new DateTime(1980, 1, 1)) .ToList();
Suporte a esquemas do lado do servidor
Por padrão, o provedor de núcleo da EF aplica sua configuração de criptografia de campo somente ao cliente. A criptografia somente do cliente é apropriada durante o desenvolvimento, quando seu esquema de criptografia ainda pode estar desenvolvendo.
Para sistemas de produção, registre o esquema de criptografia no servidor ao criar a collection. Depois que o servidor mantém o esquema, ele impõe a criptografia independentemente da configuração do cliente , protegendo contra gravações acidentais de texto simples de clientes mal configurados. Após registrar o esquema no servidor, você não poderá alterar quais campos são criptografados sem recriar a coleção.
Para criar uma collection com um esquema do lado do servidor, passe o Model para o QueryableEncryptionSchemaGenerator.GenerateSchemas() do seu contexto. Em seguida, passe o resultado para o método CreateCollection(), conforme mostrado no exemplo a seguir:
var encryptedSchemas = QueryableEncryptionSchemaGenerator.GenerateSchemas( context.Model); using var client = new MongoClient( "<connection string URI>"); var database = client.GetDatabase("hospitalDb"); foreach (var entityType in context.Model .GetEntityTypes() .Where(e => e.IsDocumentRoot())) { var collectionName = entityType.GetCollectionName(); if (encryptedSchemas.TryGetValue( collectionName, out var schema)) { database.CreateCollection( collectionName, new CreateCollectionOptions { EncryptedFields = schema }); } } context.Database.EnsureCreated();
Depois que a coleção criptografada estiver no servidor, você poderá configurar novas instâncias de contexto para usar somente o esquema do servidor . Configure QueryableEncryptionSchemaMode.Ignore no MongoOptionsExtension, como mostrado no seguinte exemplo:
var mongoOptions = new MongoOptionsExtension() .WithConnectionString("<connection string URI>") .WithDatabaseName("hospitalDb") .WithKmsProviders(kmsProviders) .WithKeyVaultNamespace(keyVaultNamespace) .WithCryptProvider( CryptProvider.AutoEncryptSharedLibrary, Environment.GetEnvironmentVariable("CRYPT_SHARED_LIB_PATH")) .WithQueryableEncryptionSchemaMode( QueryableEncryptionSchemaMode.Ignore);
No modo Ignore, qualquer configuração IsEncrypted no método OnModelCreating() não tem efeito sobre a criptografia. O esquema do servidor controla quais campos são criptografados.
Informações adicionais
Para saber mais sobre Queryable Encryption, consulte as seções Queryable Encryption e Queryable Encryption Use Cases no manual do MongoDB Server .
Para obter detalhes completos da implementação, consulte a documentação da API do provedor principal da EF.