Condividi tramite


Usare la crittografia lato client con Always Encrypted per Azure Cosmos DB

SI APPLICA A: NoSQL

Importante

È stata introdotta una modifica di rilievo con la versione 1.0 dei pacchetti di crittografia. Se sono state create chiavi di crittografia dei dati e contenitori abilitati per la crittografia con versioni precedenti, sarà necessario ricreare i database e i contenitori dopo la migrazione del codice client a pacchetti 1.0.

Always Encrypted è una funzionalità progettata per proteggere i dati sensibili, ad esempio numeri di carta di credito o numeri di identificazione nazionali/regionali (ad esempio, numeri di previdenza sociale degli Stati Uniti), archiviati in Azure Cosmos DB. Always Encrypted consente ai client di crittografare i dati sensibili all'interno delle applicazioni client e di non rivelare mai le chiavi di crittografia al database.

Always Encrypted offre funzionalità di crittografia lato client per Azure Cosmos DB. La crittografia del lato client dei dati può essere necessaria negli scenari seguenti:

  • Protezione dei dati sensibili con caratteristiche di riservatezza specifiche: Always Encrypted consente ai client di crittografare i dati sensibili all'interno delle applicazioni e non rivelare mai i dati di testo normale o le chiavi di crittografia al servizio Azure Cosmos DB.
  • Implementazione del controllo di accesso per proprietà: poiché la crittografia è controllata con le chiavi di cui si è proprietari e gestiti da Azure Key Vault, è possibile applicare i criteri di accesso per controllare le proprietà sensibili a cui ogni client ha accesso.

Concetti

Always Encrypted per Azure Cosmos DB introduce alcuni nuovi concetti coinvolti nella configurazione della crittografia lato client.

Chiavi di crittografia

Chiavi di crittografia dei dati

Quando si usa Always Encrypted, i dati vengono crittografati con chiavi DEK (Data Encryption Key) che devono essere create in anticipo. Questi DEK vengono archiviati nel servizio Azure Cosmos DB e sono definiti a livello di database, in modo che una chiave DEK possa essere condivisa tra più contenitori. La creazione dei DEK viene eseguita sul lato client usando Azure Cosmos DB SDK.

È possibile:

  • Creare una chiave DEK per proprietà per crittografare o
  • Usare la stessa chiave DEK per crittografare più proprietà.

Chiavi gestite dal cliente

Prima che i DEK vengano archiviati in Azure Cosmos DB, vengono inclusi incapsulati da una chiave gestita dal cliente (CMK). Controllando il wrapping e l'annullamento del wrapping dei DEK, i cmk controllano in modo efficace l'accesso ai dati crittografati con i dek corrispondenti. L'archiviazione della chiave gestita dal cliente è progettata come estendibile, con un'implementazione predefinita che prevede l'archiviazione in Azure Key Vault.

Chiavi di crittografia

Criteri di crittografia

Analogamente a un criterio di indicizzazione, un criterio di crittografia è una specifica a livello di contenitore che descrive come crittografare le proprietà JSON. Questo criterio deve essere fornito quando viene creato il contenitore ed è non modificabile. Nella versione corrente non è possibile aggiornare i criteri di crittografia.

Per ogni proprietà che si vuole crittografare i criteri di crittografia consentono di definire:

  • Percorso della proprietà sotto forma di /property. Attualmente sono supportati solo i percorsi di primo livello, i percorsi annidati, /path/to/property ad esempio non sono supportati.
  • ID della chiave DEK da utilizzare per crittografare e decrittografare la proprietà.
  • Un tipo di crittografia. Può essere casuale o deterministica.
  • L'algoritmo di crittografia da usare per la crittografia della proprietà. L'algoritmo specificato può eseguire l'override dell'algoritmo definito durante la creazione della chiave, se sono compatibili.

Crittografia casuale e deterministica

Il servizio Azure Cosmos DB non vede mai il testo normale delle proprietà crittografate con Always Encrypted. Tuttavia, supporta ancora alcune funzionalità di query sui dati crittografati, a seconda del tipo di crittografia usato per una proprietà. Always Encrypted supporta i due tipi di crittografia seguenti:

  • Crittografia deterministica: genera sempre lo stesso valore crittografato per qualsiasi valore di testo normale e configurazione di crittografia specificati. L'uso della crittografia deterministica consente alle query di eseguire filtri di uguaglianza sulle proprietà crittografate. Tuttavia, può consentire agli utenti malintenzionati di indovinare le informazioni sui valori crittografati esaminando i modelli nella proprietà crittografata. Questa vulnerabilità aumenta quando è presente un piccolo set di possibili valori crittografati, ad esempio True/False o area geografica Nord/Sud/Est/Ovest.

  • Crittografia casuale: usa un metodo di crittografia dei dati meno prevedibile. La crittografia casuale è più sicura, ma impedisce alle query di applicare filtri sulle proprietà crittografate.

Vedere Generazione del vettore di inizializzazione (IV) per altre informazioni sulla crittografia deterministica e casuale in Always Encrypted.

Configurare Azure Key Vault

Il primo passaggio per iniziare a usare Always Encrypted consiste nel creare i cmk in Azure Key Vault:

  1. Creare una nuova istanza di Azure Key Vault o passare a una istanza esistente.
  2. Creare una nuova chiave nella sezione Chiavi .
  3. Dopo aver creato la chiave, passare alla versione corrente e copiare l'identificatore completo della chiave:
    https://<my-key-vault>.vault.azure.net/keys/<key>/<version>. Se si omette la versione della chiave alla fine dell'identificatore di chiave, viene usata la versione più recente della chiave.

Successivamente, è necessario configurare il modo in cui Azure Cosmos DB SDK accederà all'istanza di Azure Key Vault. Questa autenticazione viene eseguita tramite un'identità Microsoft Entra. Molto probabilmente si userà l'identità di un'applicazione Microsoft Entra o un'identità gestita come proxy tra il codice client e l'istanza di Azure Key Vault, anche se è possibile usare qualsiasi tipo di identità. Usare la procedura seguente per usare l'identità di Microsoft Entra come proxy:

  1. Dall'istanza di Azure Key Vault passare alla sezione Criteri di accesso e aggiungere un nuovo criterio:

    1. In Autorizzazioni chiave selezionare Get, List, Unwrap Key, Wrap Key, Verify and Sign(Ottieni, Elenco, Annulla il wrapping della chiave), Verify and Sign (Esegui il wrapping della chiave), Verify and Sign (Verifica e firma).
    2. In Select principal (Seleziona entità) cercare l'identità di Microsoft Entra.

Proteggere la chiave gestita dal cliente dall'eliminazione accidentale

Per assicurarsi di non perdere l'accesso ai dati crittografati dopo l'eliminazione accidentale della chiave gestita dal cliente, è consigliabile impostare due proprietà nell'istanza di Azure Key Vault: Eliminazione temporanea e Protezione dall'eliminazione.

Se si crea una nuova istanza di Azure Key Vault, abilitare queste proprietà durante la creazione:

Screenshot delle proprietà di eliminazione temporanea e eliminazione della protezione per una nuova istanza di Azure Key Vault.

Se si usa un'istanza di Azure Key Vault esistente, è possibile verificare che queste proprietà siano abilitate nella sezione Proprietà del portale di Azure. Se una di queste proprietà non è abilitata, vedere le sezioni "Abilitazione della funzione di eliminazione temporanea" e "Abilitazione del flag di protezione dall'eliminazione" in uno degli articoli seguenti:

Inizializzare l'SDK

Nota

Always Encrypted per Azure Cosmos DB è attualmente supportato:

  • In .NET con il pacchetto Microsoft.Azure.Cosmos.Encryption.
  • In Java con il pacchetto azure.cosmos.encryption.

Per usare Always Encrypted, è necessario collegare un'istanza di a KeyResolver un'istanza di Azure Cosmos DB SDK. Questa classe, definita nello spazio dei Azure.Security.KeyVault.Keys.Cryptography nomi , viene usata per interagire con l'archivio chiavi che ospita i cmk.

I frammenti di codice seguenti usano la DefaultAzureCredential classe per recuperare l'identità di Microsoft Entra da usare per l'accesso all'istanza di Azure Key Vault. Qui sono disponibili esempi di creazione di diversi tipi di TokenCredential classi.

Nota

Per accedere TokenCredential alle classi, sarà necessario il pacchetto Azure.Identity aggiuntivo.

var tokenCredential = new DefaultAzureCredential();
var keyResolver = new KeyResolver(tokenCredential);
var client = new CosmosClient("<connection-string>")
    .WithEncryption(keyResolver, KeyEncryptionKeyResolverName.AzureKeyVault);

Creare una chiave di crittografia dei dati (DEK)

Prima che i dati possano essere crittografati in un contenitore, è necessario creare una chiave di crittografia dei dati nel database padre.

La creazione di una nuova chiave di crittografia dei dati viene eseguita chiamando il CreateClientEncryptionKeyAsync metodo e passando:

  • Un identificatore stringa che identifica in modo univoco la chiave nel database.
  • L'algoritmo di crittografia da usare con la chiave. Attualmente è supportato un solo algoritmo.
  • Identificatore della chiave della chiave gestita archiviata in Azure Key Vault. Questo parametro viene passato in un oggetto generico EncryptionKeyWrapMetadata in cui:
    • type definisce il tipo di sistema di risoluzione delle chiavi, ad esempio Azure Key Vault.
    • Può name essere qualsiasi nome descrittivo desiderato.
    • Deve value essere l'identificatore di chiave.

    Importante

    Dopo aver creato la chiave, passare alla versione corrente e copiare l'identificatore chiave completo: https://<my-key-vault>.vault.azure.net/keys/<key>/<version>. Se si omette la versione della chiave alla fine dell'identificatore di chiave, viene usata la versione più recente della chiave.

    • algorithm Definisce quale algoritmo deve essere usato per eseguire il wrapping della chiave di crittografia della chiave con la chiave gestita dal 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()));

Creare un contenitore con i criteri di crittografia

Specificare i criteri di crittografia a livello di contenitore durante la creazione del contenitore.

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();

Leggere e scrivere dati crittografati

Modalità di crittografia dei dati

Ogni volta che un documento viene scritto in Azure Cosmos DB, l'SDK cerca i criteri di crittografia per determinare quali proprietà devono essere crittografate e come. Il risultato della crittografia è una stringa di base 64.

Crittografia di tipi complessi:

  • Quando la proprietà da crittografare è una matrice JSON, ogni voce della matrice viene crittografata.

  • Quando la proprietà da crittografare è un oggetto JSON, vengono crittografati solo i valori foglia dell'oggetto. I nomi intermedi delle sottoproprietà rimangono in formato testo normale.

Leggere gli elementi crittografati

Non è necessaria alcuna azione esplicita per decrittografare le proprietà crittografate durante l'emissione di letture di punti (recupero di un singolo elemento in base all'ID e alla chiave di partizione), alle query o alla lettura del feed di modifiche. Motivo:

  • L'SDK cerca i criteri di crittografia per determinare quali proprietà devono essere decrittografate.
  • Il risultato della crittografia incorpora il tipo JSON originale del valore.

Si noti che la risoluzione delle proprietà crittografate e la relativa decrittografia successiva sono basate solo sui risultati restituiti dalle richieste. Ad esempio, se property1 è crittografato ma proiettato in property2 (SELECT property1 AS property2 FROM c), non verrà identificato come una proprietà crittografata quando ricevuto dall'SDK.

Filtrare le query sulle proprietà crittografate

Quando si scrivono query che filtrano le proprietà crittografate, è necessario usare un metodo specifico per passare il valore del parametro di query. Questo metodo accetta gli argomenti seguenti:

  • Nome del parametro della query.
  • Valore da usare nella query.
  • Percorso della proprietà crittografata definito nei criteri di crittografia.

Importante

Le proprietà crittografate possono essere usate solo nei filtri di uguaglianza (WHERE c.property = @Value). Con qualsiasi altro utilizzo verranno restituiti risultati di query imprevedibili e errati. Questo vincolo verrà applicato meglio nelle versioni successive dell'SDK.

var queryDefinition = container.CreateQueryDefinition(
    "SELECT * FROM c where c.property1 = @Property1");
await queryDefinition.AddParameterAsync(
    "@Property1",
    1234,
    "/property1");

Lettura di documenti quando è possibile decrittografare solo un subset di proprietà

In situazioni in cui il client non ha accesso a tutte le chiavi cmk usate per crittografare le proprietà, è possibile decrittografare solo un subset di proprietà quando i dati vengono letti di nuovo. Ad esempio, se property1 è stato crittografato con key1 ed property2 è stato crittografato con key2, un'applicazione client che ha accesso solo a key1 può comunque leggere i dati, ma non property2. In questo caso, è necessario leggere i dati tramite query SQL e proiettare le proprietà che il client non può decrittografare: SELECT c.property1, c.property3 FROM c.

Rotazione della chiave gestita dal cliente

Se si sospetta che la chiave cmk corrente sia stata compromessa, è consigliabile "ruotare" la chiave gestita( ovvero usare una nuova chiave cmk anziché quella corrente). È anche una pratica di sicurezza comune per ruotare regolarmente la chiave gestita dal cliente. Per eseguire questa rotazione, è necessario specificare solo l'identificatore della chiave del nuovo cmk da usare per eseguire il wrapping di una chiave DEK specifica. Si noti che questa operazione non influisce sulla crittografia dei dati, ma sulla protezione della chiave dek. L'accesso alla chiave gestita precedente non deve essere revocato fino al completamento della rotazione.

await database.RewrapClientEncryptionKeyAsync(
    "my-key",
    new EncryptionKeyWrapMetadata(
        KeyEncryptionKeyResolverName.AzureKeyVault,
        "akvKey",
        "https://<my-key-vault>.vault.azure.net/keys/<new-key>/<version>",
        EncryptionAlgorithm.RsaOaep.ToString()));

Rotazione DEK

L'esecuzione di una rotazione di una chiave di crittografia dei dati non è disponibile come funzionalità chiavi in mano. Ciò è dovuto al fatto che l'aggiornamento di una chiave DEK richiede un'analisi di tutti i contenitori in cui viene usata questa chiave e una ricrittografazione di tutte le proprietà crittografate con questa chiave. Questa operazione può verificarsi solo sul lato client perché il servizio Azure Cosmos DB non archivia o accede mai al valore di testo normale della chiave DEK.

In pratica, è possibile eseguire una rotazione DEK eseguendo una migrazione dei dati dai contenitori interessati a quelli nuovi. I nuovi contenitori possono essere creati esattamente come quelli originali. Per semplificare la migrazione di questi dati, è possibile trovare uno strumento di migrazione autonomo in GitHub.

Aggiunta di proprietà crittografate aggiuntive

L'aggiunta di proprietà crittografate aggiuntive a un criterio di crittografia esistente non è supportata per gli stessi motivi illustrati nella sezione precedente. Questa operazione richiede un'analisi completa del contenitore per garantire che tutte le istanze delle proprietà siano crittografate correttamente e si tratta di un'operazione che può verificarsi solo sul lato client. Proprio come una rotazione DEK, l'aggiunta di proprietà crittografate aggiuntive può essere eseguita eseguendo una migrazione dei dati a un nuovo contenitore con criteri di crittografia appropriati.

Se si ha flessibilità nel modo in cui è possibile aggiungere nuove proprietà crittografate dal punto di vista dello schema, è anche possibile sfruttare la natura indipendente dallo schema di Azure Cosmos DB. Se si usa una proprietà definita nei criteri di crittografia come "contenitore delle proprietà", è possibile aggiungere altre proprietà di seguito senza alcun vincolo. Si supponga, ad esempio, che property1 sia definito nei criteri di crittografia e che vengano scritti inizialmente property1.property2 nei documenti. Se, in un secondo momento, è necessario aggiungere property3 come proprietà crittografata, è possibile iniziare a scrivere property1.property3 nei documenti e la nuova proprietà verrà crittografata automaticamente. Questo approccio non richiede alcuna migrazione dei dati.

Passaggi successivi