Compartilhar via


Usar a criptografia do lado do cliente com o Always Encrypted para Azure Cosmos DB

APLICA-SE A: NoSQL

Importante

Uma alteração disruptiva foi implementada na 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 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:

  • Proteger 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 nunca revelem os dados de texto sem formatação ou as chaves de criptografia para o serviço do Azure Cosmos DB.
  • Implementando o controle de acesso por propriedade: como a criptografia é controlada com chaves que você possui e gerencia do Azure Key Vault, você pode 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 uma 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 a embalagem e o desembalagem 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.

Chaves de criptografia

Política de criptografia

Semelhante a uma política de indexação, uma política de criptografia é uma especificação de nível de 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 no formato /property. Somente caminhos de nível superior têm suporte no momento. Caminhos aninhados, como /path/to/property, não têm suporte.
  • O ID do DEK a ser usado 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 pode 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 em claro 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: Ele sempre gera o mesmo valor criptografado para qualquer determinado valor de texto sem formatação e configuração de criptografia. 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: Ele usa um método que criptografa 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 Azure Key Vault

A primeira etapa para começar a usar o Always Encrypted é criar suas CMKs no Azure Key Vault:

  1. Crie uma instância do Azure Key Vault ou navegue até uma existente.
  2. Crie uma nova chave na seção Chaves .
  3. 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 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:

  1. Na instância do Azure Key Vault, navegue até a seção políticas do Access e adicione uma nova política:

    1. Em Permissões de chave, selecione Obter, Listar, Desembrulhar chave, Embrulhar chave, Verificar e Assinar.
    2. Em Selecionar principal, procure sua identidade Microsoft Entra.

Proteger a sua CMK contra a exclusão acidental

Para garantir que você não perca o acesso aos seus dados criptografados após a exclusão acidental do seu CMK, é recomendável definir duas propriedades na sua instância do Azure Key Vault: Exclusão reversível e Proteção contra limpeza.

Se você criar uma nova instância do Azure Key Vault, habilite essas propriedades durante a criação:

Captura de tela das propriedades de exclusão suave e proteção contra purga para uma nova instância do Azure Key Vault.

Se você estiver usando uma instância existente do Azure Key Vault, poderá verificar se essas propriedades estão habilitadas examinando a seção Propriedades no portal do Azure. Se uma dessas propriedades não estiver habilitada, veja as seções “Habilitar exclusão reversível” e “Habilitar 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:

Para usar o Always Encrypted, é necessário anexar uma instância de KeyResolver à sua instância do SDK do Azure Cosmos DB. Essa classe, definida no namespace Azure.Security.KeyVault.Keys.Cryptography, é usada 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 TokenCredential classes aqui.

Observação

Você precisará do pacote adicional do Azure.Identity 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 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 do CMK armazenado 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.
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 (recuperando um item específico pelo ID e pela chave de partição), realizar consultas ou ler o 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

Em situações em que o cliente não tem acesso a todo o CMK usado para criptografar propriedades, apenas um subconjunto de propriedades pode ser descriptografado quando os dados são lidos novamente. 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 projetar as propriedades que o cliente não consegue decifrar: 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 rotacionar 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 dos seus dados, mas sim a proteção do DEK. O acesso ao 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 um recurso pronto para uso. 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 acontecer no lado do cliente, pois o serviço do Azure Cosmos DB não armazena nem acessa o valor de texto sem formatação do 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 em termos de como novas propriedades criptografadas podem ser adicionadas em termos de esquema, você também poderá aproveitar a natureza independente de 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, você poderá começar a escrever property1.property3 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