Usar a criptografia do lado do cliente com o Always Encrypted para Azure Cosmos DB
APLICA-SE A: NoSQL
Importante
Uma alteração interruptiva foi introduzida com a versão 1.0 de nossos pacotes de criptografia. Se você criou chaves de criptografia de dados e contêineres habilitados para criptografia com versões anteriores, precisará criar novamente seus bancos de dados e contêineres após migrar o código do cliente para pacotes 1.0.
O Always Encrypted é um recurso criado para proteger dados confidenciais, como números de cartão de crédito ou de identificação nacional/regional (por exemplo, o número do seguro social nos EUA), armazenados no Azure Cosmos DB. O Always Encrypted permite que os clientes criptografem dados confidenciais dentro de aplicativos cliente e jamais revelem as chaves de criptografia ao banco de dados.
O Always Encrypted traz funcionalidades de criptografia do lado do cliente para o Azure Cosmos DB. A criptografia de dados do lado do cliente pode ser necessária nos seguintes cenários:
- Ao proteger de dados confidenciais que têm características de confidencialidade específicas: o Always Encrypted permite que os clientes criptografem dados confidenciais dentro de seus aplicativos e jamais revelem os dados de texto sem formatação ou as chaves de criptografia ao serviço do Azure Cosmos DB.
- Ao implementar o controle de acesso por propriedade: como a criptografia é controlada com as chaves que você tem e gerencia por meio do Azure Key Vault, é possível aplicar políticas de acesso para controlar a quais propriedades confidenciais cada cliente tem acesso.
Conceitos
O Always Encrypted para Azure Cosmos DB introduz alguns novos conceitos que estão envolvidos na configuração da criptografia do lado do cliente.
Chaves de criptografia
Chaves de criptografia de dados
Ao usar o Always Encrypted, os dados são criptografados com DEKs (chaves de criptografia de dados) que devem ser criados com antecedência. Esses DEKs são armazenados no serviço do Azure Cosmos DB e são definidos no nível do banco de dados, de modo que um DEK pode ser compartilhado entre vários contêineres. A criação dos DEKs é feita no lado do cliente por meio do SDK do Azure Cosmos DB.
Você pode:
- Criar um DEK para criptografar cada propriedade ou
- Usar o mesmo DEK para criptografar várias propriedades.
Observação
O limite de recursos para a Chave de Criptografia do Cliente é 20
Chaves gerenciadas pelo cliente
Antes que os DEKs sejam armazenados no Azure Cosmos DB, eles são encapsulados por uma CMK (chave gerenciada pelo cliente). Ao controlar o encapsulamento e o desencapsulamento dos DEKs, as CMKs controlam efetivamente o acesso aos dados criptografados com seus DEKs correspondentes. O armazenamento da CMK foi projetado como um extensível, com uma implementação padrão que espera que elas sejam armazenadas no Azure Key Vault.
Política de criptografia
Semelhante a uma política de indexação, a política de criptografia é uma especificação no nível do contêiner que descreve como as propriedades JSON devem ser criptografadas. Essa política deve ser fornecida quando o contêiner é criado e é imutável. Na versão atual, você não pode atualizar a política de criptografia.
Para cada propriedade que você quiser criptografar, a política de criptografia definirá:
- O caminho da propriedade na forma de
/property
. Somente caminhos de nível superior têm suporte no momento. Caminhos aninhados, como/path/to/property
, não têm suporte. - A ID do DEK a ser usada ao criptografar e descriptografar a propriedade.
- Um tipo de criptografia. Pode ser aleatória ou determinística.
- O algoritmo de criptografia a ser usado ao criptografar a propriedade. O algoritmo especificado poderá substituir o algoritmo definido ao criar a chave se eles forem compatíveis.
Criptografia aleatória vs. determinística
O serviço do Azure Cosmos DB nunca vê o texto sem formatação das propriedades criptografadas com o Always Encrypted. No entanto, ele ainda dá suporte a algumas funcionalidades de consulta sobre os dados criptografados, dependendo do tipo de criptografia usado para a propriedade em questão. O Always Encrypted dá suporte aos seguintes dois tipos de criptografia:
Criptografia determinística: sempre gera o mesmo valor criptografado para qualquer configuração de criptografia e valor de texto sem formatação fornecidos. O uso da criptografia determinística permite que as consultas apliquem filtros de igualdade nas propriedades criptografadas. No entanto, ela pode permitir que os invasores adivinhem informações sobre os valores criptografados examinando os padrões da Propriedade criptografada. Isso é especialmente verdade nos casos em que há um pequeno conjunto de possíveis valores criptografados, como True/False ou região Norte/Sul/Leste/Oeste.
Criptografia aleatória: usa um método que criptografa os dados de maneira menos previsível. A criptografia aleatória é mais segura, mas impede que as consultas filtrem as propriedades criptografadas.
Consulte Gerando o IV (vetor de inicialização) para saber mais sobre criptografia determinística e aleatória no Always Encrypted.
Configurar o Azure Key Vault
A primeira etapa para começar a usar o Always Encrypted é criar suas CMKs no Azure Key Vault:
- Crie uma instância do Azure Key Vault ou navegue até uma existente.
- Crie uma chave na seção Chaves.
- Depois que a chave for criada, navegue até a versão atual dela e copie o identificador de chave completo:
https://<my-key-vault>.vault.azure.net/keys/<key>/<version>
.
Em seguida, você precisa configurar como o SDK do Azure Cosmos DB acessará sua instância do Azure Key Vault. Essa autenticação é feita por meio de uma identidade do Microsoft Entra. Provavelmente, você usará a identidade de um aplicativo do Microsoft Entra ou uma identidade gerenciada como o proxy entre o código do cliente e a sua instância do Azure Key Vault, embora qualquer tipo de identidade possa ser usado. Use as seguintes etapas para usar sua identidade do Microsoft Entra como o proxy:
Na instância do Azure Key Vault, navegue até a seção Políticas de acesso e adicione uma nova política:
- Em permissões de chave, selecione Obter, Listar, Desencapsular chave, Encapsular chave, Verificar e Assinar.
- Em Selecionar entidade de segurança, procure sua identidade do Microsoft Entra.
Proteger a sua CMK contra a exclusão acidental
Para garantir que você não perca o acesso aos dados criptografados após a exclusão acidental da CMK, é recomendável definir duas propriedades na sua instância do Azure Key Vault: a Exclusão Reversível e a Proteção de Limpeza.
Se você criar uma nova instância do Azure Key Vault, habilite essas propriedades durante a criação:
Se estiver usando uma instância existente do Azure Key Vault, você poderá verificar se essas propriedades estão habilitadas examinando a seção Propriedades no portal do Azure. Se qualquer uma dessas propriedades não estiver habilitada, consulte as seções “Habilitar a exclusão reversível” e “Habilitar a proteção de limpeza” em um dos seguintes artigos:
Inicializar o SDK
Observação
O Always Encrypted para Azure Cosmos DB tem suporte no momento:
- No .NET com o pacote Microsoft.Azure.Cosmos.Encryption.
- No Java com o pacote azure.cosmos.encryption.
Para usar o Always Encrypted, uma instância de um KeyResolver
deve ser anexada à sua instância do SDK do Azure Cosmos DB. Essa classe, definida no namespace Azure.Security.KeyVault.Keys.Cryptography
, é usado para interagir com o armazenamento de chaves que hospeda suas CMKs.
Os snippets de código a seguir usam a classe DefaultAzureCredential
para recuperar a identidade do Microsoft Entra a ser usada ao acessar sua instância do Azure Key Vault. Você pode encontrar exemplos de criação de diferentes tipos de classes TokenCredential
aqui.
Observação
Você precisará do pacote Azure.Identity adicional para acessar as classes TokenCredential
.
var tokenCredential = new DefaultAzureCredential();
var keyResolver = new KeyResolver(tokenCredential);
var client = new CosmosClient("<connection-string>")
.WithEncryption(keyResolver, KeyEncryptionKeyResolverName.AzureKeyVault);
Criar uma chave de criptografia de dados
Antes que os dados possam ser criptografados em um contêiner, uma chave de criptografia de dados deve ser criada no banco de dados pai.
A criação de uma nova chave de criptografia de dados é feita chamando o método CreateClientEncryptionKeyAsync
e passando:
- Um identificador de cadeia de caracteres que identificará exclusivamente a chave no banco de dados.
- O algoritmo de criptografia destinado a ser usado com a chave. No momento, há suporte para apenas um algoritmo.
- O identificador de chave da CMK armazenada no Azure Key Vault. Esse parâmetro é passado em um objeto genérico
EncryptionKeyWrapMetadata
em que:- O
type
define o tipo de resolver de chave (por exemplo, Azure Key Vault). - O
name
pode ser qualquer nome amigável desejado. - O
value
deve ser o identificador de chave.
Importante
Depois que a chave for criada, navegue até sua versão atual e copie seu identificador de chave completo:
https://<my-key-vault>.vault.azure.net/keys/<key>/<version>
.- O
algorithm
define qual algoritmo deve ser usado para encapsular a chave com criptografia de chave com a chave gerenciada pelo cliente.
- O
var database = client.GetDatabase("my-database");
await database.CreateClientEncryptionKeyAsync(
"my-key",
DataEncryptionAlgorithm.AeadAes256CbcHmacSha256,
new EncryptionKeyWrapMetadata(
KeyEncryptionKeyResolverName.AzureKeyVault,
"akvKey",
"https://<my-key-vault>.vault.azure.net/keys/<key>/<version>",
EncryptionAlgorithm.RsaOaep.ToString()));
Criar um contêiner com a política de criptografia
Especifique a política de criptografia no nível do contêiner ao criar o contêiner.
var path1 = new ClientEncryptionIncludedPath
{
Path = "/property1",
ClientEncryptionKeyId = "my-key",
EncryptionType = EncryptionType.Deterministic.ToString(),
EncryptionAlgorithm = DataEncryptionAlgorithm.AeadAes256CbcHmacSha256
};
var path2 = new ClientEncryptionIncludedPath
{
Path = "/property2",
ClientEncryptionKeyId = "my-key",
EncryptionType = EncryptionType.Randomized.ToString(),
EncryptionAlgorithm = DataEncryptionAlgorithm.AeadAes256CbcHmacSha256
};
await database.DefineContainer("my-container", "/partition-key")
.WithClientEncryptionPolicy()
.WithIncludedPath(path1)
.WithIncludedPath(path2)
.Attach()
.CreateAsync();
Ler e gravar dados criptografados
Como os dados são criptografados
Sempre que um documento é gravado no Azure Cosmos DB, o SDK procura a política de criptografia para descobrir quais propriedades precisam ser criptografadas e como isso deve ser feito. O resultado da criptografia é uma cadeia de caracteres de base 64.
Criptografia de tipos complexos:
Quando a propriedade a ser criptografada é uma matriz JSON, cada entrada da matriz é criptografada.
Quando a propriedade a ser criptografada é um objeto JSON, somente os valores da folha do objeto são criptografados. Os nomes das sub-propriedades intermediárias permanecem em formato de texto sem formatação.
Ler itens criptografados
Nenhuma ação explícita é necessária para descriptografar Propriedades criptografadas ao emitir leituras pontuais (buscando um item específico pela ID e pela chave de partição), consultas ou leitura do feed de alterações. Isso ocorre porque:
- O SDK pesquisa a política de criptografia para descobrir quais propriedades precisam ser descriptografadas.
- O resultado da criptografia incorpora o tipo JSON original do valor.
Observe que a resolução das propriedades criptografadas e a descriptografia subsequente delas baseiam-se apenas nos resultados retornados das suas solicitações. Por exemplo, se property1
é criptografado, mas é projetado para property2
(SELECT property1 AS property2 FROM c
), ele não será identificado como uma propriedade criptografada ao ser recebido pelo SDK.
Filtrar consultas em propriedades criptografadas
Ao escrever consultas que filtram as propriedades criptografadas, um método específico deve ser usado para passar o valor do parâmetro de consulta. O método usa os seguintes argumentos:
- O nome do parâmetro de consulta.
- O valor a ser usado na consulta.
- O caminho da propriedade criptografada (conforme definido na política de criptografia).
Importante
As propriedades criptografadas só podem ser usadas nos filtros de igualdade (WHERE c.property = @Value
). Qualquer outro uso retornará resultados de consulta imprevisíveis e incorretos. Essa restrição será melhor imposta nas próximas versões do SDK.
var queryDefinition = container.CreateQueryDefinition(
"SELECT * FROM c where c.property1 = @Property1");
await queryDefinition.AddParameterAsync(
"@Property1",
1234,
"/property1");
Ler documentos quando apenas um subconjunto de propriedades pode ser descriptografado
Nas situações em que o cliente não tem acesso a todas as CMKs usadas para criptografar propriedades, somente um subconjunto de propriedades pode ser descriptografado quando os dados são lidos de volta. Por exemplo, se property1
foi criptografado com a chave1 e property2
foi criptografado com a chave2, um aplicativo cliente que só tem acesso à chave1 ainda pode ler dados, mas não property2
. Nesse caso, você deve ler seus dados por meio de consultas SQL e descartar as propriedades que o cliente não pode descriptografar: SELECT c.property1, c.property3 FROM c
.
Rotação de CMKs
Talvez você queira "girar" a sua CMK (ou seja, usar uma nova CMK em vez da atual) se suspeitar que a CMK atual foi comprometida. Também é uma prática de segurança comum girar a CMK regularmente. Para executar essa rotação, você só precisa fornecer o identificador de chave da nova CMK que deve ser usada para encapsular um DEK específico. Observe que essa operação não afeta a criptografia dos seus dados, mas sim a proteção do DEK. O acesso à CMK anterior não deve ser revogado até que a rotação seja concluída.
await database.RewrapClientEncryptionKeyAsync(
"my-key",
new EncryptionKeyWrapMetadata(
KeyEncryptionKeyResolverName.AzureKeyVault,
"akvKey",
"https://<my-key-vault>.vault.azure.net/keys/<new-key>/<version>",
EncryptionAlgorithm.RsaOaep.ToString()));
Rotação de DEK
A execução de uma rotação de uma chave de criptografia de dados não é oferecida como uma capacidade turnkey. Isso porque a atualização de uma DEK requer uma verificação de todos os contêineres em que essa chave é usada e uma nova criptografia de todas as propriedades criptografadas com essa chave. Essa operação só pode ocorrer no lado do cliente, pois o serviço do Azure Cosmos DB não armazena ou nunca acessa o valor de texto sem formatação da DEK.
Na prática, uma rotação de DEK pode ser feita executando uma migração de dados dos contêineres afetados para novos. Os novos contêineres podem ser criados exatamente da mesma maneira que os originais. Para ajudá-lo com essa migração de dados, você pode encontrar uma ferramenta de migração autônoma no GitHub.
Adicionando propriedades criptografadas adicionais
Não há suporte para a adição de propriedades criptografadas adicionais a uma política de criptografia existente pelos mesmos motivos explicados na seção acima. Essa operação requer uma verificação completa do contêiner para garantir que todas as instâncias das propriedades sejam criptografadas corretamente, e essa é uma operação que só pode acontecer no lado do cliente. Assim como uma rotação de DEK, a adição de propriedades criptografadas adicionais pode ser feita executando uma migração de dados para um novo contêiner com uma política de criptografia apropriada.
Se você tiver flexibilidade na maneira como novas propriedades criptografadas podem ser adicionadas do ponto de vista do esquema, você também poderá aproveitar a independência do esquema do Azure Cosmos DB. Se você usar uma propriedade definida em sua política de criptografia como um "pacote de propriedades", poderá adicionar mais propriedades abaixo sem restrição. Por exemplo, vamos imaginar que property1
está definido em sua política de criptografia e você inicialmente grava property1.property2
em seus documentos. Se, em um estágio posterior, você precisar adicionar property3
como uma propriedade criptografada, property1.property3
poderá começar a gravar em seus documentos e a nova propriedade também será criptografada automaticamente. Essa abordagem não exige uma migração de dados.
Próximas etapas
- Saiba mais sobre a chave gerenciada pelo cliente para criptografia em repouso