Utilizar encriptação do lado do cliente com Always Encrypted para Azure Cosmos DB
APLICA-SE A: NoSQL
Importante
Uma grande mudança 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á recriar seus bancos de dados e contêineres depois de migrar o código do cliente para pacotes 1.0.
O Always Encrypted é um recurso projetado para proteger dados confidenciais, como números de cartão de crédito ou números de identificação nacionais/regionais (por exemplo, números de segurança social dos EUA), armazenados no Azure Cosmos DB. O Always Encrypted permite que os clientes criptografem dados confidenciais dentro de aplicativos cliente e nunca revelem as chaves de criptografia para o banco de dados.
O Always Encrypted traz recursos de criptografia do lado do cliente para o Azure Cosmos DB. A criptografia do lado do cliente de dados pode ser necessária nos seguintes cenários:
- Proteção de dados confidenciais com características específicas de confidencialidade: o Always Encrypted permite que os clientes criptografem dados confidenciais dentro de seus aplicativos e nunca revelem os dados de texto sem formatação ou as chaves de criptografia para o serviço Azure Cosmos DB.
- Implementando o controle de acesso por propriedade: como a criptografia é controlada com chaves que você possui e gerencia a partir do Cofre de Chaves do Azure, você pode aplicar políticas de acesso para controlar a quais propriedades confidenciais cada cliente tem acesso.
Conceitos
Always Encrypted for Azure Cosmos DB introduz alguns novos conceitos envolvidos na configuração da criptografia do lado do cliente.
Chaves de encriptação
Chaves de encriptação de dados
Ao usar o Always Encrypted, os dados são criptografados com chaves de criptografia de dados (DEK) que devem ser criadas antecipadamente. Essas DEKs são armazenadas no serviço Azure Cosmos DB e são definidas no nível do banco de dados, para que uma DEK possa ser compartilhada entre vários contêineres. A criação das DEKs é feita no lado do cliente usando o SDK do Azure Cosmos DB.
Pode:
- Crie uma DEK por propriedade para criptografar ou
- Use a mesma DEK para criptografar várias propriedades.
Chaves geridas pelo cliente
Antes de serem armazenadas no Azure Cosmos DB, as DEKs são encapsuladas por uma chave gerenciada pelo cliente (CMK). Ao controlar o empacotamento e desempacotamento de DEKs, as CMKs controlam efetivamente o acesso aos dados criptografados com suas DEKs correspondentes. O armazenamento CMK foi projetado como um extensível, com uma implementação padrão que espera que eles sejam armazenados no Cofre da Chave do Azure.
Política de encriptação
Semelhante a uma política de indexação, uma 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, não é possível atualizar a política de criptografia.
Para cada propriedade que você deseja criptografar, a política de criptografia define:
- O caminho da propriedade na forma de
/property
. Atualmente, apenas caminhos de nível superior são suportados, caminhos aninhados como/path/to/property
não são suportados. - O ID do DEK a ser usado ao criptografar e descriptografar a propriedade.
- Um tipo de criptografia. Pode ser randomizado ou determinístico.
- O algoritmo de criptografia a ser usado ao criptografar a propriedade. O algoritmo especificado pode substituir o algoritmo definido ao criar a chave se eles forem compatíveis.
Encriptação aleatória vs. determinística
O serviço Azure Cosmos DB nunca vê o texto sem formatação de propriedades criptografadas com Always Encrypted. No entanto, ele ainda suporta alguns recursos de consulta sobre os dados criptografados, dependendo do tipo de criptografia usado para uma propriedade. O Always Encrypted suporta os seguintes dois tipos de encriptação:
Encriptação determinística: gera sempre o mesmo valor encriptado para qualquer valor de texto simples e configuração de encriptação. O uso de criptografia determinística permite que as consultas executem filtros de igualdade em propriedades criptografadas. No entanto, ele pode permitir que os invasores adivinhem informações sobre valores criptografados examinando padrões na propriedade criptografada. Isso é especialmente verdadeiro se houver um pequeno conjunto de possíveis valores criptografados, como True/False ou a região Norte/Sul/Leste/Oeste.
Criptografia aleatória: usa um método que criptografa dados de maneira menos previsível. A criptografia aleatória é mais segura, mas impede que as consultas sejam filtradas em propriedades criptografadas.
Consulte Gerando o vetor de inicialização (IV) para saber mais sobre criptografia determinística e aleatória em 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 nova instância do Azure Key Vault ou navegue até uma existente.
- Crie uma nova chave na seção Chaves .
- 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>
. Se você omitir a versão da chave no final do identificador de chave, a versão mais recente da chave será usada.
Em seguida, você precisa configurar como o SDK do Azure Cosmos DB acessará sua instância do Azure Key Vault. Esta autenticação é feita através de uma identidade Microsoft Entra. Muito provavelmente, você usará a identidade de um aplicativo Microsoft Entra ou uma identidade gerenciada como o proxy entre o código do cliente e a instância do Cofre da Chave do Azure, embora qualquer tipo de identidade possa ser usado. Use as seguintes etapas para usar sua identidade do Microsoft Entra como proxy:
Na sua 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, Desembrulhar chave, Chave de encapsulamento, Verificar e Assinar.
- Em Selecionar entidade de segurança, procure a sua identidade do Microsoft Entra.
Proteja sua CMK contra 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 instância do Azure Key Vault: Soft Delete e Purge Protection.
Se você criar uma nova instância do Azure Key Vault, habilite estas propriedades durante a criação:
Se estiver a utilizar uma instância existente do Azure Key Vault, pode verificar se estas propriedades estão ativadas consultando a secção Propriedades no portal do Azure. Se alguma dessas propriedades não estiver habilitada, consulte as seções "Habilitando exclusão suave" e "Habilitando a proteção contra limpeza" em um dos seguintes artigos:
Inicializar o SDK
Nota
O Always Encrypted for Azure Cosmos DB é atualmente suportado:
Para usar Always Encrypted, uma instância de um KeyResolver
deve ser anexada à sua instância do SDK do Azure Cosmos DB. Essa classe, definida no Azure.Security.KeyVault.Keys.Cryptography
namespace, é usada para interagir com o armazenamento de chaves que hospeda suas CMKs.
Os trechos a seguir usam a DefaultAzureCredential
classe 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 TokenCredential
classes aqui.
Nota
Você precisará do pacote Azure.Identity adicional para acessar as TokenCredential
classes.
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 CreateClientEncryptionKeyAsync
método e passando:
- Um identificador de cadeia de caracteres que identificará exclusivamente a chave no banco de dados.
- O algoritmo de encriptação destinado a ser usado com a chave. Atualmente, apenas um algoritmo é suportado.
- O identificador de chave da CMK armazenada no Cofre da Chave do Azure. Este parâmetro é passado em um objeto genérico
EncryptionKeyWrapMetadata
onde:- O
type
define o tipo de resolvedor de chaves (por exemplo, Azure Key Vault). - O
name
pode ser qualquer nome amigável que você quiser. - 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>
. Se você omitir a versão da chave no final do identificador de chave, a versão mais recente da chave será usada.- O
algorithm
define qual algoritmo deve ser usado para envolver a chave de 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 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 escrever dados encriptados
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. O resultado da criptografia é uma cadeia de caracteres base 64.
Encriptação 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 folha do objeto são criptografados. Os nomes de subpropriedades 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 (buscar um único item por sua ID e chave de partição), consultas ou ler o feed de alterações. Isto acontece porque:
- O SDK procura a política de criptografia para descobrir quais propriedades precisam ser descriptografadas.
- O resultado da criptografia incorpora o tipo JSON original do valor.
Note que a resolução das propriedades encriptadas e a sua desencriptação subsequente são baseadas apenas nos resultados devolvidos dos seus pedidos. Por exemplo, se property1
estiver criptografado, mas for projetado em property2
(SELECT property1 AS property2 FROM c
), ele não será identificado como uma propriedade criptografada quando recebido pelo SDK.
Filtrar consultas em propriedades criptografadas
Ao escrever consultas que filtram propriedades criptografadas, um método específico deve ser usado para passar o valor do parâmetro de consulta. Este método utiliza 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 em filtros de igualdade (WHERE c.property = @Value
). Qualquer outro uso retornará resultados de consulta imprevisíveis e errados. Essa restrição será melhor aplicada nas próximas versões do SDK.
var queryDefinition = container.CreateQueryDefinition(
"SELECT * FROM c where c.property1 = @Property1");
await queryDefinition.AddParameterAsync(
"@Property1",
1234,
"/property1");
Leitura de documentos quando apenas um subconjunto de propriedades pode ser desencriptado
Em situações em que o cliente não tem acesso a toda a CMK usada para criptografar propriedades, apenas um subconjunto de propriedades pode ser descriptografado quando os dados são lidos de volta. Por exemplo, se property1
foi criptografado com key1 e property2
foi criptografado com key2, um aplicativo cliente que só tem acesso a key1 ainda pode ler dados, mas não property2
. Nesse caso, você deve ler seus dados por meio de consultas SQL e projetar as propriedades que o cliente não pode descriptografar: SELECT c.property1, c.property3 FROM c
.
Rotação CMK
Você pode querer "girar" 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 alternar 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 uma DEK específica. Observe que essa operação não afeta a criptografia de seus dados, mas a proteção da DEK. O acesso à CMK anterior não deve ser revogado até que a rotação esteja 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 DEK
Executar uma rotação de uma chave de criptografia de dados não é oferecido como um recurso turnkey. Isso ocorre porque a atualização de uma DEK requer uma verificação de todos os contêineres onde essa chave é usada e uma nova criptografia de todas as propriedades criptografadas com essa chave. Essa operação só pode acontecer do lado do cliente, pois o serviço Azure Cosmos DB não armazena ou nunca acessa o valor de texto sem formatação da DEK.
Na prática, uma rotação DEK pode ser feita realizando uma migração de dados dos contêineres impactados para novos. Os novos contentores podem ser criados exatamente da mesma forma que os originais. Para ajudá-lo com essa migração de dados, você pode encontrar uma ferramenta de migração independente no GitHub.
Adicionando propriedades criptografadas adicionais
A adição de propriedades criptografadas adicionais a uma política de criptografia existente não é suportada 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 do lado do cliente. Assim como uma rotação 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, também poderá aproveitar a natureza agnóstica 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ções. Por exemplo, vamos imaginar que isso property1
está definido em sua política de criptografia e você escreve property1.property2
inicialmente em seus documentos. Se, em um estágio posterior, você precisar adicionar property3
como uma propriedade criptografada, você pode começar a escrever property1.property3
em seus documentos e a nova propriedade também será automaticamente criptografada. Essa abordagem não requer nenhuma migração de dados.
Próximos passos
- Saiba mais sobre chaves gerenciadas pelo cliente para criptografia em repouso