Partilhar via


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.

Chaves de encriptação

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:

  1. Crie uma nova 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é 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:

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

    1. Em Permissões de chave, selecione Obter, Listar, Desembrulhar chave, Chave de encapsulamento, Verificar e Assinar.
    2. 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:

Captura de ecrã das propriedades de proteção de eliminação suave e limpeza para uma nova instância do Azure Key Vault.

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:

  • No .NET com o pacote Microsoft.Azure.Cosmos.Encryption.
  • Em Java com o pacote azure.cosmos.encryption.

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.
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