Dela via


Använd kryptering på klientsidan med Always Encrypted för Azure Cosmos DB

GÄLLER FÖR: NoSQL

Viktigt!

En icke-bakåtkompatibel ändring har introducerats med 1.0-versionen av våra krypteringspaket. Om du har skapat datakrypteringsnycklar och krypteringsaktiverade containrar med tidigare versioner måste du återskapa dina databaser och containrar när du har migrerat klientkoden till 1.0-paket.

Always Encrypted är en funktion som är utformad för att skydda känsliga data, till exempel kreditkortsnummer eller nationella/regionala ID-nummer (till exempel socialförsäkringsnummer i USA) som lagras i Azure Cosmos DB. Always Encrypted gör att klienter kan kryptera känsliga data i klientprogram och aldrig avslöja krypteringsnycklarna för databasen.

Always Encrypted ger krypteringsfunktioner på klientsidan till Azure Cosmos DB. Kryptering av data på klientsidan kan krävas i följande scenarier:

  • Skydda känsliga data som har specifika sekretessegenskaper: Always Encrypted gör att klienter kan kryptera känsliga data i sina program och aldrig avslöja oformaterade data eller krypteringsnycklar för Azure Cosmos DB-tjänsten.
  • Implementera åtkomstkontroll per egenskap: Eftersom krypteringen styrs med nycklar som du äger och hanterar från Azure Key Vault kan du använda åtkomstprinciper för att styra vilka känsliga egenskaper varje klient har åtkomst till.

Begrepp

Always Encrypted för Azure Cosmos DB introducerar några nya begrepp som ingår i konfigurationen av kryptering på klientsidan.

Krypteringsnycklar

Datakrypteringsnycklar

När du använder Always Encrypted krypteras data med datakrypteringsnycklar (DEK) som ska skapas i förväg. Dessa DEK:er lagras i Azure Cosmos DB-tjänsten och definieras på databasnivå, så att en DEK kan delas mellan flera containrar. Skapandet av DEK:erna görs på klientsidan med hjälp av Azure Cosmos DB SDK.

Du kan:

  • Skapa en DEK per egenskap som ska krypteras, eller
  • Använd samma DEK för att kryptera flera egenskaper.

Kundhanterade nycklar

Innan DEK:er lagras i Azure Cosmos DB omsluts de av en kundhanterad nyckel (CMK). Genom att styra omslutningen och avskrivningen av DEK:er styr CMK:er effektivt åtkomsten till de data som krypteras med motsvarande DEK:er. CMK-lagring är utformad som en utökningsbar fil med en standardimplementering som förväntar sig att de ska lagras i Azure Key Vault.

Krypteringsnycklar

Krypteringsprincip

Precis som en indexeringsprincip är en krypteringsprincip en specifikation på containernivå som beskriver hur JSON-egenskaper ska krypteras. Den här principen måste anges när containern skapas och den är oföränderlig. I den aktuella versionen kan du inte uppdatera krypteringsprincipen.

För varje egenskap som du vill kryptera definierar krypteringsprincipen:

  • Sökvägen till egenskapen i form av /property. Endast sökvägar på den översta nivån stöds för närvarande, kapslade sökvägar som /path/to/property inte stöds.
  • ID:t för DEK som ska användas vid kryptering och dekryptering av egenskapen.
  • En krypteringstyp. Det kan vara antingen randomiserat eller deterministiskt.
  • Krypteringsalgoritmen som ska användas vid kryptering av egenskapen. Den angivna algoritmen kan åsidosätta algoritmen som definieras när du skapar nyckeln om de är kompatibla.

Randomiserad kontra deterministisk kryptering

Azure Cosmos DB-tjänsten ser aldrig oformaterad text för egenskaper krypterade med Always Encrypted. Den stöder dock fortfarande vissa frågefunktioner över krypterade data, beroende på vilken krypteringstyp som används för en egenskap. Always Encrypted stöder följande två typer av kryptering:

  • Deterministisk kryptering: Den genererar alltid samma krypterade värde för ett visst oformaterat textvärde och krypteringskonfiguration. Med deterministisk kryptering kan frågor utföra likhetsfilter på krypterade egenskaper. Det kan dock göra det möjligt för angripare att gissa information om krypterade värden genom att undersöka mönster i den krypterade egenskapen. Detta gäller särskilt om det finns en liten uppsättning möjliga krypterade värden, till exempel True/False eller region nord/syd/öst/väst.

  • Randomiserad kryptering: Den använder en metod som krypterar data på ett mindre förutsägbart sätt. Randomiserad kryptering är säkrare, men förhindrar att frågor filtrerar krypterade egenskaper.

Mer information om deterministisk och randomiserad kryptering finns i Generera initieringsvektorn (IV) i Always Encrypted.

Konfigurera Azure Key Vault

Det första steget för att komma igång med Always Encrypted är att skapa dina CMK:er i Azure Key Vault:

  1. Skapa en ny Azure Key Vault-instans eller bläddra till en befintlig.
  2. Skapa en ny nyckel i avsnittet Nycklar .
  3. När nyckeln har skapats bläddrar du till den aktuella versionen och kopierar dess fullständiga nyckelidentifierare:
    https://<my-key-vault>.vault.azure.net/keys/<key>/<version>. Om du utelämnar nyckelversionen i slutet av nyckelidentifieraren används den senaste versionen av nyckeln.

Därefter måste du konfigurera hur Azure Cosmos DB SDK ska komma åt din Azure Key Vault-instans. Den här autentiseringen görs via en Microsoft Entra-identitet. Förmodligen använder du identiteten för ett Microsoft Entra-program eller en hanterad identitet som proxy mellan din klientkod och din Azure Key Vault-instans, även om alla typer av identiteter kan användas. Använd följande steg för att använda din Microsoft Entra-identitet som proxy:

  1. Från din Azure Key Vault-instans bläddrar du till avsnittet Åtkomstprinciper och lägger till en ny princip:

    1. I Nyckelbehörigheter väljer du Hämta, Lista, Packa upp nyckel, Radbryt nyckel, Verifiera och Signera.
    2. I Välj huvudnamn söker du efter din Microsoft Entra-identitet.

Skydda din CMK från oavsiktlig borttagning

För att säkerställa att du inte förlorar åtkomsten till dina krypterade data efter oavsiktlig borttagning av din CMK rekommenderar vi att du anger två egenskaper för din Azure Key Vault-instans: Mjuk borttagning och rensningsskydd.

Om du skapar en ny Azure Key Vault-instans aktiverar du dessa egenskaper när du skapar:

Skärmbild av egenskaperna för skydd mot mjuk borttagning och rensning för en ny Azure Key Vault-instans.

Om du använder en befintlig Azure Key Vault-instans kan du kontrollera att dessa egenskaper är aktiverade genom att titta på avsnittet Egenskaper på Azure-portalen. Om någon av dessa egenskaper inte är aktiverad kan du läsa avsnitten "Aktivera mjuk borttagning" och "Aktivera rensningsskydd" i någon av följande artiklar:

Initiera SDK

Kommentar

Always Encrypted för Azure Cosmos DB stöds för närvarande:

  • I .NET med paketet Microsoft.Azure.Cosmos.Encryption.
  • I Java med paketet azure.cosmos.encryption.

Om du vill använda Always Encrypted måste en instans av en KeyResolver vara kopplad till din Azure Cosmos DB SDK-instans. Den här klassen, som definieras i Azure.Security.KeyVault.Keys.Cryptography namnområdet, används för att interagera med nyckelarkivet som är värd för dina CMK:er.

Följande kodfragment använder DefaultAzureCredential klassen för att hämta Microsoft Entra-identiteten som ska användas vid åtkomst till din Azure Key Vault-instans. Du hittar exempel på hur du skapar olika typer av TokenCredential klasser här.

Kommentar

Du behöver det ytterligare Azure.Identity-paketet för att få åtkomst till klasserna TokenCredential .

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

Skapa en datakrypteringsnyckel

Innan data kan krypteras i en container måste en datakrypteringsnyckel skapas i den överordnade databasen.

Du skapar en ny datakrypteringsnyckel genom att anropa CreateClientEncryptionKeyAsync metoden och skicka:

  • En strängidentifierare som unikt identifierar nyckeln i databasen.
  • Krypteringsalgoritmen som är avsedd att användas med nyckeln. Endast en algoritm stöds för närvarande.
  • Nyckelidentifieraren för den CMK som lagras i Azure Key Vault. Den här parametern skickas i ett allmänt EncryptionKeyWrapMetadata objekt där:
    • Definierar type typen av nyckellösare (till exempel Azure Key Vault).
    • name Kan vara vilket eget namn du vill.
    • value Måste vara nyckelidentifieraren.

    Viktigt!

    När nyckeln har skapats bläddrar du till den aktuella versionen och kopierar dess fullständiga nyckelidentifierare: https://<my-key-vault>.vault.azure.net/keys/<key>/<version>. Om du utelämnar nyckelversionen i slutet av nyckelidentifieraren används den senaste versionen av nyckeln.

    • Definierar algorithm vilken algoritm som ska användas för att omsluta nyckelkrypteringsnyckeln med den kundhanterade nyckeln.
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()));

Skapa en container med krypteringsprincip

Ange krypteringsprincipen på containernivå när du skapar containern.

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

Läsa och skriva krypterade data

Hur data krypteras

När ett dokument skrivs till Azure Cosmos DB letar SDK upp krypteringsprincipen för att ta reda på vilka egenskaper som måste krypteras och hur. Resultatet av krypteringen är en base 64-sträng.

Kryptering av komplexa typer:

  • När egenskapen som ska krypteras är en JSON-matris krypteras varje post i matrisen.

  • När egenskapen som ska krypteras är ett JSON-objekt krypteras endast lövvärdena för objektet. De mellanliggande underegenskapsnamnen förblir i oformaterad text.

Läsa krypterade objekt

Ingen explicit åtgärd krävs för att dekryptera krypterade egenskaper när punktläsningar utfärdas (hämtar ett enskilt objekt med dess ID och partitionsnyckel), frågor eller läser ändringsflödet. Detta beror på att:

  • SDK:et letar upp krypteringsprincipen för att ta reda på vilka egenskaper som måste dekrypteras.
  • Resultatet av krypteringen bäddar in den ursprungliga JSON-typen av värdet.

Observera att lösningen för krypterade egenskaper och deras efterföljande dekryptering endast baseras på de resultat som returneras från dina begäranden. Om property1 den till exempel krypteras men projiceras till property2 (SELECT property1 AS property2 FROM c) identifieras den inte som en krypterad egenskap när den tas emot av SDK:t.

Filtrera frågor på krypterade egenskaper

När du skriver frågor som filtrerar på krypterade egenskaper måste en specifik metod användas för att skicka värdet för frågeparametern. Den här metoden använder följande argument:

  • Namnet på frågeparametern.
  • Värdet som ska användas i frågan.
  • Sökvägen till den krypterade egenskapen (enligt definitionen i krypteringsprincipen).

Viktigt!

Krypterade egenskaper kan endast användas i likhetsfilter (WHERE c.property = @Value). All annan användning returnerar oförutsägbara och felaktiga frågeresultat. Den här begränsningen tillämpas bättre i nästa versioner av SDK:et.

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

Läsa dokument när endast en delmängd av egenskaper kan dekrypteras

I situationer där klienten inte har åtkomst till alla CMK:er som används för att kryptera egenskaper kan endast en delmängd av egenskaper dekrypteras när data läse tillbaka. Om till property1 exempel krypterades med key1 och property2 krypterades med key2 kan ett klientprogram som bara har åtkomst till key1 fortfarande läsa data, men inte property2. I sådana fall måste du läsa dina data via SQL-frågor och projicera bort de egenskaper som klienten inte kan dekryptera: SELECT c.property1, c.property3 FROM c.

CMK-rotation

Du kanske vill "rotera" din CMK (d.v.s. använda en ny CMK i stället för den aktuella) om du misstänker att den aktuella CMK:n har komprometterats. Det är också en vanlig säkerhetspraxis att rotera CMK regelbundet. För att utföra den här rotationen behöver du bara ange nyckelidentifieraren för den nya CMK som ska användas för att omsluta en specifik DEK. Observera att den här åtgärden inte påverkar krypteringen av dina data, utan skyddet av DEK. Åtkomst till den tidigare CMK:en bör inte återkallas förrän rotationen har slutförts.

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

DEK-rotation

Att utföra en rotation av en datakrypteringsnyckel erbjuds inte som nyckelfärdig kapacitet. Detta beror på att uppdatering av en DEK kräver en genomsökning av alla containrar där den här nyckeln används och en omkryptering av alla egenskaper som krypterats med den här nyckeln. Den här åtgärden kan bara ske på klientsidan eftersom Azure Cosmos DB-tjänsten inte lagrar eller någonsin kommer åt dek:s oformaterade textvärde.

I praktiken kan en DEK-rotation göras genom att utföra en datamigrering från de berörda containrarna till nya. De nya containrarna kan skapas på exakt samma sätt som de ursprungliga. För att hjälpa dig med en sådan datamigrering kan du hitta ett fristående migreringsverktyg på GitHub.

Lägga till ytterligare krypterade egenskaper

Att lägga till ytterligare krypterade egenskaper i en befintlig krypteringsprincip stöds inte av samma skäl som beskrivs i avsnittet ovan. Den här åtgärden kräver en fullständig genomsökning av containern för att säkerställa att alla instanser av egenskaperna är korrekt krypterade, och det här är en åtgärd som bara kan ske på klientsidan. Precis som med en DEK-rotation kan du lägga till ytterligare krypterade egenskaper genom att utföra en datamigrering till en ny container med en lämplig krypteringsprincip.

Om du har flexibilitet när det gäller hur nya krypterade egenskaper kan läggas till från schemasynpunkt kan du också använda azure Cosmos DB:s schemaagnostiska karaktär. Om du använder en egenskap som definierats i krypteringsprincipen som en "egenskapsväska" kan du lägga till fler egenskaper nedan utan begränsningar. Anta till exempel att det property1 definieras i krypteringsprincipen och att du först skriver property1.property2 i dina dokument. Om du i ett senare skede behöver lägga property3 till som en krypterad egenskap kan du börja skriva property1.property3 i dina dokument och den nya egenskapen krypteras också automatiskt. Den här metoden kräver ingen datamigrering.

Nästa steg