Udostępnij za pośrednictwem


Używanie szyfrowania po stronie klienta z funkcją Always Encrypted dla usługi Azure Cosmos DB

DOTYCZY: NoSQL

Ważne

Wprowadzono zmianę powodującą niezgodność z wersją 1.0 naszych pakietów szyfrowania. Jeśli utworzono klucze szyfrowania danych i kontenery z obsługą szyfrowania z poprzednimi wersjami, należy ponownie utworzyć bazy danych i kontenery po przeprowadzeniu migracji kodu klienta do pakietów 1.0.

Funkcja Always Encrypted jest funkcją przeznaczoną do ochrony poufnych danych, takich jak numery kart kredytowych lub numery identyfikacyjne krajowe/regionalne (na przykład numery ubezpieczenia społecznego USA), przechowywane w usłudze Azure Cosmos DB. Funkcja Always Encrypted umożliwia klientom szyfrowanie poufnych danych wewnątrz aplikacji klienckich i nigdy nie ujawnia kluczy szyfrowania w bazie danych.

Funkcja Always Encrypted umożliwia szyfrowanie po stronie klienta w usłudze Azure Cosmos DB. Szyfrowanie danych po stronie klienta może być wymagane w następujących scenariuszach:

  • Ochrona poufnych danych, które mają określone cechy poufności: funkcja Always Encrypted umożliwia klientom szyfrowanie poufnych danych wewnątrz aplikacji i nigdy nie ujawnia danych zwykłych tekstu lub kluczy szyfrowania w usłudze Azure Cosmos DB.
  • Implementowanie kontroli dostępu dla właściwości: ponieważ szyfrowanie jest kontrolowane za pomocą kluczy, które są własnością i którymi zarządzasz w usłudze Azure Key Vault, można zastosować zasady dostępu, aby kontrolować, do których poufnych właściwości ma dostęp każdy klient.

Pojęcia

Funkcja Always Encrypted dla usługi Azure Cosmos DB wprowadza pewne nowe pojęcia związane z konfiguracją szyfrowania po stronie klienta.

Klucze szyfrowania

Klucze szyfrowania danych

W przypadku korzystania z funkcji Always Encrypted dane są szyfrowane przy użyciu kluczy szyfrowania danych (DEK), które powinny zostać utworzone z wyprzedzeniem. Te zestawy SZYFROWANIA są przechowywane w usłudze Azure Cosmos DB i są definiowane na poziomie bazy danych, dzięki czemu klucz szyfrowania danych może być współużytkowany w wielu kontenerach. Tworzenie zestawów DEKs odbywa się po stronie klienta przy użyciu zestawu SDK usługi Azure Cosmos DB.

Masz następujące możliwości:

  • Tworzenie jednego klucza szyfrowania danych na właściwość w celu zaszyfrowania lub
  • Użyj tego samego klucza szyfrowania szyfrowania danych, aby zaszyfrować wiele właściwości.

Klucze zarządzane przez klienta

Przed zapisaniem zestawów SZYFROWANIA w usłudze Azure Cosmos DB są one opakowane przez klucz zarządzany przez klienta (CMK). Kontrolując zawijanie i rozpakuj pakiety DEKs, cmKs skutecznie kontrolują dostęp do danych zaszyfrowanych przy użyciu odpowiednich szyfrowania szyfrowania. Magazyn CMK jest zaprojektowany jako rozszerzalny z domyślną implementacją, która oczekuje ich przechowywania w usłudze Azure Key Vault.

Klucze szyfrowania

Zasady szyfrowania

Podobnie jak w przypadku zasad indeksowania, zasady szyfrowania są specyfikacją na poziomie kontenera opisującą sposób szyfrowania właściwości JSON. Te zasady należy podać podczas tworzenia kontenera i jest niezmienny. W bieżącej wersji nie można zaktualizować zasad szyfrowania.

Dla każdej właściwości, którą chcesz zaszyfrować, zasady szyfrowania definiują:

  • Ścieżka właściwości w postaci /property. Obecnie obsługiwane są tylko ścieżki najwyższego poziomu, takie jak ścieżki zagnieżdżone, takie jak /path/to/property nie są obsługiwane.
  • Identyfikator klucza szyfrowania danych do użycia podczas szyfrowania i odszyfrowywania właściwości.
  • Typ szyfrowania. Może to być losowe lub deterministyczne.
  • Algorytm szyfrowania używany podczas szyfrowania właściwości. Określony algorytm może zastąpić algorytm zdefiniowany podczas tworzenia klucza, jeśli są one zgodne.

Losowe a deterministyczne szyfrowanie

Usługa Azure Cosmos DB nigdy nie widzi zwykłego tekstu właściwości zaszyfrowanych za pomocą funkcji Always Encrypted. Jednak nadal obsługuje niektóre możliwości wykonywania zapytań za pośrednictwem zaszyfrowanych danych, w zależności od typu szyfrowania używanego dla właściwości. Funkcja Always Encrypted obsługuje następujące dwa typy szyfrowania:

  • Szyfrowanie deterministyczne: zawsze generuje tę samą zaszyfrowaną wartość dla dowolnej konfiguracji zwykłego tekstu i szyfrowania. Użycie szyfrowania deterministycznego umożliwia zapytaniom wykonywanie filtrów równości na zaszyfrowanych właściwościach. Może to jednak umożliwić osobom atakującym odgadnięcie informacji o zaszyfrowanych wartościach przez zbadanie wzorców we zaszyfrowanej właściwości. Jest to szczególnie istotne, jeśli istnieje niewielki zestaw możliwych zaszyfrowanych wartości, takich jak Prawda/Fałsz, lub Region Północny/Południowy/Wschód/Zachód.

  • Szyfrowanie losowe: używa metody, która szyfruje dane w mniej przewidywalny sposób. Szyfrowanie losowe jest bezpieczniejsze, ale uniemożliwia filtrowanie zapytań na zaszyfrowanych właściwościach.

Zobacz Generowanie wektora inicjowania (IV), aby dowiedzieć się więcej na temat deterministycznego i losowego szyfrowania w funkcji Always Encrypted.

Konfigurowanie usługi Azure Key Vault

Pierwszym krokiem do rozpoczęcia pracy z funkcją Always Encrypted jest utworzenie zestawów CMKs w usłudze Azure Key Vault:

  1. Utwórz nowe wystąpienie usługi Azure Key Vault lub przejdź do istniejącego.
  2. Utwórz nowy klucz w sekcji Klucze .
  3. Po utworzeniu klucza przejdź do bieżącej wersji i skopiuj jego pełny identyfikator klucza:
    https://<my-key-vault>.vault.azure.net/keys/<key>/<version>. Jeśli pominięto wersję klucza na końcu identyfikatora klucza, zostanie użyta najnowsza wersja klucza.

Następnie należy skonfigurować sposób uzyskiwania dostępu do wystąpienia usługi Azure Key Vault przez zestaw SDK usługi Azure Cosmos DB. To uwierzytelnianie odbywa się za pośrednictwem tożsamości firmy Microsoft Entra. Najprawdopodobniej użyjesz tożsamości aplikacji Microsoft Entra lub tożsamości zarządzanej jako serwera proxy między kodem klienta i wystąpieniem usługi Azure Key Vault, chociaż można użyć dowolnej tożsamości. Wykonaj następujące kroki, aby użyć tożsamości firmy Microsoft Entra jako serwera proxy:

  1. W wystąpieniu usługi Azure Key Vault przejdź do sekcji Zasady dostępu i dodaj nowe zasady:

    1. W obszarze Uprawnienia klucza wybierz pozycję Pobierz, Lista, Odpakuj klucz, Zawij klucz, Sprawdź i podpisz.
    2. W obszarze Wybierz podmiot zabezpieczeń wyszukaj tożsamość firmy Microsoft Entra.

Ochrona klucza zarządzanego przez klienta przed przypadkowym usunięciem

Aby upewnić się, że nie utracisz dostępu do zaszyfrowanych danych po przypadkowym usunięciu klucza zarządzanego przez klienta, zaleca się ustawienie dwóch właściwości w wystąpieniu usługi Azure Key Vault: usuwanie nietrwałe i czyszczenie.

Jeśli tworzysz nowe wystąpienie usługi Azure Key Vault, włącz te właściwości podczas tworzenia:

Zrzut ekranu przedstawiający właściwości usuwania nietrwałego i przeczyszczania dla nowego wystąpienia usługi Azure Key Vault.

Jeśli używasz istniejącego wystąpienia usługi Azure Key Vault, możesz sprawdzić, czy te właściwości są włączone, przeglądając sekcję Właściwości w witrynie Azure Portal. Jeśli którakolwiek z tych właściwości nie jest włączona, zobacz sekcje "Włączanie usuwania nietrwałego" i "Włączanie ochrony przed przeczyszczeniem" w jednym z następujących artykułów:

Inicjowanie zestawu SDK

Uwaga

Funkcja Always Encrypted dla usługi Azure Cosmos DB jest obecnie obsługiwana:

  • Na platformie .NET z pakietem Microsoft.Azure.Cosmos.Encryption.
  • W języku Java z pakietem azure.cosmos.encryption.

Aby można było używać funkcji Always Encrypted, wystąpienie elementu KeyResolver musi być dołączone do wystąpienia zestawu SDK usługi Azure Cosmos DB. Ta klasa zdefiniowana Azure.Security.KeyVault.Keys.Cryptography w przestrzeni nazw służy do interakcji z magazynem kluczy hostowania kluczy hostowania kluczy.

Poniższe fragmenty kodu używają DefaultAzureCredential klasy , aby pobrać tożsamość firmy Microsoft Entra do użycia podczas uzyskiwania dostępu do wystąpienia usługi Azure Key Vault. Przykłady tworzenia różnych rodzajów TokenCredential klas można znaleźć tutaj.

Uwaga

Aby uzyskać dostęp TokenCredential do klas, potrzebny będzie dodatkowy pakiet Azure.Identity.

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

Tworzenie klucza szyfrowania danych

Aby można było zaszyfrować dane w kontenerze, należy utworzyć klucz szyfrowania danych w nadrzędnej bazie danych.

Tworzenie nowego klucza szyfrowania danych odbywa się przez wywołanie CreateClientEncryptionKeyAsync metody i przekazanie:

  • Identyfikator ciągu, który będzie jednoznacznie identyfikować klucz w bazie danych.
  • Algorytm szyfrowania przeznaczony do użycia z kluczem. Obecnie obsługiwany jest tylko jeden algorytm.
  • Identyfikator klucza przechowywany w usłudze Azure Key Vault. Ten parametr jest przekazywany w obiekcie ogólnym EncryptionKeyWrapMetadata , w którym:
    • Element type definiuje typ rozpoznawania kluczy (na przykład azure Key Vault).
    • Może to być dowolna przyjazna name nazwa.
    • Musi value być identyfikatorem klucza.

    Ważne

    Po utworzeniu klucza przejdź do bieżącej wersji i skopiuj jego pełny identyfikator klucza: https://<my-key-vault>.vault.azure.net/keys/<key>/<version>. Jeśli pominięto wersję klucza na końcu identyfikatora klucza, zostanie użyta najnowsza wersja klucza.

    • Definiuje algorithm algorytm używany do opakowowania klucza szyfrowania klucza za pomocą klucza zarządzanego przez klienta.
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()));

Tworzenie kontenera z zasadami szyfrowania

Określ zasady szyfrowania na poziomie kontenera podczas tworzenia kontenera.

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

Odczytywanie i zapisywanie zaszyfrowanych danych

Jak dane są szyfrowane

Za każdym razem, gdy dokument jest zapisywany w usłudze Azure Cosmos DB, zestaw SDK wyszukuje zasady szyfrowania, aby ustalić, które właściwości muszą być szyfrowane i jak. Wynikiem szyfrowania jest podstawowy ciąg 64.

Szyfrowanie typów złożonych:

  • Gdy właściwość do zaszyfrowania jest tablicą JSON, każdy wpis tablicy jest szyfrowany.

  • Gdy właściwość do zaszyfrowania jest obiektem JSON, tylko wartości liści obiektu są szyfrowane. Pośrednie nazwy właściwości podrzędnych pozostają w postaci zwykłego tekstu.

Odczytywanie zaszyfrowanych elementów

Nie jest wymagana jawna akcja w celu odszyfrowywania zaszyfrowanych właściwości podczas wystawiania odczytów punktów (pobierania pojedynczego elementu według jego identyfikatora i klucza partycji), zapytań lub odczytywania zestawienia zmian. Jest tak, ponieważ:

  • Zestaw SDK wyszukuje zasady szyfrowania, aby ustalić, które właściwości należy odszyfrować.
  • Wynik szyfrowania osadza oryginalny typ JSON wartości.

Należy pamiętać, że rozpoznawanie zaszyfrowanych właściwości i ich kolejnych odszyfrowywania jest oparte tylko na wynikach zwracanych z żądań. Na przykład jeśli property1 jest zaszyfrowany, ale jest przewidywany do property2 (SELECT property1 AS property2 FROM c), nie zostanie zidentyfikowany jako zaszyfrowana właściwość po odebraniu przez zestaw SDK.

Filtrowanie zapytań dotyczących zaszyfrowanych właściwości

Podczas pisania zapytań filtrujących zaszyfrowane właściwości należy użyć określonej metody do przekazania wartości parametru zapytania. Ta metoda przyjmuje następujące argumenty:

  • Nazwa parametru zapytania.
  • Wartość do użycia w zapytaniu.
  • Ścieżka zaszyfrowanej właściwości (zgodnie z definicją w zasadach szyfrowania).

Ważne

Zaszyfrowane właściwości można używać tylko w filtrach równości (WHERE c.property = @Value). Każde inne użycie zwróci nieprzewidywalne i nieprawidłowe wyniki zapytania. To ograniczenie będzie lepiej wymuszane w następnych wersjach zestawu SDK.

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

Odczytywanie dokumentów, gdy można odszyfrować tylko podzbiór właściwości

W sytuacjach, gdy klient nie ma dostępu do wszystkich kluczy cmK używanych do szyfrowania właściwości, tylko podzbiór właściwości można odszyfrować, gdy dane są odczytywane z powrotem. Jeśli na przykład property1 został zaszyfrowany przy użyciu klucza1 i property2 został zaszyfrowany przy użyciu klucza2, aplikacja kliencka, która ma dostęp tylko do klucza key1, nadal może odczytywać dane, ale nie property2. W takim przypadku należy odczytywać dane za pośrednictwem zapytań SQL i projektować właściwości, których klient nie może odszyfrować: SELECT c.property1, c.property3 FROM c.

Rotacja klucza zarządzanego przez klienta

Możesz chcieć "obrócić" klucz cmk (tj. użyć nowego klucza cmK zamiast bieżącego), jeśli podejrzewasz, że bieżący klucz cmK został naruszony. Powszechną praktyką w zakresie zabezpieczeń jest również regularne obracanie klucza zarządzanego przez klienta. Aby wykonać tę rotację, musisz podać tylko identyfikator klucza nowego klucza zarządzanego przez klienta, który powinien zostać użyty do opakowania określonego klucza szyfrowania danych. Pamiętaj, że ta operacja nie ma wpływu na szyfrowanie danych, ale ochronę klucza szyfrowania danych. Dostęp do poprzedniego klucza zarządzanego klienta nie powinien zostać odwołany do momentu ukończenia rotacji.

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

Rotacja szyfrowania szyfrowania

Wykonywanie rotacji klucza szyfrowania danych nie jest oferowane jako gotowa do użycia funkcja. Wynika to z faktu, że aktualizacja klucza szyfrowania danych wymaga skanowania wszystkich kontenerów, w których ten klucz jest używany, oraz ponownego szyfrowania wszystkich właściwości zaszyfrowanych za pomocą tego klucza. Ta operacja może wystąpić tylko po stronie klienta, ponieważ usługa Azure Cosmos DB nie przechowuje ani nigdy nie uzyskuje dostępu do wartości zwykłego tekstu klucza szyfrowania danych.

W praktyce rotacja klucza szyfrowania danych może odbywać się przez przeprowadzenie migracji danych z kontenerów, których to dotyczy, do nowych. Nowe kontenery można utworzyć dokładnie tak samo jak oryginalne. Aby ułatwić migrację danych, możesz znaleźć autonomiczne narzędzie do migracji w usłudze GitHub.

Dodawanie dodatkowych zaszyfrowanych właściwości

Dodanie dodatkowych zaszyfrowanych właściwości do istniejących zasad szyfrowania nie jest obsługiwane z tych samych powodów opisanych w powyższej sekcji. Ta operacja wymaga pełnego skanowania kontenera w celu upewnienia się, że wszystkie wystąpienia właściwości są prawidłowo zaszyfrowane i jest to operacja, która może odbywać się tylko po stronie klienta. Podobnie jak rotacja klucza szyfrowania danych, dodanie dodatkowych zaszyfrowanych właściwości można wykonać przez przeprowadzenie migracji danych do nowego kontenera z odpowiednimi zasadami szyfrowania.

Jeśli masz elastyczność w sposobie dodawania nowych zaszyfrowanych właściwości z punktu widzenia schematu, możesz również wykorzystać niezależny od schematu charakter usługi Azure Cosmos DB. Jeśli używasz właściwości zdefiniowanej w zasadach szyfrowania jako "torba właściwości", możesz dodać więcej właściwości poniżej bez ograniczeń. Załóżmy na przykład, że property1 jest ona zdefiniowana w zasadach szyfrowania i początkowo zapisujesz property1.property2 je w dokumentach. Jeśli na późniejszym etapie musisz dodać property3 jako zaszyfrowaną właściwość, możesz rozpocząć pisanie property1.property3 w dokumentach, a nowa właściwość również zostanie zaszyfrowana. Takie podejście nie wymaga migracji danych.

Następne kroki